securitycookiesauthorizationtoken

Access token and Refresh token best practices ? How to implement Access & Refresh Tokens


I'm making SPA, and decided to use JWT for Authentication/Authorization, and I have read some blogs about Tokens vs Cookies. I understand how cookie authorization works, and understand how basic token authorization works. The problem is, I don't see how refresh token fits into it, seems to me it decreases security. Let me explain, as I see it:

Cookie approach

When you authenticate user via username & password, you create session ID associated with that user. And set it as cookie, every time that client calls to your server it sends that cookie, and server can look up associated user in database or some other server side storage.

Token approach

When you authenticate user via username & password, you create a signed Token, with expiration date, email address or userID, role, etc. in payload. For security tokens should have short expiration time. Tokens can be stored anywhere Local storage, Session storage, cookies. I will be using local storage, or session storage, to prevent XSRF.

Access Token & Refresh Token

So I want to use Refresh tokens to prevent user from needing to login constantly. So lets say on Authentication, I give user Access token and Refresh token, when users Access token expires, user can use Refresh token to get New Access token, This is what I don't get.

What's the best practice ?

Currently I'm thinking about using:

Let's say it looks like this:

  +--------+                                           +---------------+
  |        |------------ Authorization Grant --------->|               |
  |        |                                           |               |
  |        |<--------------- Access Token -------------|               |
  |        |               & Refresh Token (cookie)    |               |
  |        |               & XSRF Token                |               |
  |        |                                           |               |
  |        |                                           |               |
  |        |--------- Access Token ------------------->|               |
  |        |                                           |               |
  |        |<----- Protected Resource -----------------|               |
  | Client |                                           |     Server    |
  |        |--------- Access Token ------------------->|               |
  |        |                                           |               |
  |        |<----- Invalid Token Error ----------------|               |
  |        |                                           |               |
  |        |                                           |               |
  |        |---------------- Refresh Token ----------->|               |
  |        |               & XSRF Token                |               |
  |        |                                           |               |
  |        |<--------------- Access Token -------------|               |
  |        |               & XSRF Token                |               |
  +--------+               & Optional Refresh Token    +---------------+

Server would issue new XSRF Token every time Refresh token is used(after one XSRF token is used it stops working and server issues new one). What you think about this implementation ? In my eyes this limits server lookups to database, as it uses access tokens, access tokens is short lived, and user don't have to login constantly as it uses refresh token/cookie witch is protected by XSRF token.

Is this OK ?

Thanks !


Solution

  • Regarding access token and refresh token

    Consider the access token to be a "dirty" token. Token you share a lot. It does not have to be one server you pass the token to, there can be many. Because of this the attack surface rises. If one server does something stupid like writing tokens into server logs and then exposing the logs to the world, you want to limit the negative impact, therefore the access tokens are short lived, to limit the time the attacker can do something malicious.

    On the other hand a refresh token is a "clean" token. Something you store for yourself to remember and use it only if you must. Of course if the attacker gains physical access to your computer and the user agent, then it is game over. But here we try to protect from the remote attacker. The refresh token should only be used when talking to an auth server or an auth endpoint. If you decide to make it a cookie - you can - just remember to limit the directory path to just the REST endpoints the token is to be passed to.

    Regarding your solution

    It looks good to my eye. Maybe I would not implement the XSRF Token just to save effort. I mean, what is the worst thing that can happen, if someone tries to attack over CSRF? He might be able to make you refresh your token. But the token will not be exposed to the attacker only because of CSRF.

    One more thing

    I like your question. It is really well written! : )