hackforla / hackforla/peopledepot

Update email in db when signing up through Cognito

Open
#257 5 comments 0 reactions 0 assignees View on GitHub
complexity: large ethan feature: SSO milestone: missing PII: FALSE points: missing ready for dev lead role: dev role: dev lead s: PD team size: 3pt
Dominant language
Python
Stars
14
Forks
37
Avg merge
9d 15h
Merged PRs (30d)
5

Description

Status: not fixed

### Overview

As a user, I want the email entered when signing up with Cognito to match the username and email created in the People Depot DB, so that it is clear which record is associated with me.

### Resources
- [ ] [ChatGPT thread](https://chat.openai.com/share/f5def1f4-2c3b-4e6a-819f-98022cdffa77)

### Background

People Depot API is currently only being used in dev and is not called by any app, so developers are testing using Postman or similar tool. Similar issues will occur when in production.

Here is an overview of the steps:
- enter in a URL that allows you to create a new user in Cognito and get a token for that user.
- use Postman or similar tool with the token to call an API.
- When the API is called and the user does not exist in the Django db, a user is created with username equal to a UUID provided by the system. The email is not populated.

### Solution
Currently, jwt.py (to be renamed to jwt_handler) calls authorize from the rest_framework_jwt package. The Django code then based on configuration calls django.contrib.auth.__init__.py which then calls authorize from django.contrib.backends.py. This was derived from locking the database which then sends an exception trace whenit can't insert. Here are the relevant snippets from jwt.py.
```
import jwt
...
jwt.authorize(payload)
```
Through configuration, this calls django.contrib.auth.authorize. Cognito passes the user information defined in this method.

To solve this, override authenticate function in backends.py and replace statement that creates a user to add email as a parameter. The code in backends.py that needs to be replaced is:
user, created = UserModel._default_manager.get_or_create(
**{UserModel.USERNAME_FIELD: username}
)

More details are in Action items.
### Action Items
Note: this is marked as large as you may need to debug if something doesn't work.

- [ ] Rename jwt.py to jwt_handler.py. Do not do any autorefactoring.
- [ ] In settings.py, change the HANDLER constants to this:
```
"JWT_PAYLOAD_GET_USERNAME_HANDLER": "core.utils.jwt_handler.get_username_from_payload_handler",
"JWT_DECODE_HANDLER": "core.utils.jwt_handler.cognito_jwt_decode_handler",
```
- [ ] Create a CustomModelBackend which subclasses from ModelBackend
- [ ] Copy authenticate method for ModelBackend from venv/lib/django/contrib/auth/backends.py into CustomModelBackend
- [ ] Add email as a parameter to authenticate
- [ ] Modify this line:
```
user, created = UserModel._default_manager.get_or_create(
**{UserModel.USERNAME_FIELD: username}
)
```
to
```
user, created = User.objects.create_user( {UserModel.USERNAME_FIELD}=username, email=email, password=password)
```

- [ ] Modify AUTHENTICATION_BACKENDS array in settings.py.
```
AUTHENTICATION_BACKENDS = [
# Replace with a reference to the CustomModelBackend you created in previous step
'core.custom_auth_backends.CustomModelBackend',
# Other authentication backends...
]

```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.