djangorestframework-simplejwt
djangorestframework-simplejwt copied to clipboard
Allow User creation after token validation.
Hi ! I've successfully set up a Django project that validates JWTs from AWS Cognito using the JWK_URL
setting.
I ran into a problem though, which is the fact that users making requests to my API don't necessarily have a corresponding record in the local User
table, so JWTAuthentication.get_user
runs into problems. I would like to have the chance to create these users.
I ended up subclassing JWTAuthentication
and made it work by overriding the get_user
method.
I think this could be a good improvement to the library, and is probably a common requirement from users in positions like mine (using external auth).
With a bit of guidance as to how exactly this could/should be implemented, I'd be glad to work on a small PR.
Hi @cristobalmackenzie Good to hear! What you can do is create an import string that allows users to specify how to get the user. An example is the authentication rule callable. Then, in get_user itself, you can check the api settings to see if a callable was set. If it was, pass the data (from the validation) to the callable and return the result. If a callable was not set, you can run the code that is currently there. If that's confusing, create a PR of what you think we should we and we can discuss further :)
Hi @Andrew-Chen-Wang , this is clear and sounds like a good solution to me. I'll work on it and check-in with any updates.
Hi @cristobalmackenzie I'm running into this as I want to use auth0, and was curious how you went about solving this in the end.
Cheers.
I solved this by overriding get_user
in a subclass of django_rest_framework_simplejwt.authentication.JWTAuthentication
. My get_user
validates application-specific claims, resolves any conflict with existing users on user identifiers, and creates users if necessary. Our custom user model captures the iss
and sub
claims as a unique identifier tuple for the user.
Some gotchas you might encounter:
-
email
claim: Django normalizes email addresses viaget_user_model().objects.normalize_email()
. Domains are case insensitive and local portion is case sensitive (shouldn't matter but in some situations it might). -
iss
andsub
are case sensitive claims. If you are saving these fields in your database to query against later, make sure those fields are using a case-sensitive collation.
@cristobalmackenzie, @dcopso . I've been trying setup AWS Cognito using JWK_URL
, but not working, can you give me a example, please, how you did this setup.
My settings.py
SIMPLE_JWT = {
"JWK_URL": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXX/.well-known/jwks.json",
"ALGORITHM": "RS256",
"AUDIENCE": "<my cognito app client>",
"ISSUER": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXX",
}
myview.py
from rest_framework_simplejwt.authentication import JWTAuthentication
class TesteViewSet(
mixins.ListModelMixin,
viewsets.GenericViewSet,
):
queryset = MyModel.objects.all()
serializer_class = TesteSerializer
authentication_classes = [JWTAuthentication]
What more I need to do?
Tks in advance, :)