Inability for automatic token refresh when using `grant_type=password`
Describe the bug
Trying to authenticate and generate requests using an OAuth2Session using username/password authentication. I'm able to generate an initial token to be used in my session, however, I was trying to utilize the functionality to automatically refresh tokens by passing in the token_endpoint to automatically as stated in the documentation.
When my token would expire it would not refresh the token automatically and lead to an InvalidToken error. After looking into this further I tried to invoke the authorization to refresh and generate a new token by passing in the grant_type=password as one of the recognized metadata that gets passed into the client. However noticed that this will not properly resolve the problem as the ensure_active_token is used to automatically refresh tokens:
https://github.com/lepture/authlib/blob/a2ada05dae625695f559140675a8d2aebc6b5974/authlib/oauth2/client.py#L256-L269
is neglecting to pass in the rest of the metadata from the session (like grant_type) to refresh_token here https://github.com/lepture/authlib/blob/a2ada05dae625695f559140675a8d2aebc6b5974/authlib/oauth2/client.py#L222-L254
that only uses passed-in params to construct the body to generate a new token through prepare_token_request here:
https://github.com/lepture/authlib/blob/a2ada05dae625695f559140675a8d2aebc6b5974/authlib/oauth2/client.py#L238-L241
Error Stacks
File
"/Users/mamdouh.abuelatta/.local/share/virtualenvs/optic-dr-ETdtnlpf/lib/python3.8/site-packages/authlib/integrations/requests_client/oauth2_session.py
", line 109, in request
return super(OAuth2Session, self).request(
File
"/Users/mamdouh.abuelatta/.local/share/virtualenvs/optic-dr-ETdtnlpf/lib/python3.8/site-packages/requests/sessions.py
", line 528, in request
prep = self.prepare_request(req)
File
"/Users/mamdouh.abuelatta/.local/share/virtualenvs/optic-dr-ETdtnlpf/lib/python3.8/site-packages/requests/sessions.py
", line 456, in prepare_request
p.prepare(
File
"/Users/mamdouh.abuelatta/.local/share/virtualenvs/optic-dr-ETdtnlpf/lib/python3.8/site-packages/requests/models.py
", line 320, in prepare
self.prepare_auth(auth, url)
File
"/Users/mamdouh.abuelatta/.local/share/virtualenvs/optic-dr-ETdtnlpf/lib/python3.8/site-packages/requests/models.py
", line 556, in prepare_auth
r = auth(self)
File
"/Users/mamdouh.abuelatta/.local/share/virtualenvs/optic-dr-ETdtnlpf/lib/python3.8/site-packages/authlib/integrations/requests_client/oauth2_session.py
", line 24, in __call__
self.ensure_active_token()
File
"/Users/mamdouh.abuelatta/.local/share/virtualenvs/optic-dr-ETdtnlpf/lib/python3.8/site-packages/authlib/integrations/requests_client/oauth2_session.py
", line 21, in ensure_active_token
raise InvalidTokenError()
authlib.integrations.base_client.errors.InvalidTokenError: token_invalid:
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
To Reproduce
A minimal example to reproduce the behavior:
- Initialize OAuth2Session with a valid
token_endpointandgrant_type=password fetch_tokenwithusername/password- Wait for(or manipulate token expiry) token to be in an expired state
- Use
client.requestto initiate a request
Expected behavior
Ability to pass grant_type=password and allow for automatic refresh token when the initial token has expired.
Environment:
- OS: macOS Big Sur 11.7.3
- Python Version: 3.8
- Authlib Version: 1.2.0
Proposed Solution
A. Pass in the rest of the metadata from the session (like grant_type) to refresh_token here:https://github.com/lepture/authlib/blob/a2ada05dae625695f559140675a8d2aebc6b5974/authlib/oauth2/client.py#L222-L254
that will be passed-down as a params to construct the body to generate a new token through prepare_token_request here:
https://github.com/lepture/authlib/blob/a2ada05dae625695f559140675a8d2aebc6b5974/authlib/oauth2/client.py#L238-L241
B. Pass in combined params (method/session) when constructing the body to generate a new token through prepare_token_request here:
https://github.com/lepture/authlib/blob/a2ada05dae625695f559140675a8d2aebc6b5974/authlib/oauth2/client.py#L238-L241