From 51e3a545d7380e5b1983b0a1e8b5088a88efe522 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Thu, 2 May 2024 16:44:06 +0300 Subject: Include refresh tokens with generated JWT This shim enables us to have a refresh token with the JWT. This might not be the way to refresh JWTs - this is because the `authlib.oauth2.rfc7523.token.JWTBearerTokenGenerator.__call__(…)` method has a comment that states: # there is absolutely no refresh token in JWT format Searching on the internet, however, seems to indicate that JWTs can be used in conjunction with refresh tokens... We need to verify this and fix this if necessary. --- .../oauth2/grants/jwt_bearer_grant.py | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'gn_auth/auth') diff --git a/gn_auth/auth/authentication/oauth2/grants/jwt_bearer_grant.py b/gn_auth/auth/authentication/oauth2/grants/jwt_bearer_grant.py index 895acb7..8e2f082 100644 --- a/gn_auth/auth/authentication/oauth2/grants/jwt_bearer_grant.py +++ b/gn_auth/auth/authentication/oauth2/grants/jwt_bearer_grant.py @@ -1,6 +1,7 @@ """JWT as Authorisation Grant""" from flask import current_app as app +from authlib.common.security import generate_token from authlib.oauth2.rfc7523.jwt_bearer import JWTBearerGrant as _JWTBearerGrant from authlib.oauth2.rfc7523.token import ( JWTBearerTokenGenerator as _JWTBearerTokenGenerator) @@ -30,6 +31,25 @@ class JWTBearerTokenGenerator(_JWTBearerTokenGenerator): "sub": str(tokendata["sub"])} + def __call__(self, grant_type, client, user=None, scope=None, + expires_in=None, include_refresh_token=True): + # there is absolutely no refresh token in JWT format + """ + The default generator does not provide refresh tokens with JWT. It goes + so far as to state "there is absolutely no refresh token in JWT format". + + This shim allows us to have a refresh token. We should probably look for + a supported way of using JWTs with refresh capability. + """ + token = self.generate(grant_type, client, user, scope, expires_in) + if include_refresh_token: + return { + **token, + "refresh_token": generate_token(length=42) + } + return token + + class JWTBearerGrant(_JWTBearerGrant): """Implement JWT as Authorisation Grant.""" @@ -57,3 +77,17 @@ class JWTBearerGrant(_JWTBearerGrant): Check if the client has permission to access the given user's resource. """ return True # TODO: Check this!!! + + def create_token_response(self): + """If valid and authorized, the authorization server issues an access + token. + """ + token = self.generate_token( + scope=self.request.scope, + user=self.request.user, + include_refresh_token=self.request.client.check_grant_type( + "refresh_token") + ) + app.logger.debug('Issue token %r to %r', token, self.request.client) + self.save_token(token) + return 200, token, self.TOKEN_RESPONSE_HEADER -- cgit v1.2.3