When a client logs in, issue them a JWT with an expiration (more on this below). On subsequent API requests, send that token in an Authorization
header as a Bearer
token. This token can be stored in localStorage
, which is the most common, so that if the user revisits the site or refreshes the page, they are still logged in. Other client-side storage options like sessionStorage
or a cookie can be used. JWTs can get big though depending on how much information is stored in the payload, which could exceed the maximum cookie size (4K).
When an API call is made with an expired token, return a 401 HTTP status code and redirect users to the login page.
One approach is to have a /refresh
endpoint. This endpoint can take the current token and give you a new one. This endpoint will only return a new token if the current token is about to expire. Otherwise, it will return the same active token.
Another approach that is similar but more complex involves refresh tokens. Check out Refresh Token Rotation.
To log out a user, delete that token from the client-side storage. The drawback of this is that just deleting the token from the client doesn't invalidate the token. In theory, if someone had that token, it could still be used.
Keep track of the tokens in a database. When a user wants to log out, delete the token from the database. When verifying tokens on API calls, check if the token is in the database. There isn't really a standard for this and I've heard of different implementations.
What seems to be pretty common is to have a sufficient expiration time (7-30 days) which likely won't disrupt the UX too much and involves the least amount of development work. However, this is a bigger window and could increase the liklihood for a compromised token. Additionally, you may read about recommendations to have a really short expiration (like 5 minutes). With a short expiration, you'll need to have token refreshing in place to not result in a terrible UX. This involves much more development work.