I am using Python
3.5.1 with Requests
2.9.1. My use case as follows: I need to authenticate (get a token) from service T and use it as value of the Authorization
header when making requests to a resource server R. The token expires at some point and a new one needs to be fetched.
I have an application using requests
, which when started first fetches a token and remembers it - sets in the Session
used for requests to R. From then on for 3 minutes, everything works as a charm. After 3 minutes, I get unauthorized
responses as the token is invalid.
I use Session
for all requests except for the one to authenticate; this call updates the Authorization
header on the Session
for other requests to use.
I created code to re-authenticate automatically when unauthorized
is detected, using the response
hook (set only on the Session
), here is the code:
def __hook(self, res, *args, **kwargs):
if res.status_code == requests.codes.unauthorized:
print('Token expired, refreshing')
self.auth() # sets the token on self.__session
req = res.request
print('Resending request', req.method, req.url, req.headers)
req.headers['Authorization'] = self.__session.headers['Authorization'] # why is it needed?
return self.__session.send(res.request)
Basically, it even works. There are a couple of issues, though:
Why is it necessary to re-set the
Authorization
header on the request, even though the session is updated and is used to resend the original request? Without the line, the application will just keep on refreshing the token as the new one is never used, this can be seen in the output, the token is the original one which caused the automatic refresh.How can I make the code more robust, i.e. prevent endless recursion (I am not sure whether it is possible in reality, but with the line setting the
Authorization
header on the retried request it will just go on an on)? I was thinking of setting a custom header, and if the hooks discovers the failed request has it, it would not re-authenticate and resend. Is there anything better? Edit: it turns out it is possible to get an (almost) endless loop (it is recursive, after all) if the configuration is wrong: the tokens are taken for one environment (like STAGING), but the resource server is from another (TEST) - theauth
request will succeed but the token is actually incorrect for the resource server. For the time being I implemented the 'special' header solution mentioned above.
Is this a good approach in general or is there anything better suited for the task in requests
?