Are you tired of worrying about user authentication and authorization in your NestJS applications and want role-based authorization? Look no further! This project provides a comprehensive, battle-tested solution for managing user access and permissions, so you can focus on building amazing apps.
Built for developers, by developers
Whether you're a solo dev or part of a team, this project is designed to help you:
-
Secure your app with robust authentication and authorization
-
Scale your solution with confidence
-
Customize access control to fit your unique needs
POST http://localhost:3000/users/signup
Parameter | Type | Description |
---|---|---|
username,password,email |
string |
Required. Running database |
POST http://localhost:3000/auth/login
Parameter | Type | Description |
---|---|---|
username,password |
string |
Required. |
GET http://localhost:3000/profile
Parameter | Type | Description |
---|---|---|
username,password |
string |
Required. Jwt Access Token |
POST http://localhost:3000/profile
Parameter | Type | Description |
---|---|---|
username,password |
string |
Required. Jwt Bearer Token |
POST http://localhost:3000/admin/signup
Parameter | Type | Description |
---|---|---|
username,password,email |
string |
Required. Running database |
POST http://localhost:3000/auth/login
Parameter | Type | Description |
---|---|---|
username,password |
string |
Required. |
GET http://localhost:3000/profile
Parameter | Type | Description |
---|---|---|
username,password |
string |
Required. Jwt Access Token |
POST http://localhost:3000/profile
Parameter | Type | Description |
---|---|---|
username,password |
string |
Required. Jwt Bearer Token |
Any additional information goes here
Add badges from somewhere like: shields.io
Contributions are always welcome!
See contributing.md
for ways to get started.
Please adhere to this project's code of conduct
.
To deploy this project run
npm run start:dev
To run this project, you will need to add the following environment variables to your .env file. You can customize it the way you want :
DB_PORT='5432'
DB_USERNAME='postgres'
DB_PASSWORD='root'
DB_DATABASE='passportdb'
A: This usually happens when the user does not have the required role to access the route. Ensure that the @Roles()
decorator is correctly applied to the route, and that the RolesGuard is verifying the roles correctly. Check that the user's role is included in the JWT payload when generating the token in auth.service.ts
. Log the roles in the RolesGuard to ensure the correct roles are being checked, and verify that the roles are passed as an array in both the JWT payload and the user object.
A: This error occurs when roles is not an array, and you're trying to call array methods like includes() or find() on a non-array value. Ensure that the roles passed from the @Roles()
decorator and in the JWT payload are arrays. In the RolesGuard, add a check to ensure roles is an array using Array.isArray()
:
if (!roles || !Array.isArray(roles)) {
return true; // No roles required, allow access
}
A: This happens when the role is not included in the payload when generating the JWT token in AuthService. Ensure that the role is part of the user object when generating the JWT in auth.service.ts:
const payload = { username: user.username, sub: user.userId, roles: [user.role] };
Also, make sure that the roles are properly included when validating the token in jwt.strategy.ts:
return { userId: payload.sub, username: payload.username, roles: payload.roles };
A: This can happen if the authentication logic is only checking the UsersService and not the AdminService when validating the user credentials. Ensure that in auth.service.ts, you're checking both the UsersService for regular users and the AdminService for admins:
const user = await this.userService.findOne(username);
if (!user) {
const admin = await this.adminService.findOne(username);
// Check admin login
}
A: This happens if the @Roles() decorator is hardcoded or incorrectly set, causing the guard to always receive the same role. Ensure that the @Roles() decorator is correctly applied on routes and dynamically sets roles based on the expected access level:
@Roles('admin') // For admin routes
@Roles('user') // For user routes
A: This occurs if the roles are not being properly set or returned in the validate method of jwt.strategy.ts. Ensure that the validate function in jwt.strategy.ts returns the roles array from the JWT payload:
async validate(payload: any) {
return { userId: payload.sub, username: payload.username, roles: payload.roles };
}
A: This might happen if the validateUser method in AuthService is not correctly validating credentials or if the password comparison using bcrypt fails. Verify that the user exists in the database by checking the UsersService and AdminService in validateUser, and ensure that bcrypt.compare() is properly comparing the plain-text password with the hashed password stored in the database.
A: The expiration time of the JWT token is controlled by the expiresIn option in AuthService. If set too low, the token will expire quickly. Adjust the expiresIn value in the generateAccessToken method to a higher value if needed:
return this.jwtService.sign(payload, { expiresIn: '3600s' }); // 1 hour
A: This could happen if the refresh token is not validated correctly or if the validateRefreshToken method in AuthService is not correctly implemented. Ensure that the refresh token is properly validated in validateRefreshToken:
const payload = this.jwtService.verify(token);
Check that the refresh token has a longer expiresIn value than the access token, and ensure the correct user data is returned from the refresh token validation.
- Role-Based Access Control
- JSON Web Token Authentication
- Customizable Authentication Flow
- Environment Variable Configuration
- Database Support
- Error Handling and Logging
- Cross-Platform Compatibility
If you have any feedback, please reach out to me at https://www.linkedin.com/in/atiq-ur-rehman-1314712aa/
I'm a full stack developer...
wokring in Angular | NestJs | Django | Amazon Aws
π©βπ» I'm currently working on Backend
π§ I'm currently learning NestJs
π―ββοΈ I'm looking to collaborate on full Stack Projects
π€ I'm looking for help with getting Internship
Typescript, Javascript, HTML, CSS, Python
Install my-project with npm
cd my-project
npm install
Files Involved: role.enum.ts
- I learned that defining roles in an enum file like roles.enum.ts allows for effective role management.
- By using enums, I can define roles such as admin and user and integrate these roles into the system consistently.
- This ensures that roles are standardized across the application, especially when used in role-based access control.
Files Involved: user.entity.ts, admin.entity.ts
- I added a role column to both the User and Admin entities.
- This column helps assign a specific role to each user or admin in the system.
- When retrieving users from the database, this role is included in the JWT token to handle role-based authorization.
Files Involved: create-user.dto.ts, create-admin.dto.ts
- I ensured that when creating users or admins, the role attribute is included in the DTOs (Data Transfer Objects).
- This guarantees that the role is part of the request structure when creating new users or admins, making the role available for authorization checks.
Files Involved: roles.decorator.ts, roles.guard.ts
- I created a Roles decorator (roles.decorator.ts) to specify which roles are allowed to access specific routes.
- The decorator allows me to define which roles (e.g., admin or user) are required to access a route.
- The RolesGuard (roles.guard.ts) then enforces these role requirements.
- Initially, I faced issues when the guard failed due to roles.includes not being a function, but I fixed this by ensuring roles was always an array.
Files Involved: auth.service.ts, jwt.strategy.ts, local.strategy.ts
- I implemented a system where both admins and users can log in using the same authentication service.
- Initially, I faced an issue where only user logins were working because I was only checking UsersService for validation.
- I solved this by adding a check for AdminService in AuthService, ensuring that both admins and users can log in and receive their respective JWT tokens.
Files Involved: auth.service.ts, jwt.strategy.ts
- I encountered an issue where the role was not included in the JWT payload, which caused the role guard to fail.
- To resolve this, I updated the generateAccessToken and generateRefreshToken methods in auth.service.ts to include the user's role in the JWT payload.
- Additionally, I fixed the JwtStrategy to ensure the roles were extracted correctly from the token payload.
Files Involved: app.controller.ts, roles.guard.ts
- When trying to access the /profile route, I encountered a 403 Forbidden error even though the correct roles were assigned.
- This was due to the roles not being properly included in the JWT or not being correctly handled in the JwtStrategy.
- Once I ensured that the roles were properly extracted and passed through the RolesGuard, the issue was resolved, and admins were able to access admin-only routes.
Files Involved: roles.guard.ts
- The RolesGuard initially threw errors like roles.includes is not a function.
- This happened because roles was not always an array.
- After adding checks to ensure roles was an array, I was able to resolve the issue and properly enforce role-based access control. I also learned to log the roles and user.roles to debug these types of issues effectively.
Files Involved: roles.guard.ts, jwt.strategy.ts
- Another issue arose when I consistently received a Forbidden resource error after login.
- The problem was that the roles in the JWT payload were not correctly handled in the RolesGuard or JwtStrategy.
- I learned to ensure that the roles are properly encoded in the JWT and extracted correctly during validation to allow access to routes based on roles.
Files Involved: app.controller.ts, roles.guard.ts
- After resolving the role-based access issues, I tested the functionality by creating separate routes for users and admins, applying the @Roles() decorator to protect the routes.
- By using Postman to test login and accessing the protected routes, I confirmed that only admins could access admin-only routes and users could not.
Here are some related projects
To run tests, run the following command
npm run test
unit tests :
npm run test
e2e tests :
$ npm run test:e2e
test coverage:
npm run test:cov
Clone the project
git clone https://github.com/AtiqBytes/passport-jwt-nestjs.git
Go to the project directory
cd my-project
Install dependencies
npm install
Start the server
npm run start:dev