authlib icon indicating copy to clipboard operation
authlib copied to clipboard

Refresh token with requests session, client_credentials grant and without explicitly provided grant_type breaks

Open iivanov-qb opened this issue 6 months ago • 1 comments

Describe the bug

When using Authlib with requests session, _guess_grant_type method is used by fetch_token but not by ensure_active_token so if one initialises the session without adding the grant_type in the metadata and the already existing token happens to be expired, this could cause troubles in case of client_credentials grant as the check in ensure_active_token is explicitly for client_credentials:

elif self.metadata.get("grant_type") == "client_credentials":

So, if grant_type is not explicitly provided and _guess_grant_type is not executed, this would end up false and token won't be refreshed properly.

Error Stacks

authlib/integrations/requests_client/oauth2_session.py", line 140, in request
    return super().request(method, url, auth=auth, **kwargs)
  File "requests/sessions.py", line 575, in request
    prep = self.prepare_request(req)
  File "requests/sessions.py", line 484, in prepare_request
    p.prepare(
  File "requests/models.py", line 371, in prepare
    self.prepare_auth(auth, url)
  File "requests/models.py", line 602, in prepare_auth
    r = auth(self)
  File "authlib/integrations/requests_client/oauth2_session.py", line 25, in __call__
    self.ensure_active_token()
  File "authlib/integrations/requests_client/oauth2_session.py", line 22, in ensure_active_token
    raise InvalidTokenError()
authlib.integrations.base_client.errors.InvalidTokenError: token_invalid: "

To Reproduce

Try connect to OAuth API with client_credentials grant with requests session without explicitly providing the grant type to the session. Provide the token, don't fetch it in the current session. Then try refresh the token. Expectation is, that it won't refresh, because it won't match the grant type, as it is not in the metadata.

Expected behavior

metadata should be populated from _guess_grant_type not only on fetch_token but every time we try refresh the token as well, aka ensure_active_token

Environment:

  • OS: Not related
  • Python Version: Not related
  • Authlib Version: 1.5.2

Additional context

N/A

iivanov-qb avatar Jun 26 '25 17:06 iivanov-qb

I encountered this too. It can be worked around by supplying the grant type when registering the remote app:

oauth.register(
    ...
    client_kwargs={"grant_type": "client_credentials"},
)

markhobson avatar Jul 22 '25 16:07 markhobson