huggingface / chat-ui

Open source codebase powering the HuggingChat app
https://huggingface.co/chat
Apache License 2.0
7.19k stars 1.04k forks source link

Use refresh tokens for OAuth #1377

Open nsarrazin opened 1 month ago

nsarrazin commented 1 month ago

Currently we use long-lived sessions that get extended when the user performs an action. In order to better manage sessions, we could switch to an OAuth flow where we have a short lived session with an access token cookie and a refresh token that we can use to refresh the sessions, since HuggingFace now supports refresh tokens.

We would probably need to make this flow opt-in in the config as I'm not sure every oauth provider supports this ?

relevant: https://github.com/huggingface/chat-ui/pull/1365#pullrequestreview-2201751954 cc @coyotte508 if you have any resources on how to implem this, I've never done it before :eyes:

coyotte508 commented 1 month ago

hmm well basically in the oauth response, besides userinfo, you have an optional refresh token. And also the oauth token expiration date, and refresh token expiration date.

So, you need to store in the session both the oauth token and the expiration date.

When the expiration date is close (eg half of the oauth token duration), you can use the refresh token to create a new oauth token and store it in DB in the session's document.

The more tricky part is refreshing the refresh token. It will only work, once, and you need to store the new refresh token in DB. The old token won't be valid anymore.

I would suggest refreshing the refresh token at the next opportunity once it's a month old. Since the sessions last two weeks, there's no risk of a session with an expired refresh token (they last three months, at least with HF).

If refreshRefreshToken fails, it should update the session to make the next try in an hour, to avoid a failing API call every single request . Make sure to do db.session.updateOne({_id:..., refreshToken: <old refresh token>}, ...) so that a concurrent refresh is not overwritten by the failed one.

When the oauth token cannot be refreshed and expires, the session should probably be removed from DB.

Probably got in more details than needed :sweat_smile:

dlavrenuek commented 1 month ago

The more tricky part is refreshing the refresh token. It will only work, once, and you need to store the new refresh token in DB. The old token won't be valid anymore.

The refresh access token request will also return the refresh token*, there is no separate request to renew the refresh token (at least not in the spec). If HuggingFace IDP always returns a new refresh token, then always setting both tokens on login/refresh makes sense.

* it depends on the identity provider implementation. Some IDPs always return a new refresh token, some only return it if the expiration time of the old one is short. Also some useful info: some IDPs return the refresh token as JWT but some just return a formatles string, it means that expiration date of the refresh token might not always be known.

coyotte508 commented 1 month ago

Yes my bad, the same call refreshes both the access token & refresh token.