Skip to content

Commit a843c23

Browse files
committed
debug: add comprehensive logging to JWT verification to find hanging point
1 parent 271332d commit a843c23

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

commitly-backend/app/core/auth.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,50 +221,74 @@ def verify_clerk_token(token: str) -> ClerkClaims:
221221
async def verify_clerk_token_async(token: str) -> ClerkClaims:
222222
"""Async version of verify_clerk_token that doesn't block the event loop."""
223223
import asyncio
224+
import logging
225+
226+
logger = logging.getLogger(__name__)
227+
logger.info("verify_clerk_token_async: Starting token verification")
224228

225229
try:
226230
header = jwt.get_unverified_header(token)
231+
logger.info("verify_clerk_token_async: Got unverified header")
227232
except JWTError as exc:
233+
logger.error("verify_clerk_token_async: Malformed token header")
228234
raise InvalidClerkToken("Malformed token header") from exc
229235

230236
kid = header.get("kid")
231237
if not isinstance(kid, str):
238+
logger.error("verify_clerk_token_async: Missing key identifier")
232239
raise InvalidClerkToken("Missing key identifier")
240+
241+
logger.info(f"verify_clerk_token_async: Fetching JWKS for kid={kid}")
233242

234243
# Use async version to avoid blocking
235244
jwk_data = await jwks_cache.get_key_async(kid)
245+
logger.info("verify_clerk_token_async: Got JWKS data, starting signature verification")
236246

237247
# Run CPU-intensive JWT operations in executor to avoid blocking
238248
def verify_signature():
249+
logger.info("verify_signature: Constructing public key")
239250
public_key = jwk.construct(jwk_data)
251+
logger.info("verify_signature: Public key constructed")
240252

241253
try:
242254
message, encoded_signature = token.rsplit(".", 1)
243255
except ValueError as exc:
256+
logger.error("verify_signature: Invalid token structure")
244257
raise InvalidClerkToken("Token structure is invalid") from exc
245258

259+
logger.info("verify_signature: Decoding signature")
246260
decoded_signature = base64url_decode(encoded_signature.encode("utf-8"))
261+
logger.info("verify_signature: Verifying signature with public key")
247262
if not public_key.verify(message.encode("utf-8"), decoded_signature):
263+
logger.error("verify_signature: Signature verification failed")
248264
raise InvalidClerkToken("Signature verification failed")
249-
250-
return jwt.get_unverified_claims(token)
265+
266+
logger.info("verify_signature: Signature verified, getting claims")
267+
claims = jwt.get_unverified_claims(token)
268+
logger.info("verify_signature: Claims retrieved")
269+
return claims
251270

252271
# Run signature verification in thread pool to avoid blocking event loop
272+
logger.info("verify_clerk_token_async: Running signature verification in executor")
253273
loop = asyncio.get_event_loop()
254274
claims = await loop.run_in_executor(None, verify_signature)
275+
logger.info("verify_clerk_token_async: Signature verification complete")
255276

256277
now = int(time.time())
257278

258279
exp = claims.get("exp")
259280
if exp is not None and int(exp) <= now:
281+
logger.error("verify_clerk_token_async: Token expired")
260282
raise InvalidClerkToken("Token has expired")
261283

262284
nbf = claims.get("nbf")
263285
if nbf is not None and now < int(nbf):
286+
logger.error("verify_clerk_token_async: Token not yet valid")
264287
raise InvalidClerkToken("Token is not yet valid")
265288

266289
issuer = claims.get("iss")
267290
if issuer != settings.clerk_issuer:
291+
logger.error(f"verify_clerk_token_async: Invalid issuer {issuer}")
268292
raise InvalidClerkToken("Invalid issuer")
269293

270294
audience_values = _select_audience(claims.get("aud"))
@@ -273,6 +297,7 @@ def verify_signature():
273297
]
274298
if audience_values:
275299
if not any(audience in audience_values for audience in allowed_audiences):
300+
logger.error(f"verify_clerk_token_async: Invalid audience {audience_values}")
276301
raise InvalidClerkToken("Invalid audience")
277302

278303
if settings.clerk_authorized_parties:
@@ -283,13 +308,17 @@ def verify_signature():
283308
_normalize_party(party) for party in settings.clerk_authorized_parties
284309
}
285310
if "*" not in allowed and normalized_azp not in allowed:
311+
logger.error(f"verify_clerk_token_async: Unauthorized party {normalized_azp}")
286312
raise InvalidClerkToken("Token not issued for this application")
287313
else:
314+
logger.error("verify_clerk_token_async: Missing authorized party")
288315
raise InvalidClerkToken("Token missing authorized party")
289316

290317
if "sub" not in claims:
318+
logger.error("verify_clerk_token_async: Missing subject claim")
291319
raise InvalidClerkToken("Token is missing subject claim")
292320

321+
logger.info("verify_clerk_token_async: Token verification successful")
293322
return cast(ClerkClaims, claims)
294323

295324

0 commit comments

Comments
 (0)