-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: to use AuthenticationMiddleware instead of decode token in …
…create chat
- Loading branch information
Showing
8 changed files
with
172 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { PayloadUser } from '../interfaces/payload-user.interface'; | ||
|
||
export {}; | ||
|
||
declare global { | ||
namespace Express { | ||
interface Request { | ||
user: PayloadUser; | ||
} | ||
} | ||
} | ||
req.user; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { NextFunction, Request, Response } from 'express'; | ||
|
||
import { AttachCookiesToResponse } from '../../utils/response-cookies'; | ||
import { UnauthenticatedError, UnauthorizedError } from '../../domain/errors'; | ||
import { JWTAdapter } from '../../config/jwt.adapter'; | ||
import { UserRoles } from '../../domain/interfaces/payload-user.interface'; | ||
|
||
/** | ||
* Middleware class for authentication and authorization. | ||
*/ | ||
export class AuthMiddleware { | ||
/** | ||
* Constructs an instance of AuthMiddleware. | ||
* @param jwt - Instance of JWTAdapter for handling JSON Web Tokens. | ||
*/ | ||
constructor(private readonly jwt: JWTAdapter) {} | ||
|
||
/** | ||
* Middleware for authenticating user requests. | ||
*/ | ||
public authenticateUser = async ( | ||
req: Request, | ||
res: Response, | ||
next: NextFunction | ||
) => { | ||
const { refreshToken, accessToken } = req.signedCookies; | ||
|
||
// Check if refresh token and access token are present | ||
if (!refreshToken && !accessToken) | ||
throw new UnauthenticatedError('Please first login'); | ||
|
||
if (accessToken) { | ||
// Validate access token | ||
const payload = this.jwt.validateToken(accessToken); | ||
if (!payload) throw new UnauthorizedError('Invalid token validation'); | ||
req.user = payload.user; | ||
const wsToken = this.jwt.generateToken({ user: payload.user }, '1d'); | ||
req.user.wsToken = wsToken; | ||
return next(); | ||
} | ||
|
||
// Validate refresh token | ||
const payload = this.jwt.validateToken(refreshToken); | ||
if (!payload) throw new UnauthorizedError('Invalid token validation'); | ||
|
||
const { user } = payload; | ||
|
||
// Generate new tokens | ||
const accessTokenJWT = this.jwt.generateToken({ user }, '15m'); | ||
const refreshTokenJWT = this.jwt.generateToken( | ||
{ user, refreshToken }, | ||
'1d' | ||
); | ||
|
||
// Attach new tokens to response cookies | ||
AttachCookiesToResponse.attach({ | ||
res, | ||
accessToken: accessTokenJWT!, | ||
refreshToken: refreshTokenJWT!, | ||
}); | ||
|
||
req.user = user; | ||
req.user.wsToken = accessTokenJWT; | ||
next(); | ||
}; | ||
|
||
/** | ||
* Middleware for authorizing user permissions based on roles. | ||
* @param roles - Roles allowed to access the resource. | ||
*/ | ||
public authorizePermissions = (...roles: UserRoles[]) => { | ||
return (req: Request, res: Response, next: NextFunction) => { | ||
const { role } = req.user; | ||
|
||
if (role === 'admin') return next(); | ||
|
||
if (!roles.includes(role!)) | ||
throw new UnauthorizedError('Unauthorized to access this resource'); | ||
|
||
next(); | ||
}; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { Response } from 'express'; | ||
import { envs } from '../config/envs'; | ||
|
||
interface Options { | ||
res: Response; | ||
accessToken: string; | ||
refreshToken: string; | ||
} | ||
|
||
/** | ||
* Utility class for attaching cookies to the response. | ||
*/ | ||
export class AttachCookiesToResponse { | ||
/** | ||
* Method to attach access and refresh tokens as cookies to the response. | ||
* @param options - Object containing response object and token values. | ||
*/ | ||
static attach({ res, accessToken, refreshToken }: Options) { | ||
// Define cookie expiration times | ||
const oneMinute = 1000 * 60; | ||
const oneDay = 1000 * 60 * 60 * 24; | ||
|
||
// Attach access token cookie to the response | ||
res.cookie('accessToken', accessToken, { | ||
httpOnly: true, | ||
secure: envs.NODE_ENV === 'production', | ||
signed: true, | ||
expires: new Date(Date.now() + oneMinute), | ||
}); | ||
|
||
// Attach refresh token cookie to the response | ||
res.cookie('refreshToken', refreshToken, { | ||
httpOnly: true, | ||
expires: new Date(Date.now() + oneDay), | ||
secure: envs.NODE_ENV === 'production', | ||
signed: true, | ||
}); | ||
} | ||
} |