Comments (8)
Hi @anyeone, you are correct that the idea was that this should be implemented by the project. But we can definitely add an example.
We use the following:
def get_or_create_for_cognito(self, payload):
cognito_id = payload['sub']
try:
return self.get(cognito_id=cognito_id)
except self.model.DoesNotExist:
pass
try:
first_name = payload.get('given_name', None)
last_names = [
payload.get('middle_name', None),
payload.get('family_name', None)
]
last_name = ' '.join(filter(None, last_names)) or None
user = self.create(
cognito_id=cognito_id,
email=payload['email'],
is_active=True,
first_name=first_name,
last_name=last_name)
except IntegrityError:
user = self.get(cognito_id=cognito_id)
return user
from django-cognito-jwt.
@mikedebock Thanks for the detailed explanation.
In the meantime, it seems cognito_id(which is in uuid4) is used for querying the user database; I would perhaps change the code a little more efficient in fetching the user object.
You may or may not make cognito_id the primary key, but I think it should at least be indexed.
import uuid
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.auth.models import UserManager as _UserManager
from django.db import models
class UserManager(_UserManager):
def get_or_create_for_cognito(self, payload):
cognito_id = payload['sub']
try:
return self.get(cognito_id=cognito_id)
except self.model.DoesNotExist:
pass
try:
user = self.create(
cognito_id=cognito_id,
email=payload['email'],
is_active=True)
except IntegrityError:
user = self.get(cognito_id=cognito_id)
return user
class User(AbstractBaseUser, PermissionsMixin):
cognito_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
objects = UserManager()
from django-cognito-jwt.
Hi @anyeone, you are correct that the idea was that this should be implemented by the project. But we can definitely add an example.
We use the following:
def get_or_create_for_cognito(self, payload): cognito_id = payload['sub'] try: return self.get(cognito_id=cognito_id) except self.model.DoesNotExist: pass try: first_name = payload.get('given_name', None) last_names = [ payload.get('middle_name', None), payload.get('family_name', None) ] last_name = ' '.join(filter(None, last_names)) or None user = self.create( cognito_id=cognito_id, email=payload['email'], is_active=True, first_name=first_name, last_name=last_name) except IntegrityError: user = self.get(cognito_id=cognito_id) return user
Where do I add this definition?
from django-cognito-jwt.
Hi @mhoonjeon, you're right that a additional cognito_id
field should be added to the UserModel, I'll add that to the example above.
The difference between this JWT implementation and the DRF token is that we don't store the (JWT) token in the db, but only the Cognito user id (in the column cognito_id
).
The payload argument in the get_or_create_for_cognito
is a dict which contains user data (see: https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html#user-pool-id-token-payload).
We use the value of sub
which contains the UUID (Cognito's user-id) to create a user.
The django_cognito_jwt.JSONWebTokenAuthentication
queries every time the UserModel to populate request.user
so it is available for the DRF views.
from django-cognito-jwt.
@mvantellingen How are you getting the payload values in your example method? The call to get_or_create_for_cognito
is sending the jwt_payload
which is the access token from Cognito. We need the ID token to get the claims about the authenticated user.
from django-cognito-jwt.
Realized that the ID token is what's expected in the auth header. I've added a PR #9 to make that more clear.
from django-cognito-jwt.
Hi @aurashn,
You should add this to the UserManager of your UserModel.
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.auth.models import UserManager as _UserManager
class UserManager(_UserManager):
def get_or_create_for_cognito(self, payload):
cognito_id = payload['sub']
try:
return self.get(cognito_id=cognito_id)
except self.model.DoesNotExist:
pass
try:
user = self.create(
cognito_id=cognito_id,
email=payload['email'],
is_active=True)
except IntegrityError:
user = self.get(cognito_id=cognito_id)
return user
class User(AbstractBaseUser, PermissionsMixin):
cognito_id = models.CharField(max_length=128, blank=True)
objects = UserManager()
from django-cognito-jwt.
@mikedebock Hi. I'm trying to understand how this library works to see if we should move our auth-related apis from DRF to AWS cognito. If I understand correctly, the auth workflow is as follows(correct me if I'm wrong).
- Client app requests cognito for auth, which returns tokens including id_token in JWT format.
- Client app then uses the JWT id_token to call the DRF backend. The get_or_create_for_cognito() is called, meaning cognito_id is mapped to the specific user in database.
If looks like here we save the cognito_id in the database, which baffles me. I thought the whole point of using JWT instead of the default DRF token was NOT to save the token on db & remove the necessity to query database on every request - and this should be better for scalability.
Am I understanding this right? If so, could you explain the logic behind your implementation?
ps: Additional question - do we have to add a custom cognito_id
field to the user table, if we decide to use the library?
from django-cognito-jwt.
Related Issues (20)
- Example authentication flow? HOT 5
- AWS Lambda
- ValueError: too many values to unpack (expected 2) After use customized `User` model HOT 1
- Python 3.5 does not support f' format HOT 3
- How to solve `Customized User` clash with `User`? HOT 5
- Unable to accept Cognito Access Tokens HOT 2
- Cognito Audience Optional HOT 1
- `.get_public_key` in TokenValidator return None
- Can i add Multiple Clients/Audience Id in django settings.py HOT 1
- How to use this library with GraphQL?
- LICENSE file should be packaged to the pypi archive
- Using the Django admin interface HOT 2
- WrappedAttributeError at / module 'jwt' has no attribute 'ExpiredSignature' HOT 3
- token_validator giving urllib3 error
- ImportError: cannot import name 'RSAAlgorithm'.
- Replace ugettext and smart_text with proper functions for Django 4 compatibility
- validate token error HOT 1
- Can this package work for EXTERNAL_PROVIDER HOT 1
- Investigate if we can support the new alb auth HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-cognito-jwt.