0

I previously read that Access Token must be sent with every request to the API but Refresh Token must be sent ONLY when the Access Token expires.

I'm trying to use a similar model to the conventional model, where the Access Token is JWT, but the Refresh Token is just a random unique string (stored on server)

so the Access Token JWT claims looks like this:

{
   "user_id": "user123456789",
   "refresh_token": "A9t2G8eH8j2QW2j9U",
   "exp": 154922000
}

When a client sends a request to my API, the Access Token (JWT) will be sent to the server. If it is expired, then a new Access Token will be sent to them with a newly-generated Refresh Token alongside the HTTP Response of the requested resource (after doing some validation).

This way:

  1. The client only needs to securely-save and send one JWT Token instead of two, with their requests.

  2. The client doesn't have to make a second request just to refresh their Access Token in case if it's expired. (No 401 HTTP Response).

Request with valid AccessToken => (Response with the requested resource)

Request with expired AccessToken => (Response with the requested resource + New AccessToken)

The problem here is that the Refresh Token (random unique string) is being sent with every request over the wire in plain text, and I can't want to force my clients to use HTTPS only.

but then again, even in the "conventional model" the Refresh Token will be sent every X period of time, and a packet sniffer will be able to steal it easily if the connection wasn't over HTTPS

Am I missing something here? Is my model flawed? Or is the conventional OAuth model must be strictly used over HTTPS? Is forcing HTTPS is my last resort?

0

I will quote parts of the question and try to answer them.

I previously read that Access Token must be sent with every request to the API but Refresh Token must be sent ONLY when the Access Token expires.

No, the refresh token is not supposed to be sent to the API. A refresh token is sent to the authorisation server to obtain a new access token.

when a client sends a request to my API, the Access Token (JWT) will be sent to the server, if it's expired, then a new Access Token will be sent to them with a newly-generated refresh_token alongside with the HTTP Response of the requested resource (after doing some validation).

This defeats the whole purpose of a refresh token. The idea for a refresh token is that to keep access token lifespan shorter (to minimise the time available for reusing access token in case of a disclosure). When an access token expires, the access should be rejected outright. Also, issuing access and refresh tokens is the responsibility of the authorisation server not the resource server (your API).

If you prefer to use only a single token, you should take a look at the OAuth2 implicit flow. In this flow, only the access token is issued and you don't have to deal with a refresh token. However, this means that every time the access token expires, you need to redirect the user to the authorisation server to obtain new access token if required.

is the conventional OAuth model must be strictly used over HTTPS? Is forcing HTTPS is my last resort?

Yes, you must use HTTPS. Tokens must be protected in transit as well as in rest. A leaked token means that the attacker will have access to your resource server.

I heavily recommend to read RFC 6819 that explains the OAuth 2.0 threat model and different security considerations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.