Fix OAuth

This commit is contained in:
Mawoka
2026-06-24 18:09:00 +02:00
parent a9b9aa6e96
commit 0f5a581ead
3 changed files with 100 additions and 66 deletions
+41 -27
View File
@@ -6,15 +6,15 @@
import uuid
import asyncpg
from fastapi import APIRouter, Request, HTTPException, Response
from classquiz.config import settings
from fastapi import APIRouter, HTTPException, Request, Response
from pydantic import BaseModel, ValidationError
from classquiz.db.models import User, UserAuthTypes
from classquiz.auth import check_token
from classquiz.config import settings
from classquiz.db.models import User, UserAuthTypes
from classquiz.helpers.avatar import gzipped_user_avatar
from classquiz.oauth.authenticate_user import log_user_in, rememberme_check
from classquiz.oauth.init_oauth import init_oauth
from pydantic import BaseModel, ValidationError
settings = settings()
@@ -47,17 +47,29 @@ class OpenIDResponse(BaseModel):
@router.get("/login")
async def openid_login(req: Request):
if settings.custom_openid_provider.client_id is None or settings.custom_openid_provider.client_secret is None:
raise HTTPException(status_code=501, detail="Custom-OAuth-Login isn't available on this server")
if (
settings.custom_openid_provider.client_id is None
or settings.custom_openid_provider.client_secret is None
):
raise HTTPException(
status_code=501, detail="Custom-OAuth-Login isn't available on this server"
)
oauth = init_oauth()
return await oauth.custom.authorize_redirect(req, f"{settings.root_address}/api/v1/users/oauth/custom/auth")
return await oauth.custom.authorize_redirect(
req, f"{settings.root_address}/api/v1/users/oauth/custom/auth"
)
@router.get("/auth")
async def auth(request: Request, response: Response):
if settings.custom_openid_provider.client_id is None or settings.custom_openid_provider.client_secret is None:
raise HTTPException(status_code=501, detail="Custom-OAuth-Login isn't available on this server")
if (
settings.custom_openid_provider.client_id is None
or settings.custom_openid_provider.client_secret is None
):
raise HTTPException(
status_code=501, detail="Custom-OAuth-Login isn't available on this server"
)
access_token = request.cookies.get("access_token")
rememberme_token = request.cookies.get("rememberme_token")
if access_token is not None:
@@ -68,7 +80,9 @@ async def auth(request: Request, response: Response):
except HTTPException:
pass
if rememberme_token is not None:
return await rememberme_check(rememberme_token=rememberme_token, response=response)
return await rememberme_check(
rememberme_token=rememberme_token, response=response
)
oauth = init_oauth()
user_data = await oauth.custom.authorize_access_token(request)
@@ -77,29 +91,29 @@ async def auth(request: Request, response: Response):
except (TypeError, ValidationError):
raise HTTPException(status_code=401, detail="Something went wrong.")
try:
await User.objects.create(
id=uuid.uuid4(),
email=user_data.email,
username=user_data.preferred_username,
verified=user_data.email_verified,
auth_type=UserAuthTypes.CUSTOM,
google_uid=user_data.sub.hex,
avatar=gzipped_user_avatar(),
)
# skipcq: PYL-W0703
except asyncpg.exceptions.UniqueViolationError:
# Most likely a duplicate email/username, not UUID.
raise HTTPException(status_code=400, detail="User already exists.")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
user = await User.objects.get_or_none(
email=user_data.email,
google_uid=user_data.sub.hex,
auth_type=UserAuthTypes.CUSTOM,
verified=True,
)
print(user_data)
if user is None:
try:
user = await User.objects.create(
id=uuid.uuid4(),
email=user_data.email,
username=user_data.preferred_username,
verified=user_data.email_verified,
auth_type=UserAuthTypes.CUSTOM,
google_uid=user_data.sub.hex,
avatar=gzipped_user_avatar(),
)
# skipcq: PYL-W0703
except asyncpg.exceptions.UniqueViolationError:
# Most likely a duplicate email/username, not UUID.
raise HTTPException(status_code=400, detail="User already exists.")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
await log_user_in(user=user, request=request, response=response)
response.headers.append("Location", "/account/login")
+30 -21
View File
@@ -4,19 +4,19 @@
import uuid
from datetime import datetime
import asyncpg
import authlib.integrations.base_client
from fastapi import APIRouter, Request, HTTPException, Response
from fastapi import APIRouter, HTTPException, Request, Response
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
from classquiz.auth import check_token
from classquiz.config import settings
from fastapi.responses import RedirectResponse
from classquiz.db.models import User, UserAuthTypes
from pydantic import BaseModel
from classquiz.helpers.avatar import gzipped_user_avatar
from classquiz.oauth.authenticate_user import log_user_in, rememberme_check
from datetime import datetime
from classquiz.oauth.init_oauth import init_oauth
settings = settings()
@@ -76,15 +76,21 @@ class GitHubOauthResponse(BaseModel):
@router.get("/login")
async def github_login(req: Request):
if settings.github_client_id is None or settings.github_client_secret is None:
raise HTTPException(status_code=501, detail="GitHub-Login isn't available on this server")
raise HTTPException(
status_code=501, detail="GitHub-Login isn't available on this server"
)
oauth = init_oauth()
return await oauth.github.authorize_redirect(req, f"{settings.root_address}/api/v1/users/oauth/github/auth")
return await oauth.github.authorize_redirect(
req, f"{settings.root_address}/api/v1/users/oauth/github/auth"
)
@router.get("/auth")
async def auth(request: Request, response: Response):
if settings.github_client_id is None or settings.github_client_secret is None:
raise HTTPException(status_code=501, detail="GitHub-Login isn't available on this server")
raise HTTPException(
status_code=501, detail="GitHub-Login isn't available on this server"
)
access_token = request.cookies.get("access_token")
rememberme_token = request.cookies.get("rememberme_token")
if access_token is not None:
@@ -95,7 +101,9 @@ async def auth(request: Request, response: Response):
except HTTPException:
pass
if rememberme_token is not None:
return await rememberme_check(rememberme_token=rememberme_token, response=response)
return await rememberme_check(
rememberme_token=rememberme_token, response=response
)
oauth = init_oauth()
try:
token = await oauth.github.authorize_access_token(request)
@@ -107,25 +115,26 @@ async def auth(request: Request, response: Response):
if user_data.email is None:
return RedirectResponse("/account/oauth-error?error=email")
# REGISTER USER
try:
await User.objects.create(
id=uuid.uuid4(),
email=user_data.email,
username=user_data.login,
verified=True,
auth_type=UserAuthTypes.GITHUB,
avatar=gzipped_user_avatar(),
)
except asyncpg.exceptions.UniqueViolationError:
raise HTTPException(status_code=400, detail="User already exists.")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
user = await User.objects.get_or_none(
email=user_data.email,
username=user_data.login,
auth_type=UserAuthTypes.GITHUB,
verified=True,
)
if user is None:
try:
user = await User.objects.create(
id=uuid.uuid4(),
email=user_data.email,
username=user_data.login,
verified=True,
auth_type=UserAuthTypes.GITHUB,
avatar=gzipped_user_avatar(),
)
except asyncpg.exceptions.UniqueViolationError:
raise HTTPException(status_code=400, detail="User already exists.")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
await log_user_in(user=user, request=request, response=response)
response.headers.append("Location", "/account/login")
+29 -18
View File
@@ -51,16 +51,22 @@ class OauthGoogleResponse(BaseModel):
@router.get("/login")
async def google_login(req: Request):
if settings.google_client_secret is None or settings.google_client_id is None:
raise HTTPException(status_code=501, detail="Google-Login isn't available on this server")
raise HTTPException(
status_code=501, detail="Google-Login isn't available on this server"
)
oauth = init_oauth()
return await oauth.google.authorize_redirect(req, f"{settings.root_address}/api/v1/users/oauth/google/auth")
return await oauth.google.authorize_redirect(
req, f"{settings.root_address}/api/v1/users/oauth/google/auth"
)
@router.get("/auth")
async def auth(request: Request, response: Response):
if settings.google_client_secret is None or settings.google_client_id is None:
raise HTTPException(status_code=501, detail="Google-Login isn't available on this server")
raise HTTPException(
status_code=501, detail="Google-Login isn't available on this server"
)
access_token = request.cookies.get("access_token")
rememberme_token = request.cookies.get("rememberme_token")
if access_token is not None:
@@ -71,7 +77,9 @@ async def auth(request: Request, response: Response):
except HTTPException:
pass
if rememberme_token is not None:
return await rememberme_check(rememberme_token=rememberme_token, response=response)
return await rememberme_check(
rememberme_token=rememberme_token, response=response
)
oauth = init_oauth()
user_data = await oauth.google.authorize_access_token(request)
@@ -80,26 +88,29 @@ async def auth(request: Request, response: Response):
except (TypeError, ValidationError):
raise HTTPException(status_code=401, detail="Something went wrong.")
# REGISTER USER
try:
await User.objects.create(
id=uuid.uuid4(),
email=user_data.email,
username=user_data.name,
verified=user_data.email_verified,
auth_type=UserAuthTypes.GOOGLE,
google_uid=user_data.sub,
avatar=gzipped_user_avatar(),
)
except asyncpg.exceptions.UniqueViolationError:
raise HTTPException(status_code=400, detail="User already exists.")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
user = await User.objects.get_or_none(
email=user_data.email,
google_uid=user_data.sub,
auth_type=UserAuthTypes.GOOGLE,
verified=True,
)
if user is None:
if user_data.email_verified is False:
raise HTTPException(status_code=401, detail="Email isn't verified")
try:
user = await User.objects.create(
id=uuid.uuid4(),
email=user_data.email,
username=user_data.name,
verified=True,
auth_type=UserAuthTypes.GOOGLE,
google_uid=user_data.sub,
avatar=gzipped_user_avatar(),
)
except asyncpg.exceptions.UniqueViolationError:
raise HTTPException(status_code=400, detail="User already exists.")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
await log_user_in(user=user, request=request, response=response)
response.headers.append("Location", "/account/login")