-
Notifications
You must be signed in to change notification settings - Fork 21
Authentication Design Doc
Author: Saket Patel
Reviewers: Priyansh Garg
Status: Draft | In Review | Approved
Why do we need authentication?
We want to restrict access to Gymkhana application to the people of the institute. We will identify them via their official email id.
There are two ways we could go about it:
- Basic/Token authentication (email and password mechanism)
- Social authentication (using Google oauth2)
Let's talk about pros and cons of both the methods.
This authentication mechanism allows users to authenticate themselves by using their official mail ID and a password of their choosing. Application will deny authentication if email id is not official.
Users will be shown a form for login and another for signup. Once they sign up, an OTP is sent to their official mail ID, which they need to enter before they are allowed the access to the website. While logging in OTP is not required initially. But later on MultiFactor Authentication can be provided as a feature to make platform more secure for the users.
- No extra library to be used
rest_framework.authtokencan be used for token authentication, after basic authentication. - Login will be available on the institute's intranet when Internet access goes down.
- Introduces complexity in the code as we are taking care of authentication, although we can delegate it to django/rest_framework, some additional mechanisms like sending/verifying OTP while signing user up will need to be taken care of.
- Storing passwords locally on the database.
As our mail server is hosted on Google Workspace, we can leverage Google OAuth2 social authentication to sign/log users in. Users will be given an option to SignUp/LogIn using Official Mail ID on the landing page. When users click on that button they'll be redirected to accounts.google.com for authentication. Once user signs/logs in on the google, they'll be redirected back to the website with an access-token. This access-token is sent to our API which validates it and exchanges it for a local OAuth token for our API. Clients will then use this new OAuth token to authenticate themselves to the API.
- Minimum complexity in the implementation as these mechanisms can be handled by libraries like: drf-social-oauth,
- Some initial configuration might need to be done on Google Cloud Platform to create
client-idandclient-secretfor our API. - One click authentication for the users.
- Users won't be able to login/signup when the Internet access in the institute is down.
I am leaning towards having social authentication initially and if need arises we can always provide basic authentication additionally.
User interaction with the interface and corresponding processes in backend goes like the following:
1. User clicks on Login using Google -> Gets redirected to accounts.google.com for authentication.
2. User authenticates and allows access to information like emailID and public profile -> Gets redirected back to a redirect_uri configures with Google.
3. UI sends the access_token received from Google to the API -> API validates the token internally with Google and generates internal access_token
3. User receives the internal access_token and stores it in the sessionStorage to reuse it.
4. User is logged in -> Moving forward user needs to send this internal access_token with each request to the API.
Above is just the high level view of how it is going to be like. We might face some issues while implementation which are hard to estimate at this point.
We use Google OAuth2 flow to log user in. User journey and API actions that make it work are as follows:
- User clicks on
SIGN INbutton on the UI. - UI redirects the user to Google login page.
- User uses their
iiitdmjaccount to authorize the UI to access itsopenid,profileandemailresources. User will be shown an error if they try to log in using email id that doesn't belong toiiitdmjorganization. - After user successfully signs in to their google account, they are redirected to Gymkhana UI with an
authorization_code. - UI sends the
authorization_codeto the API on/auth/token. - API validates the
authorization_codewith Google, and exchanges it for anid_token. - The
id_tokenis a JSON Web Token (JWT). This JWT is verified using Google's certificates. - The
id_tokenis decoded and user information likeemail,first_name,last_name,profile_pictureis extracted from it. - If user with extracted
emaildoes not exist, then a new account is created for the user and the other user info extracted from theid_tokenis stored in it. - If the user exists
- If a valid token exists, then it is returned to the user.
- If a valid token doesn't exist, new token is sent to the user after deleting the expired token if one exists.
- UI receives the
access_tokenalong with basic user information that was extracted from theid_token. - UI uses this token to access protected API routes by sending it into an
Authorizationheader.
A middleware would be created to authenticate requests having token in Authorization request header. The header value will have Bearer as the token prefix.
This middleware will authenticate the requests and add the user whom the token belongs to to the request. Views can access the authenticated user using request.user.
After user is done using the application, they probably want to log off. We will have an endpoint auth/token:revoke. This will delete the token from the db.