lepture / authlib

The ultimate Python library in building OAuth, OpenID Connect clients and servers. JWS,JWE,JWK,JWA,JWT included.
https://authlib.org/
BSD 3-Clause "New" or "Revised" License
4.45k stars 445 forks source link

The expires_in function needs to have a timedelta to avoid tokenExpiry errors for milliseconds #567

Closed pghole closed 4 months ago

pghole commented 1 year ago

Describe the bug

I am using the OAuth2session object

client = OAuth2Session(client_id=client_id, client_secret=client_secret, token_endpoint=token_url, grant_type='client_credentials')
client.fetch_token(token_url)
client.get(<MY_PROTECTED_URL>)

Here, the library behavior is that the token gets automatically refreshed if that has expired. Refer https://github.com/lepture/authlib/blob/master/authlib/oauth2/client.py#L257

However, the function which checks the token expiry https://github.com/lepture/authlib/blob/master/authlib/oauth2/rfc6749/wrappers.py#L13 , simply checks the expiry time with the current time . Because of this we are missing some corner cases, where the token is about to expire in few milliseconds/seconds and when the API call to the protected url is made, it gives error in authentication.

JWT expired at 2023-06-20T13:16:42Z. Current time: 2023-06-20T13:16:42Z, a difference of 105 milliseconds. Allowed clock skew: 0 milliseconds." Error Stacks

JWT expired at 2023-06-20T13:16:42Z. Current time: 2023-06-20T13:16:42Z, a difference of 105 milliseconds. Allowed clock skew: 0 milliseconds."

To Reproduce

A minimal example to reproduce the behavior:

While the exact replication is not possible here as the request is failing by few milliseconds.

client = OAuth2Session(client_id=<client_id>, client_secret=<client_secret>, token_endpoint=<token_url>, grant_type='client_credentials')
client.fetch_token(<token_ur>l)
client.get(<MY_PROTECTED_URL>)

A clear and concise description of what you expected to happen.

Even if the token got expired by few milliseconds, the library should be able to handle such cases by obtaining a new token. Instead of https://github.com/lepture/authlib/blob/master/authlib/oauth2/rfc6749/wrappers.py#L17 , we should be adding a small timedelta . For eg - even if the token is going to expire in next 60 seconds, refresh that still.

Environment:

Additional context

There should be some timedelta introduced in the function , so that we can avoid facing issues where API requests fail by few milliseconds. Here, we can add logic to show that token has expired , let's say 30-60 seconds prior to its actual expiry.

princekhunt commented 5 months ago

I have tried to fix the issue by adding 60s timedelta in is_expired function. check PR #634

Thanks

codespearhead commented 4 months ago

This issue was fixed in #634 , but since that PR is not linked to this issue, it was not closed automatically.

@pghole Can you close it?