-
Notifications
You must be signed in to change notification settings - Fork 613
[BUG][AUTH]: JWT_AUDIENCE_VERIFICATION=false does not disable issuer validation #1792
Description
🐞 Bug Summary
Setting JWT_AUDIENCE_VERIFICATION=false disables audience (aud) validation but still requires the iss (issuer) claim. Tokens without an iss claim are rejected with 401 Unauthorized even when this flag is false.
🧩 Affected Component
-
mcpgateway- API -
mcpgateway- UI (admin panel) -
mcpgateway.wrapper- stdio wrapper - Federation or Transports
- CLI, Makefiles, or shell scripts
- Container setup (Docker/Podman/Compose)
- Other (explain below)
Specific file: mcpgateway/utils/verify_credentials.py (lines ~107-114)
🔁 Steps to Reproduce
- Configure Context Forge with
JWT_AUDIENCE_VERIFICATION=false - Generate a valid JWT signed with the correct secret but without an
issclaim:import jwt token = jwt.encode( {"sub": "user-123", "exp": 9999999999}, "your-jwt-secret-key", algorithm="HS256" )
- Send request to Context Forge:
curl -H "Authorization: Bearer <token>" http://localhost:4444/v1/mcp/list_tools - Observe:
401 Unauthorized
🤔 Expected Behavior
When JWT_AUDIENCE_VERIFICATION=false, tokens without iss or aud claims should be accepted (signature and expiration still validated). This would allow integration with third-party systems that issue JWTs without standard claims.
📓 Logs / Error Output
401 Unauthorized: Token is missing the "iss" claim
🧠 Environment Info
| Key | Value |
|---|---|
| Version or commit | v1.0.0-BETA-1 |
| Runtime | Python 3.11 |
| Platform / OS | Ubuntu 22.04 (WSL2) |
| Container | Docker Compose |
🧩 Additional Context (optional)
Root Cause: In verify_credentials.py, the issuer parameter is always passed to jwt.decode():
decode_kwargs = {
"key": get_jwt_public_key_or_secret(),
"algorithms": [settings.jwt_algorithm],
"options": options,
"audience": settings.jwt_audience,
"issuer": settings.jwt_issuer, # Always passed → always validated
}
payload = jwt.decode(token, **decode_kwargs)PyJWT behavior: When issuer=<value> is passed, it requires the token to contain a matching iss claim. To skip issuer validation, the parameter must be omitted entirely.
Proposed Fix: Add JWT_ISSUER_VERIFICATION config option:
# Only add issuer if verification enabled
if settings.jwt_issuer_verification:
decode_kwargs["issuer"] = settings.jwt_issuerDefault True preserves backward compatibility.