Revoking Tokens
Contents
Revoking Tokens#
Note
This functionality is introduced in version 0.3.0.
Sometimes, you want to revoke a token. As João Angelo wrote:
In general the easiest answer would be to say that you cannot revoke a JWT token, but that’s simply not true. The honest answer is that the cost of supporting JWT revocation is sufficiently big for not being worth most of the times….
There are plenty of times that you want to revoke a token. However, you can’t just reach into the person’s browser and remove it, though. You have to indicate to the browser (or whatever client) that the token is no longer good.
If expiration is not good enough, and you
need “immediate token revocation” as it’s called, then the
Authenticator has the functionality for you.
Each token generated by an Authenticator has the
"jti"
claim in it. This allows you to “track” the issued JWT and,
if needed, invalidate it.
To invalidate a token, you’ll need to store the identifier somewhere so that you can tell if it’s good or not. This is essentially a session-tracking mechanism.
Here’s an example of the two-step process for how to do this
with the jwtdown-fastapi.
Override jti methods#
There are there are three methods to override:
get_session_getterwhich uses FastAPI’s dependency injection mechanism to get an instance of the thing you use to manage session datajti_createdwhich alerts you to when a new JWT is created and there is a new"jti"claim which will happen during the login processjti_destroyedwhich alerts you to when a JWT has expired and the"jti"claim is no longer any good, or during the logout processvalidate_jtiwill get called whenever someone tries to access a protected endpoint and, if it returnsFalse, then the person will not be allowed to access that protected endpoint
# authenticator.py
import os
from fastapi import Depends
from jwtdown_fastapi.authentication import Authenticator
from queries.accounts import AccountRepo, AccountOut, Account
from queries.sessions import SessionRepo
class MyAuthenticator(Authenticator):
# Other overridden methods
def get_session_getter(self, session_repo: SessionRepo = Depends()):
return session_repo
async def jti_created(self, jti, account, session_repo):
await session_repo.create(jti, account)
async def jti_destroyed(self, jti, session_repo):
await session_repo.delete(jti)
async def validate_jti(self, jti, session_repo):
return session_repo.get(jti) is not None
authenticator = MyAuthenticator(os.environ["SIGNING_KEY"])
Implement a revocation endpoint#
In your application, you will need a way to revoke a valid JWT. You can create an endpoint that lets you do that.
# router.py
@router.delete("/api/sessions/{account_id}", response_model=bool)
async def delete_session(
account_id: str,
account_data: dict = Depends(authenticator.get_current_account_data),
session_repo: SessionRepo = Depends(),
) -> bool:
if "admin" in account_data["roles"]:
session_repo.delete_sessions(account_id)
return True
return False