fix auth
This commit is contained in:
+43
-11
@@ -139,22 +139,54 @@ async def mcp_protocol_handler(request: Request):
|
||||
token = auth_header.split(" ")[1]
|
||||
try:
|
||||
# Validate Clerk JWT token (required)
|
||||
from clerk_backend_api import Clerk
|
||||
clerk = Clerk(bearer_auth=os.getenv("CLERK_SECRET_KEY"))
|
||||
jwt_claims = clerk.jwt_templates.verify_token(token)
|
||||
user_id = jwt_claims.get("sub")
|
||||
from clerk_backend_api import Clerk, models
|
||||
import jwt
|
||||
|
||||
if not user_id:
|
||||
logger.error("JWT token validation failed - no user_id in claims")
|
||||
# First, decode JWT token without verification to get session_id
|
||||
try:
|
||||
decoded_token = jwt.decode(token, options={"verify_signature": False})
|
||||
session_id = decoded_token.get("sid") or decoded_token.get("session_id")
|
||||
except Exception as e:
|
||||
logger.error(f"JWT token decoding failed: {e}")
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail="Invalid token - no user_id in claims"
|
||||
detail="Invalid JWT token format"
|
||||
)
|
||||
|
||||
logger.info(f"Bearer JWT token validated for user: {user_id}")
|
||||
# Add user info to request state
|
||||
request.state.user_id = user_id
|
||||
request.state.token_scopes = jwt_claims.get("scopes", ["read", "search"])
|
||||
if not session_id:
|
||||
logger.error("No session_id found in JWT token")
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail="Invalid token - no session_id in claims"
|
||||
)
|
||||
|
||||
# Now verify the session with Clerk
|
||||
clerk = Clerk(bearer_auth=os.getenv("CLERK_SECRET_KEY"))
|
||||
|
||||
try:
|
||||
# Use deprecated but working sessions.verify method
|
||||
session = clerk.sessions.verify(session_id=session_id, token=token)
|
||||
user_id = session.user_id if session else None
|
||||
|
||||
if not user_id:
|
||||
logger.error("Session verification failed - no user_id")
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail="Invalid session - no user_id"
|
||||
)
|
||||
|
||||
logger.info(f"Bearer JWT token validated for user: {user_id}")
|
||||
# Add user info to request state
|
||||
request.state.user_id = user_id
|
||||
request.state.session_id = session_id
|
||||
request.state.token_scopes = ["read", "search"] # Default scopes
|
||||
|
||||
except models.ClerkErrors as e:
|
||||
logger.error(f"Clerk session verification failed: {e}")
|
||||
raise HTTPException(
|
||||
status_code=401,
|
||||
detail="Session verification failed"
|
||||
)
|
||||
|
||||
except HTTPException:
|
||||
# Re-raise HTTPException as-is
|
||||
|
||||
@@ -189,6 +189,62 @@ async def register_client(request: Request):
|
||||
"token_endpoint_auth_method": "none"
|
||||
})
|
||||
|
||||
@router.post("/auth/callback")
|
||||
async def oauth_callback_post(request: Request):
|
||||
"""OAuth callback POST endpoint for token exchange"""
|
||||
|
||||
# Parse form data (standard OAuth token exchange format)
|
||||
form_data = await request.form()
|
||||
grant_type = form_data.get("grant_type")
|
||||
code = form_data.get("code")
|
||||
redirect_uri = form_data.get("redirect_uri")
|
||||
client_id = form_data.get("client_id")
|
||||
code_verifier = form_data.get("code_verifier")
|
||||
|
||||
logger.info(f"OAuth callback POST - grant_type: {grant_type}")
|
||||
logger.info(f"Code: {code[:20] if code else 'None'}...")
|
||||
logger.info(f"Client ID: {client_id}")
|
||||
logger.info(f"PKCE verifier: {bool(code_verifier)}")
|
||||
|
||||
if grant_type != "authorization_code":
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={"error": "unsupported_grant_type"}
|
||||
)
|
||||
|
||||
if not code or not redirect_uri:
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={"error": "invalid_request", "error_description": "Missing code or redirect_uri"}
|
||||
)
|
||||
|
||||
try:
|
||||
# Validate authorization code
|
||||
if not code.startswith("clerk_auth_"):
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content={"error": "invalid_grant", "error_description": "Invalid authorization code"}
|
||||
)
|
||||
|
||||
# TODO: In production, validate code against stored session
|
||||
# For now, we'll return a placeholder response
|
||||
|
||||
# Generate or retrieve actual Clerk JWT token
|
||||
# This should be the actual JWT token from Clerk authentication
|
||||
return JSONResponse({
|
||||
"access_token": "PLACEHOLDER_CLERK_JWT_TOKEN",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 3600,
|
||||
"scope": "read search"
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.exception(f"OAuth callback POST failed: {e}")
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content={"error": "server_error", "error_description": str(e)}
|
||||
)
|
||||
|
||||
@router.post("/token")
|
||||
async def token_endpoint(request: Request):
|
||||
"""OAuth 2.1 Token Endpoint - exchanges code for Clerk JWT"""
|
||||
|
||||
Reference in New Issue
Block a user