0

When working with Django OAuth Toolkit, using OIDC if you supply openid as the scope in request you get a id_token with access token. This ID Token can initially be used to identify the user you have got access token for and also create a session.

This is what i am getting in JWT ID Token

{
 "aud": "audience",
 "iat": 1681801110,
 "at_hash": "hash of included access token",
 "sub": "1",
 "given_name": "Dushyant",
 "preferred_username": "dsh",
 "iss": "authEndpointurl",
 "exp": 1681837110,
 "auth_time": 1681567804,
 "jti": "tokenid"
}

But I wish to modify the claims in this JWT ID Token, it reveals the primary key of the database of Authorization Server as the unique id of the user which i don't want in the claim called sub. I want to use another unique key as the value of sub claim. I tried overriding the response a Custom Backend:

class CustomOAuthBackend(OAuthLibCore):
def __init__(self, server):
    super().__init__(server)
    
def create_token_response(self, request):
    response_data = super().create_token_response(request)
    #Modify the response here
    return response_data

And added this as the Custom Backend in the settings. "OAUTH2_BACKEND_CLASS":"pathto.CustomOAuthBackend",

I haven't written any modification code for the response here since the token here is already created When I am calling the original create_token_response.

I want to override it in a way that I can modify the claims dict, I am not sure where it is getting created. We get the id_token all prepared. I want to override the process of creating id_token and change sub claim value.

Let me know if any more information is required.

Update 1: While looking for a possible solution, found oauth2_provider.oauth2_validators have methods get_oidc_claims() and get_id_token_dictionary() which looks like could lead to a possible solution. Figuring out how to use it.

There is a write up in the code

This method is OPTIONAL and is NOT RECOMMENDED. finalize_id_token SHOULD be implemented instead. However, if you want a full control over the minting of the id_token, you MAY want to override get_id_token instead of using finalize_id_token.

This write up talks about get_id_token() method. Going through the code I see that finalize_id_token() is the method where JWT is created from claims. This method calls get_id_token_dictionary then this internally calls get_oidc_claims() then this calls get_claim_dict(request). get_claim_dict(request) only takes a request while others take token etc also. This method looks correct to override as this actually adds that sub claim to claims.

def get_claim_dict(self, request):
    if self._get_additional_claims_is_request_agnostic():
        claims = {"sub": lambda r: str(r.user.id)}
    else:
        claims = {"sub": str(request.user.id)}

    # https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
    if self._get_additional_claims_is_request_agnostic():
        add = self.get_additional_claims()
    else:
        add = self.get_additional_claims(request)
    claims.update(add)

    return claims

I can get claims from this modify it and return the new updated claims.

Dushyant Deshwal
  • 388
  • 4
  • 17

1 Answers1

0

I was able to do it by the same process I mentioned in the question. At the end I override get_claim_dict(self, request) method.

class CustomOAuth2Validator(OAuth2Validator):

  def get_claim_dict(self, request):
       claims = super().get_claim_dict(request)
       claims["sub"] = lambda request: get_user_guid(request=request)
       return claims

I override the get_claim_dict in OAuth2Validator. Add this validator as custom validator in django settings "OAUTH2_VALIDATOR_CLASS": "pathTo.CustomOAuth2Validator",

On decoding the JWT ID Token you will get the new value.

Got New Sub Value

Dushyant Deshwal
  • 388
  • 4
  • 17