If we're talking about not only working but also secure stateless authentication you will need to consider proper strategy with both access
and refresh
tokens.
Access token is a token which provides an access to a protected resource.
Expiration
here might be installed approximately in ~1 hour (depends on your considerations).
Refresh token is a special token which should be used to generate additional access token
in case it was expired or user session has been updated. Obviously you need to make it long lived (in comparison with access token
) and secure as much as possible.
Expiration
here might be installed approximately in ~10 days or even more (also depends on your considerations).
FYI: Since refresh tokens
are long lived, to make them really secure you might want to store them in your database (refresh token requests are performed rarely). In this way, let's say, even if your refresh token was hacked somehow and someone regenerated access/refresh
tokens, of course you will loose permissions, but then you still can login to the system, since you know login/pass (in case you will use them later) or just by signing in via any social network.
Where to store these tokens?
There are basically 2 common places:
- HTML5 Web Storage (localStorage/sessionStorage)
Good to go, but in the same time risky enough. Storage is accessible via javascript code on the same domain. That means in case you've got XSS, your tokens might be hacked. So by choosing this method you must take care and encode/escape all untrusted data. And even if you did it, I'm pretty sure you use some bunch of 3rd-party client-side modules and there is no guarantee any of them has some malicious code.
Also Web Storage
does not enforce any secure standards during transfer. So you need to be sure JWT is sent over HTTPS
and never HTTP
.
- Cookies
With specific HttpOnly
option cookies are not accessible via javascript and are immune to XSS. You can also set the Secure
cookie flag to guarantee the cookie is only sent over HTTPS.
However, cookies are vulnerable to a different type of attack: cross-site request forgery (CSRF).
In this case CSRF
could be prevented by using some kind of synchronized token patterns. There is good implementation in AngularJS
, in Security Considerations section.
An article you might want to follow.
To illustrate how it works in general:
Few words about JWT itself:
To make it clear there is really cool JWT Debugger from Auth0 guys.
There are 2 (sometimes 3) common claims types: public
, private
(and reserved).
An example of JWT
body (payload, can be whatever you want):
{
name: "Dave Doe",
isAdmin: true,
providerToken: '...' // should be verified then separately
}
More information about JWT
structure you will find here.