OAuth implementation research
We will be using RFC-6749 as the reference protocol for our system to implement OAuth 2.0.
Python Package
We will be using jazzband/django-oauth-toolkit for implementing OAuth 2.0 in our system. It follows the RFC standards closely.
Its documentation can be found here.
Overview
Pre-requisites:
An application per tenant would be created using their corresponding API Role Account using a sample link as follow:
http://localhost:8000/backend/o/applications/register/
This would be registered by the loyalty team as an onboarding process.
The sample page would look like this:
Note that Hashing Algorithm has not been selected for Open ID Connect in this image. It provides us a mechanism to add OIDC support with both HMAC and RSA encryption. If these are selected, corresponding SECRET_KEYS must be defined in our system and allows us to use the .well-known URL for public keys.
The client_id and client_secret would then be provided to the customer for integration of our APIs.
For Admin Panel authorization, these would be added in secret keys of containers in our environment variables for their particular deployment.
LMS Admin Panel
The admin panel uses grant_type: “password” to obtain the access token from the service.
A sample payload for calling from the admin panel is as follow:
{
"grant":"password",
"username" : "admin@organizationretain.co",
"password": "admin"
}
and the sample response would be in the shape of the following payload:
{
"access_token": "cBAIuuMULbNhaBbQUKng8hwniNqSQZ",
"expires_in": 36000,
"token_type": "Bearer",
"scope": "read write",
"refresh_token": "4kE4mqmgVam5SDwTVpSJRfiwbv8G9l",
"user": {
"id": 1,
"last_login": "2021-06-23T14:48:38.233402Z",
"is_superuser": true,
"first_name": "Admin",
"last_name": "User",
"is_staff": true,
"is_active": true,
"date_joined": "2021-03-30T08:09:45.975000Z",
"username": "admin@organizationretain.co",
"email": "admin@organizationretain.co",
"company": 1,
"phone": null,
"is_verified": true,
"role": null,
"deletion_allowed": true
}
}
API Services
API Services exposed would use the same authorization method as defined in RFC-6749 for obtaining a token. Summary of which is given:
Send the response_type=code to get the first short-lived token. Sample URL would look like the following:
This will redirect you to a page to accept page where you authorize the API usage against your id. The sample page would look like this:
Once you click on Authorize, It will make an API call for obtaining AccessCode by POSTing API URL at
http://localhost:8000/backend/o/token/
with form data sample as follow:
grant_type=authorization_code
code=XnIFBmiIQP8UjCL8A9GV4r1MpQdROe
client_id=geLlVEQc9b6virE9m1WbYGIOMGCnCF050ZqYeQLD
client_secret=NiumSTj244137CoTJn2WwK6RrgDy0ISjtEYpGljxgnSYxmDIRI46iyn6otkCAMixvEr34lx89ZKIXdhaHwdscNL3i6Uk0ip7dNcFkWAJHjxTYNDWhwiGOiAk54ZbtntT
redirect_uri=http%3A%2F%2Flocalhost%3A8001%2Fapi%2Fv1%2Fmember%2Fstatic%2Fdrf-yasg%2Fswagger-ui-dist%2Foauth2-redirect.htmlIf the form data is correct, we will obtain a payload containing the AccessToken. Sample response would look like this:
{ "access_token":"5HW6fJyPnrp0BoRnQzR0wYG0nSHeeF", "expires_in":36000, "token_type":"Bearer", "scope":"read write", "refresh_token":"occ67ZGZbpGtGotWSEuegTvTpkmYTI" }
We can now send this access_token as the following header value in our API calls:
Authorization: Bearer 5HW6fJyPnrp0BoRnQzR0wYG0nSHeeF