Oauth
Precious Leads uses the Django OAuth Toolkit library for everything related to authentication and third party authorization.
This requires every client (React, Mobile app, Zapier, etc) to register first before being able to access the API.
Registering React and Mobile App as clients using Django Admin:
- Go to Applications and click Add Application.
- In Client Type select “Public”.
- In Authorization Grant Type select “Resource Owner Password Based” .
- In Name write a representative name such as “React Frontend” or “Mobile App”.
- IMPORTANT: Uncheck the “Hash client secret”. In this case, the client is Public and the client secret is not used, so this won’t have security consequences. If the secret is hashed, it will cause problems with SSO and OIDC, as explained here.
For local testing, use the following client_ids:
React Front End: xKlT6jSbagp7j3mhxroyq5jv4VneVJYW0cb4SBmd
Mobile App: GxWqvQpR6VjdNqhxsIEDL5WLnOlnVgSb35zDrOOE
Registering Zapier as client using Django Admin:
- Go to Applications and click Add Application.
- In Redirect URIs add the Zapier redirect URI (you can add http://127.0.0.1:8000/noexist/ or any other URL for testing purposes).
- In Client Type select “Confidential”.
- In Authorization Grant Type select “Authorization Code”.
- Copy the client secret before it gets hashed during saving.
- Enable the “Skip Authorization” checkbox, as we will be showing the consent window on the front end, not Django.
- In Name write “Zapier”. This will show up to users during the authorization step.
For local testing, use the following client_ids:
Zapier: 8FlSTYYB1EYHVvk3lkNx6ZfxO5YJskJmSTQOvMeC
Login endpoint for React and Mobile App:
Endpoint: /auth/token/
Request body fields:
{
client_id: xxx
grant_type: password
username: xxx
password: xxx
}
By specifying “password” as grant_type, we will be logging in right away, skipping the authorization code flow.
Response fields:
{
"access_token": "cld0xQsHn1GWGsWZTNj1HxJ5znqAgV",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "read write leads",
"refresh_token": "jp78r8w2UZurlioWU65C8mFTfjtGRu"
}
Front end and mobile app should save both access_token and refresh_token. The refresh token will be used primarily for logging out (revoke).
IMPORTANT: The registration and change password endpoints no longer return a token. The client has to request a token to the token endpoint immediately after registration or changing password.
Logout Endpoint
Endpoint: /auth/revoke_token/
In this endpoint you can revoke either the access token alone or the refresh token.
It is recommended to revoke the refresh token as it will take care of revoking the access token as well.
Request body fields:
{
client_id: xxx
token: xxx
token_type_hint (optional): refresh_token (or access_token if you're revoking only the access_token)
}
Convert Token Endpoint for SSO
Endpoint: /social-auth/convert-token/
When using SSO (for example Google) we need to convert the token Google gives us with an access_token for accessing the API.
Request body fields:
{
client_id: The client id of the React front end or mobile app.
backend: google-oauth2 (For Google. It is different for other apps.)
token: The token given by Google or other apps.
grant_type: convert_token
}
Current SSO Functionality
Here’s how the SSO currently works:
-
If a person logs in with Google and the email does not exist in our database, a new user is automatically created with the Google email, first name, last name, and the password set to “not set.”
-
If a person tries to log in with Google but the email already exists because they previously registered manually, the backend returns an error: “user already exists.” Here, we should consider personalizing the message to something like, “You already have an account, please log in using your email and password.” Another option could be to explore the possibility of “linking” both accounts, allowing the user to log in with either Google or their password.
-
If a person tries to log in manually (with a password) but had previously logged in via Google, the backend will return an error: “credentials not valid” because the password is “not set.” It would also be good to personalize the response message in this case.
-
If a person logs in with Google and then, within the dashboard, tries to “Change Password,” they won’t be able to because the password is “not set.” We need to decide how to handle this situation.
-
If a person logs in with Google and then, within the dashboard, tries to change their email to something like a Hotmail address, they won’t be able to log in with that new email afterward because there is no password set for that user. We need to determine how to address this issue.