Add OAuth error return interface format

This commit is contained in:
咕谷酱
2025-07-26 23:48:48 +08:00
parent ef977d1c2d
commit 130bcdcdc1
2 changed files with 54 additions and 9 deletions

View File

@@ -27,3 +27,10 @@ class UserCreate(BaseModel):
password: str
email: str
country_code: str = "CN"
class OAuthErrorResponse(BaseModel):
error: str
error_description: str
hint: str
message: str

View File

@@ -11,11 +11,26 @@ from app.auth import (
)
from app.config import settings
from app.dependencies import get_db
from app.models.oauth import TokenResponse
from app.models.oauth import TokenResponse, OAuthErrorResponse
from fastapi import APIRouter, Depends, Form, HTTPException
from fastapi import APIRouter, Depends, Form
from fastapi.responses import JSONResponse
from sqlmodel.ext.asyncio.session import AsyncSession
def create_oauth_error_response(error: str, description: str, hint: str, status_code: int = 400):
"""创建标准的 OAuth 错误响应"""
error_data = OAuthErrorResponse(
error=error,
error_description=description,
hint=hint,
message=description
)
return JSONResponse(
status_code=status_code,
content=error_data.model_dump()
)
router = APIRouter(tags=["osu! OAuth 认证"])
@@ -36,19 +51,30 @@ async def oauth_token(
client_id != settings.OSU_CLIENT_ID
or client_secret != settings.OSU_CLIENT_SECRET
):
raise HTTPException(status_code=401, detail="Invalid client credentials")
return create_oauth_error_response(
error="invalid_client",
description="Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).",
hint="Invalid client credentials",
status_code=401
)
if grant_type == "password":
# 密码授权流程
if not username or not password:
raise HTTPException(
status_code=400, detail="Username and password required"
return create_oauth_error_response(
error="invalid_request",
description="The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.",
hint="Username and password required"
)
# 验证用户
user = await authenticate_user(db, username, password)
if not user:
raise HTTPException(status_code=401, detail="Invalid username or password")
return create_oauth_error_response(
error="invalid_grant",
description="The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.",
hint="Incorrect sign in"
)
# 生成令牌
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
@@ -77,12 +103,20 @@ async def oauth_token(
elif grant_type == "refresh_token":
# 刷新令牌流程
if not refresh_token:
raise HTTPException(status_code=400, detail="Refresh token required")
return create_oauth_error_response(
error="invalid_request",
description="The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.",
hint="Refresh token required"
)
# 验证刷新令牌
token_record = await get_token_by_refresh_token(db, refresh_token)
if not token_record:
raise HTTPException(status_code=401, detail="Invalid refresh token")
return create_oauth_error_response(
error="invalid_grant",
description="The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.",
hint="Invalid refresh token"
)
# 生成新的访问令牌
access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
@@ -109,4 +143,8 @@ async def oauth_token(
)
else:
raise HTTPException(status_code=400, detail="Unsupported grant type")
return create_oauth_error_response(
error="unsupported_grant_type",
description="The authorization grant type is not supported by the authorization server.",
hint="Unsupported grant type"
)