Giter Site home page Giter Site logo

otot-c's Introduction

CS3219 OTOT Task C

Task C: Authentication and Authorisation Task

Table of Content

Motivation

This application simulates authentication through the use of user logins and role-based authentication.

In the case of the Public, they can only successfully access /. This can be any arbitrary website that allows any visitor to only read its contents, this can be a messaging board like Reddit or a (non-paywalled) news website.

A User differs from Public as they are allowed to view information that's gated behind a login, this functions similar to social media platforms where a curated social feed is served to you based on your preference or the ability to view as many Medium articles as you desire.

The role of Admin here is used to illustrate that there are some actions that only an Admin can execute due to their elevated privilege while the public or a normal User can't. In this application, an Admin is allowed to view everyone's information (password is hashed as has been omitted out). In reality, an Admin is very likely to have full CRUD access over the application or infrastructure, which means that they would have the ability to remove or edit any resource such as removing bad actors from their system, or manually resetting another user's password.

To summarise, this report showcases how authentication and authorisation is implemented via JWT using the NestJS. The example is simulated is a simple user database that allows users to login, view their own data, and view the data of others if the have enough authorisation.

Why NestJS instead of Express?

  1. NestJS is built on top of Express, and I wanted to explore what it offers.
  2. Its integration with JWT and role-based authentication is well-documented.
  3. NestJS also nicely integrates with the popular Express-compatible authentication middleware, Passport.
  4. The structure enforced by NestJS' boilerplate-generation (nest new <project_name>) makes it easy to extend the application for all sorts of strategies.

Routes Planning

Route HTTP Code Inputs Role Response
/ 200 Public "Greetings EVERYONE!"
/auth/login 201 Valid user credentials Public Access token object
/auth/login 401 Invalid user credentials Public "Invalid credentials"
/me 200 Valid token Admin/User Own user info, token details
/me 401 No token or invalid token Public "Unauthorized"
/profile/:username 200 Valid token, role, username Admin User info of username
/profile/:username 404 Valid token, role, Admin "username not found"
/profile/:username 403 Valid token, username User "Forbidden resource"
/profile/:username 401 No token or invalid token Public "Unauthorized"

HTTP Error 401 Vs 403

This being the main point of the task can be broken down as such.

Error 401 indicates that the request does not have valid credentials to access a certain resource. This is seen /me where no bearer token or an invalid one is given in the header of the request. This is one way to limit access to a resource from unauthorised users such as bad actors or public access in general.

On the other hand, Error 403 indicates that the request is valid, meaning that they do have access to the resource, but does not have enough privilege to access, where privilege here is explored through role-based authentication. As seen in /profile/:username, anyone without the admin role would be met with an "Unauthorized" message as this resource works with the intention that admins can view the information of all users, excluding their passwords (which are hashed in the database).

Requirements

  1. NodeJS
  2. NestJS
  3. Jest (recommended, quick way to show that it's working)
  4. Postman (easier to inspect requests)
    • You may refer to the collection here.
    • Collection utilises Test to set the Authorization headers of a request through environmenet variables.

A Record<string,User> is used in place of a database as this is a proof-of-concept and it makes it easier to test via Jest.

Running the application

# Install dependencies
yarn

# Run the application
yarn start:dev # Hot reloads on change

The application is set to run on http://localhost:3000.

Implementation Summary

Authentication

This is done by extending the PassportStrategy of @nestjs/passport and doing a simple validation to check if the provided username and password (via argon2's verify function) matches what is stored in the (mock) database. The AuthGuard decorator is also used to apply the need for authentication in /auth/login

Related files:

Authorisation

Also utilising AuthGuards and PassportStrategy from @nestjs/passport, a JWT strategy is created to authorise requests with specific JWTs. Role-based authentication is then applied here by ensuring that the specified roles of certain routes are met to prevent unauthorised access.

Related files:

Testing the application

Expected values of the tests are based on Routes Planning.

Running Jest

yarn test

Testing with Postman

Request name Description
/ Test that anyone can access this endpoint
auth/login -- user Logs in as userBob, returns access token which is set the collection variable token to test me and profile/:username
auth/login -- admin Logs in as adminAlice, returns access token which is sets the collection variable token to test me and profile/:username
auth/login -- invalid Logs in as adminAlice, but sets token with an invalid token
me Returns the profile associated to the user if token is valid
profile/:username Returns profile assocated to the given username, if token has admin role

Note: For demonstration purposes, auth/login -- invalid sets the token to "THIS_IS_INVALID".

Credentials

Here are the following credentials for the mock database:

Username Password Role
adminAlice alice_password Admin, User
userBob bob_password User
unknown unknown User

Jest Screenshot

jest-image

Refer to ./test/app.e2e-spec.ts for the test details, or manually test with Postman with the collection here.

Extending this task

  1. Refresh token
    • Currently the tokens are set to expire in 300 seconds.
    • Popular websites implement refresh tokens, typically through /refresh, to allow users to stay logged in to a website for an extended amount of time.
      • "Remember me for 30 days"
  2. Explore other Passport strategies
  3. Explore class-validator and class-transformer to ensure that the proper login credentials are given.
    • Currently assumes that user would give according to what is needed.
    • Transform the password to its hashed version before sending the request as the password is currently being sent in plaintext.

otot-c's People

Contributors

yusufaine avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.