There is no way I know of to arbitrarily invalidate a token without involving a database one way or another.
Be careful with Approach 2 if your service can be accessed on several devices. Consider the following scenario...
- User signs in with iPad, Token 1 issued and stored.
- User signs in on website. Token 2 issued. User logs out.
- User tries to use iPad, Token 1 was issued before user logged out from website, Token 1 now considered invalid.
You might want to look at the idea of refresh tokens although these require database storage too.
Also see here for a good SO discussion regarding a similar problem, particular IanB's solution which would save some db calls.
Proposed solution
Personally, this is how I'd approach it...user authenticates, issued with access token with a short expiry (say 15 mins) and a refresh token valid either for a much longer period or indefinitely. Store a record of this refresh token in a db.
Whenever the user is 'active', issue a new auth token each time (valid for 15 mins each time). If the user is not active for over 15 minutes and then makes a request (so uses an expired jwt), check the validity of the refresh token. If it's valid (including db check) then issue a new auth token.
If a user 'logs out' either on a device or through a website then destroy both access refresh tokens client side and importantly revoke the validity of the refresh token used. If a user changes their password on any device, then revoke all their refresh tokens forcing them to log in again as soon as their access token expires. This does leave a 'window of uncertainty' but that's unavoidable without hitting a db every time.
Using this approach also opens up the possibility of users being able to 'revoke' access to specific devices if required as seen with many major web apps.