Skip to content
This repository was archived by the owner on Dec 6, 2024. It is now read-only.
This repository was archived by the owner on Dec 6, 2024. It is now read-only.

Allow more robust JWT enrichment #29

@com4

Description

@com4

I would like a way to make a more robust JWT modeling some of the claims after OIDC (though not completely compliant). To do this I need access to user information. Currently the token_enricher function is passed only the request object but it doesn't contain any user information since the user is not logged in.

I propose passing all known information to the token_enricher function and letting the user decide exactly what's included in the token. For example:

payload_enricher = getattr(settings, 'JWT_PAYLOAD_ENRICHER', None)
if payload_enricher:
    fn = import_string(payload_enricher)
    enriched_data = fn(
        request=request,
        token_content=content,
        token_obj=token,
        current_claims=extra_data)

    if getattr(settings, 'JWT_PAYLOAD_ENRICHER_OVERWRITE', False):
        extra_data = enriched_data
    else:
        extra_data.update(enriched_data)

This would allow for user functions that look more like this:

# myproject/myapp/jwt_utils.py

def payload_enricher(**kwargs):
    # Keyword Args: request, token_content, token_obj, current_claims

    # The Django HTTPRequest object
    request = kwargs.pop('request', None)

    # Dictionary of the content of the Oauth response. Includes values like
    # access_token, expires_in, token_type, refresh_token, scope
    content = kwargs.pop('token_content', None)

    # The oauth2_provider access token (by default:
    # oauth2_provider.models.AccessToken)
    token = kwargs.pop('token_obj', None)

    # The automatically generated claims. This usually includes your
    # JWT_ID_ATTRIBUTE and scope. This can be useful if you want to use
    # JWT_PAYLOAD_ENRICHER_OVERWRITE mode.
    current_claims = kwargs.pop('current_claims', None)

    # Values returned here must be serializable by json.dumps
    return {
        'sub': token.user.pk,
        'preferred_username': token.user.username,
        ...
    }

This implementation "works for me" but it may break backward compatibility with existing enrichment functions that accept a single named parameter (this should be fixed in the future by updating the documentation to accept **kwargs as in the above example).

I've opened a pull request (#30) if this is something others would find value in.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions