Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend token payload #352

Open
webjunkie opened this issue Sep 1, 2022 · 3 comments
Open

Extend token payload #352

webjunkie opened this issue Sep 1, 2022 · 3 comments

Comments

@webjunkie
Copy link

webjunkie commented Sep 1, 2022

I'm trying to get custom fields into the JWT payload to make things work with Hasura. I can set a custom jwt_payload function, but I get the problem that there is a hardcoded type TokenPayloadType used everywhere which thus throws an error: __init__() got an unexpected keyword argument.

How can I extend tokens to include custom payload?

@webjunkie
Copy link
Author

@KundaPanda can you assist?

@jaydensmith
Copy link

Dirty hack that made this work for me for the time being:

app/utils.py

from calendar import timegm
from datetime import datetime

import strawberry

from strawberry_django_jwt.object_types import TokenPayloadType
from strawberry_django_jwt.settings import jwt_settings


def monkey_patch_payload_type():
    fields = {
        'something': (str, '')
    }

    for field, data in fields.items():
        setattr(TokenPayloadType, field, data[1])
        TokenPayloadType.__annotations__[field] = data[0]

    strawberry.type(TokenPayloadType)

    return TokenPayloadType


def jwt_payload(user, _=None):
    username = user.get_username()

    if hasattr(username, 'pk'):
        username = username.pk

    exp = datetime.utcnow() + jwt_settings.JWT_EXPIRATION_DELTA

    payload = {
        user.USERNAME_FIELD: username,
        'exp': timegm(exp.utctimetuple()),
    }

    if jwt_settings.JWT_ALLOW_REFRESH:
        payload['origIat'] = timegm(datetime.utcnow().utctimetuple())

    if jwt_settings.JWT_AUDIENCE is not None:
        payload['aud'] = jwt_settings.JWT_AUDIENCE

    if jwt_settings.JWT_ISSUER is not None:
        payload['iss'] = jwt_settings.JWT_ISSUER

    payload_data = TokenPayloadType(**payload)
    payload_data.something = 'foo bar'

    return payload_data

app/schema.py

import strawberry

from strawberry_django_jwt.middleware import AsyncJSONWebTokenMiddleware
from app.utils import monkey_patch_payload_type

monkey_patch_payload_type()

...

schema = strawberry.Schema(query=Query, mutation=Mutation, extensions=[
    AsyncJSONWebTokenMiddleware,
])

settings.py

GRAPHQL_JWT = {
    ...
    'JWT_PAYLOAD_HANDLER': 'app.utils.jwt_payload',
}

@webjunkie
Copy link
Author

Thanks!

I also ended up doing it somewhat dirty, by using jwt_encode and jwt_decode to fiddle with the JWT before/after it hits this library.

This can be overwritten in settings as well like

GRAPHQL_JWT = {
    "JWT_ENCODE_HANDLER": "utils.jwt_payload.jwt_encode",
    "JWT_DECODE_HANDLER": "utils.jwt_payload.jwt_decode",
    ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants