Yes, it is a bad UX that the session expire randomly and how to handle this is a whole subject per se.
Here are my two cents:
- Web Apps: If you set an expiration of 1 week, do not use the token for 1 week. Use it for a day and then use the token to get a new token. This way every time your user uses the application, he gets one extra week logged in. This is not different than the normal concept of session and cookies.
If the user does not use your application for a week, next time he go to your app, he will have to login again and this is fine and widely accepted.
- For Mobile/Native Apps: you can use the same explained above, but that's not how most of the mobile applications work these days, I can open facebook after a month without using it and I'm sure I will not need to login again. One way you can do this is to use a refresh token that never expires to fetch a JWT that does expires. The problem with a token that never expires is that it never expires, what happen if your phone is stolen?. In my opinion, there must be a clear and easy interface where the user can revoke these tokens but looking at random alphanumeric characters wont help, so the best practice will be to show something like "Revoke access on John's IPad" this means that the refresh token must be requested for an specific device name.
Certain events can trigger things, if you lost your wallet (at least in Argentina), first thing you do is to call the bank to disable your credit cards. If you forget your laptop in a friend's house and you don't want then to read your Facebook you will probably change your password. Changing the password is usually a good event to
1. Revoke all refresh tokens (for native apps)
2. Anchor the "iss" date for JWTs, this means that tokens issued before the last password change are not longer valid.
Because changing the password can have other purposes, you can also put a prominent button in your UI: "Close session on all browsers and devices", this will delete all refresh token and store the timestamp to check against the JWTs.
We might write a blog post soon about this on Auth0's blog: https://auth0.com/blog.