🐞 Bug Summary
When an OAuth2 provider returns a token response without the expires_in field, the gateway crashes with a TypeError during token storage. The expires_in parameter is RECOMMENDED (not REQUIRED) per RFC 6749 Section 5.1, so providers may legitimately omit it.
🧩 Affected Component
🔁 Steps to Reproduce
- Configure a gateway with OAuth2 pointing to a provider that does not return
expires_in in the token response (e.g., some Azure AD configurations, custom OAuth servers)
- Attempt to connect to the gateway — OAuth flow triggers token exchange
- Token response is received successfully but lacks
expires_in
- Gateway crashes when trying to compute
expires_at = now + expires_in
🤔 Expected Behavior
The gateway should handle missing expires_in gracefully:
- Extract
expires_in from the token response, defaulting to None when absent
- Store the token without an
expires_at timestamp when no expiry is provided
- The token should remain usable until explicitly revoked or refreshed
📓 Logs / Error Output
TypeError: unsupported operand type(s) for +: 'datetime' and 'NoneType'
Occurs in token_storage_service.py when expires_in is None and the code tries to compute datetime.now() + timedelta(seconds=expires_in).
🧠 Environment Info
| Key |
Value |
| Version or commit |
1.0.0-RC2 |
| Runtime |
Python 3.12, Gunicorn |
| Platform / OS |
Linux (Kubernetes) |
| Container |
Docker |
🧩 Additional Context
RFC 6749 Section 5.1 states:
expires_in — RECOMMENDED. The lifetime in seconds of the access token.
Since it is RECOMMENDED and not REQUIRED, the gateway must handle its absence gracefully. The fix involves two changes:
oauth_manager.py: Extract expires_in with .get() and pass None when absent
token_storage_service.py: Accept Optional[int] for expires_in and skip expires_at computation when None
🐞 Bug Summary
When an OAuth2 provider returns a token response without the
expires_infield, the gateway crashes with aTypeErrorduring token storage. Theexpires_inparameter is RECOMMENDED (not REQUIRED) per RFC 6749 Section 5.1, so providers may legitimately omit it.🧩 Affected Component
mcpgateway- API🔁 Steps to Reproduce
expires_inin the token response (e.g., some Azure AD configurations, custom OAuth servers)expires_inexpires_at = now + expires_in🤔 Expected Behavior
The gateway should handle missing
expires_ingracefully:expires_infrom the token response, defaulting toNonewhen absentexpires_attimestamp when no expiry is provided📓 Logs / Error Output
Occurs in
token_storage_service.pywhenexpires_inisNoneand the code tries to computedatetime.now() + timedelta(seconds=expires_in).🧠 Environment Info
1.0.0-RC2🧩 Additional Context
RFC 6749 Section 5.1 states:
Since it is RECOMMENDED and not REQUIRED, the gateway must handle its absence gracefully. The fix involves two changes:
oauth_manager.py: Extractexpires_inwith.get()and passNonewhen absenttoken_storage_service.py: AcceptOptional[int]forexpires_inand skipexpires_atcomputation whenNone