build(authentication): Add Authentik strategy, import new passport oidc module, add swagger desc for roles guard, remove index for auth modules
This commit is contained in:
parent
d70bdab1e9
commit
58287dcac3
48
package-lock.json
generated
48
package-lock.json
generated
|
|
@ -21,6 +21,7 @@
|
||||||
"class-validator": "^0.14.2",
|
"class-validator": "^0.14.2",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
|
"passport-openidconnect": "^0.1.2",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1"
|
||||||
},
|
},
|
||||||
|
|
@ -36,6 +37,7 @@
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^22.10.7",
|
"@types/node": "^22.10.7",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
|
"@types/passport-openidconnect": "^0.1.3",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
|
|
@ -3354,6 +3356,16 @@
|
||||||
"undici-types": "~6.21.0"
|
"undici-types": "~6.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/oauth": {
|
||||||
|
"version": "0.9.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.6.tgz",
|
||||||
|
"integrity": "sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/passport": {
|
"node_modules/@types/passport": {
|
||||||
"version": "1.0.17",
|
"version": "1.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz",
|
||||||
|
|
@ -3373,6 +3385,19 @@
|
||||||
"@types/passport-strategy": "*"
|
"@types/passport-strategy": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/passport-openidconnect": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/passport-openidconnect/-/passport-openidconnect-0.1.3.tgz",
|
||||||
|
"integrity": "sha512-k1Ni7bG/9OZNo2Qpjg2W6GajL+pww6ZPaNWMXfpteCX4dXf4QgaZLt2hjR5IiPrqwBT9+W8KjCTJ/uhGIoBx/g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/express": "*",
|
||||||
|
"@types/oauth": "*",
|
||||||
|
"@types/passport": "*",
|
||||||
|
"@types/passport-strategy": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/passport-strategy": {
|
"node_modules/@types/passport-strategy": {
|
||||||
"version": "0.2.38",
|
"version": "0.2.38",
|
||||||
"resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz",
|
"resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz",
|
||||||
|
|
@ -8689,6 +8714,12 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/oauth": {
|
||||||
|
"version": "0.10.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.2.tgz",
|
||||||
|
"integrity": "sha512-JtFnB+8nxDEXgNyniwz573xxbKSOu3R8D40xQKqcjwJ2CDkYqUDI53o6IuzDJBx60Z8VKCm271+t8iFjakrl8Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
|
|
@ -8930,6 +8961,23 @@
|
||||||
"passport-strategy": "^1.0.0"
|
"passport-strategy": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/passport-openidconnect": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/passport-openidconnect/-/passport-openidconnect-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-JX3rTyW+KFZ/E9OF/IpXJPbyLO9vGzcmXB5FgSP2jfL3LGKJPdV7zUE8rWeKeeI/iueQggOeFa3onrCmhxXZTg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"oauth": "0.10.x",
|
||||||
|
"passport-strategy": "1.x.x"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jaredhanson"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/passport-strategy": {
|
"node_modules/passport-strategy": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
"class-validator": "^0.14.2",
|
"class-validator": "^0.14.2",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
|
"passport-openidconnect": "^0.1.2",
|
||||||
"reflect-metadata": "^0.2.2",
|
"reflect-metadata": "^0.2.2",
|
||||||
"rxjs": "^7.8.1"
|
"rxjs": "^7.8.1"
|
||||||
},
|
},
|
||||||
|
|
@ -47,6 +48,7 @@
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^22.10.7",
|
"@types/node": "^22.10.7",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
|
"@types/passport-openidconnect": "^0.1.3",
|
||||||
"@types/supertest": "^6.0.2",
|
"@types/supertest": "^6.0.2",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ import { ROLES_KEY } from '../decorators/roles.decorators';
|
||||||
import { Roles } from '.prisma/client';
|
import { Roles } from '.prisma/client';
|
||||||
import { JwtPayload } from 'src/modules/authentication/strategies/jwt.strategy';
|
import { JwtPayload } from 'src/modules/authentication/strategies/jwt.strategy';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
interface RequestWithUser extends Request {
|
interface RequestWithUser extends Request {
|
||||||
user: JwtPayload;
|
user: JwtPayload;
|
||||||
}
|
}
|
||||||
|
|
@ -17,6 +19,23 @@ interface RequestWithUser extends Request {
|
||||||
export class RolesGuard implements CanActivate {
|
export class RolesGuard implements CanActivate {
|
||||||
constructor(private reflector: Reflector) {}
|
constructor(private reflector: Reflector) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* @function canActivate
|
||||||
|
* @description
|
||||||
|
* Authorization guard that checks whether the current user has one of the required roles
|
||||||
|
* to access a specific route handler. It uses metadata defined by the `@Roles()` decorator
|
||||||
|
* and verifies the user's role accordingly.
|
||||||
|
*
|
||||||
|
* If no roles are specified for the route, access is granted by default.
|
||||||
|
* If the user is not authenticated or does not have a required role, access is denied.
|
||||||
|
*
|
||||||
|
* @param {ExecutionContext} ctx - The current execution context, which provides access
|
||||||
|
* to route metadata and the HTTP request.
|
||||||
|
*
|
||||||
|
* @returns {boolean} - Returns `true` if access is allowed, otherwise throws a `ForbiddenException`
|
||||||
|
* or returns `false` if the user is not authenticated.
|
||||||
|
*/
|
||||||
canActivate(ctx: ExecutionContext): boolean {
|
canActivate(ctx: ExecutionContext): boolean {
|
||||||
const requiredRoles = this.reflector.get<Roles[]>(
|
const requiredRoles = this.reflector.get<Roles[]>(
|
||||||
ROLES_KEY,
|
ROLES_KEY,
|
||||||
|
|
|
||||||
20
src/modules/authentication/services/jwt-auth.service.ts
Normal file
20
src/modules/authentication/services/jwt-auth.service.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { UUID } from 'crypto';
|
||||||
|
import { UsersService } from 'src/modules/users-management/services/users.service';
|
||||||
|
import { JwtService } from '@nestjs/jwt';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthService {
|
||||||
|
constructor(
|
||||||
|
private usersService: UsersService,
|
||||||
|
private jwtService: JwtService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async validateUser(user_id: UUID): Promise<any> {
|
||||||
|
const user = await this.usersService.findOne(user_id);
|
||||||
|
if (user) {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/modules/authentication/strategies/authentik.strategy.ts
Normal file
28
src/modules/authentication/strategies/authentik.strategy.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PassportStrategy } from '@nestjs/passport';
|
||||||
|
import { Strategy } from 'passport-openidconnect';
|
||||||
|
|
||||||
|
export interface AuthentikPayload {
|
||||||
|
//TODO: check Authentik payload contents
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthentikStrategy extends PassportStrategy(Strategy) {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
issuer: process.env.AUTHENTIK_ISSUER || "ISSUER MISSING",
|
||||||
|
clientID: process.env.AUTHENTIK_CLIENT_ID || "CLIENT ID MISSING",
|
||||||
|
clientSecret: process.env.AUTHENTIK_CLIENT_SECRET || "CLIENT SECRET MISSING",
|
||||||
|
callbackURL: process.env.AUTHENTIK_CALLBACK_URL || "CALLBACK URL MISSING",
|
||||||
|
authorizationURL: `${process.env.AUTHENTIK_ISSUER}/authorize/`,
|
||||||
|
tokenURL: `${process.env.AUTHENTIK_ISSUER}/token/`,
|
||||||
|
userInfoURL: `${process.env.AUTHENTIK_ISSUER}/userinfo/`,
|
||||||
|
scope: [],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async validate(): Promise<any> {
|
||||||
|
// Check what kind of payload we're actually handling here
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user