fix npm run build
This commit is contained in:
Vendored
+110
@@ -0,0 +1,110 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthController = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const swagger_1 = require("@nestjs/swagger");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
let AuthController = class AuthController {
|
||||
authService;
|
||||
constructor(authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
async login(returnTo, res) {
|
||||
const redirect = await this.authService.createAuthorizationRedirect(returnTo);
|
||||
return res.redirect(302, redirect);
|
||||
}
|
||||
async callback(code, state, res) {
|
||||
const result = await this.authService.handleCallback(code, state);
|
||||
// set cookies
|
||||
const cookieOptions = {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
};
|
||||
// access token cookie (internal JWT)
|
||||
res.cookie('raylab_jwt', result.accessToken, { ...cookieOptions, maxAge: result.expiresIn * 1000 });
|
||||
// refresh token cookie
|
||||
res.cookie('raylab_refresh', result.refreshToken, { ...cookieOptions, maxAge: result.refreshTtl * 1000 });
|
||||
return res.redirect(302, result.returnTo || '/');
|
||||
}
|
||||
async logout(req, res) {
|
||||
const refreshToken = req.cookies?.raylab_refresh || req.body?.refreshToken;
|
||||
const redirect = await this.authService.logout(refreshToken);
|
||||
return res.redirect(302, redirect);
|
||||
}
|
||||
async refresh(req) {
|
||||
const refreshToken = req.cookies?.raylab_refresh || req.body?.refreshToken;
|
||||
const result = await this.authService.refresh(refreshToken);
|
||||
return { success: true, data: result };
|
||||
}
|
||||
async me(req) {
|
||||
const token = (req.cookies?.raylab_jwt) || (req.headers.authorization && req.headers.authorization.replace(/^Bearer\s+/i, ''));
|
||||
const user = await this.authService.me(token);
|
||||
return { success: true, data: user };
|
||||
}
|
||||
};
|
||||
exports.AuthController = AuthController;
|
||||
__decorate([
|
||||
(0, common_1.Get)('login'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Start Authorization Code + PKCE login (redirect to Identity Provider)' }),
|
||||
__param(0, (0, common_1.Query)('returnTo')),
|
||||
__param(1, (0, common_1.Res)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "login", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('callback'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'OIDC callback endpoint' }),
|
||||
__param(0, (0, common_1.Query)('code')),
|
||||
__param(1, (0, common_1.Query)('state')),
|
||||
__param(2, (0, common_1.Res)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [String, String, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "callback", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('logout'),
|
||||
(0, common_1.HttpCode)(common_1.HttpStatus.OK),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Logout (invalidate internal session and redirect to identity provider logout)' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__param(1, (0, common_1.Res)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object, Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "logout", null);
|
||||
__decorate([
|
||||
(0, common_1.Post)('refresh'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Refresh internal JWT using internal refresh token' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "refresh", null);
|
||||
__decorate([
|
||||
(0, common_1.Get)('me'),
|
||||
(0, swagger_1.ApiOperation)({ summary: 'Get current user from internal JWT (cookie or Authorization header)' }),
|
||||
__param(0, (0, common_1.Req)()),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [Object]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AuthController.prototype, "me", null);
|
||||
exports.AuthController = AuthController = __decorate([
|
||||
(0, swagger_1.ApiTags)('Auth'),
|
||||
(0, common_1.Controller)('auth'),
|
||||
__metadata("design:paramtypes", [auth_service_1.AuthService])
|
||||
], AuthController);
|
||||
//# sourceMappingURL=auth.controller.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.controller.js","sourceRoot":"","sources":["../../../src/modules/auth/auth.controller.ts"],"names":[],"mappings":"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"}
|
||||
Vendored
+75
@@ -0,0 +1,75 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthModule = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const auth_controller_1 = require("./auth.controller");
|
||||
const auth_service_1 = require("./auth.service");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const jwt_1 = require("@nestjs/jwt");
|
||||
const prisma_service_1 = require("../../shared/prisma.service");
|
||||
const user_interface_1 = require("../identity/domain/repositories/user.interface");
|
||||
const prisma_user_repository_1 = require("../identity/infrastructure/repositories/prisma-user.repository");
|
||||
const sync_identity_handler_1 = require("../identity/application/handlers/user/sync-identity.handler");
|
||||
const role_interface_1 = require("../identity/domain/repositories/role.interface");
|
||||
const prisma_role_repository_1 = require("../identity/infrastructure/repositories/prisma-role.repository");
|
||||
const i_auth_config_1 = require("../identity/application/config/i-auth-config");
|
||||
const env_auth_config_1 = require("../identity/application/config/env-auth-config");
|
||||
const redis_pkce_store_1 = require("./pkce/redis-pkce.store");
|
||||
const inmemory_refresh_store_1 = require("./refresh/inmemory-refresh.store");
|
||||
const oidc_service_1 = require("./oidc.service");
|
||||
const role_sync_service_1 = require("./role-sync.service");
|
||||
const redis_service_1 = require("../../shared/redis.service");
|
||||
const group_hash_service_1 = require("./group-hash.service");
|
||||
const authentication_service_1 = require("./authentication.service");
|
||||
const event_bus_service_1 = require("../../core/event-bus/event-bus.service");
|
||||
const audit_service_1 = require("../audit/audit.service");
|
||||
const authorization_module_1 = require("../authorization/authorization.module");
|
||||
let AuthModule = class AuthModule {
|
||||
};
|
||||
exports.AuthModule = AuthModule;
|
||||
exports.AuthModule = AuthModule = __decorate([
|
||||
(0, common_1.Module)({
|
||||
imports: [
|
||||
config_1.ConfigModule,
|
||||
authorization_module_1.AuthorizationModule,
|
||||
jwt_1.JwtModule.registerAsync({
|
||||
imports: [config_1.ConfigModule],
|
||||
useFactory: async (config) => ({
|
||||
secret: config.get('RAYLAB_JWT_SECRET') || 'raylab-secret',
|
||||
signOptions: { algorithm: 'HS256' },
|
||||
}),
|
||||
inject: [config_1.ConfigService],
|
||||
}),
|
||||
],
|
||||
controllers: [auth_controller_1.AuthController],
|
||||
providers: [
|
||||
auth_service_1.AuthService,
|
||||
prisma_service_1.PrismaService,
|
||||
prisma_user_repository_1.PrismaUserRepository,
|
||||
prisma_role_repository_1.PrismaRoleRepository,
|
||||
sync_identity_handler_1.SyncIdentityHandler,
|
||||
{ provide: user_interface_1.IUser, useClass: prisma_user_repository_1.PrismaUserRepository },
|
||||
{ provide: role_interface_1.IRole, useClass: prisma_role_repository_1.PrismaRoleRepository },
|
||||
{ provide: i_auth_config_1.IAuthConfig, useClass: env_auth_config_1.EnvAuthConfig },
|
||||
// In-memory PKCE and Refresh stores (Redis removed)
|
||||
redis_pkce_store_1.RedisPkceStore,
|
||||
inmemory_refresh_store_1.InMemoryRefreshStore,
|
||||
// OIDC & Role Sync
|
||||
oidc_service_1.OidcService,
|
||||
role_sync_service_1.RoleSyncService,
|
||||
group_hash_service_1.GroupHashService,
|
||||
authentication_service_1.AuthenticationService,
|
||||
event_bus_service_1.EventBus,
|
||||
audit_service_1.AuditService,
|
||||
redis_service_1.RedisService,
|
||||
],
|
||||
exports: [auth_service_1.AuthService, oidc_service_1.OidcService, role_sync_service_1.RoleSyncService, authentication_service_1.AuthenticationService, event_bus_service_1.EventBus],
|
||||
})
|
||||
], AuthModule);
|
||||
//# sourceMappingURL=auth.module.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.module.js","sourceRoot":"","sources":["../../../src/modules/auth/auth.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAAwC;AACxC,uDAAmD;AACnD,iDAA6C;AAC7C,2CAA6D;AAC7D,qCAAwC;AACxC,gEAA4D;AAC5D,mFAAuE;AACvE,2GAAsG;AACtG,uGAAkG;AAClG,mFAAuE;AACvE,2GAAsG;AACtG,gFAA2E;AAC3E,oFAA+E;AAC/E,8DAAyD;AACzD,6EAAwE;AACxE,iDAA6C;AAC7C,2DAAsD;AACtD,8DAA0D;AAC1D,6DAAwD;AACxD,qEAAiE;AACjE,8EAAkE;AAClE,0DAAsD;AACtD,gFAA4E;AA0CrE,IAAM,UAAU,GAAhB,MAAM,UAAU;CAAG,CAAA;AAAb,gCAAU;qBAAV,UAAU;IAvCtB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,qBAAY;YACZ,0CAAmB;YACnB,eAAS,CAAC,aAAa,CAAC;gBACtB,OAAO,EAAE,CAAC,qBAAY,CAAC;gBACvB,UAAU,EAAE,KAAK,EAAE,MAAqB,EAAE,EAAE,CAAC,CAAC;oBAC5C,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,eAAe;oBAC1D,WAAW,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE;iBACpC,CAAC;gBACF,MAAM,EAAE,CAAC,sBAAa,CAAC;aACxB,CAAC;SACH;QACD,WAAW,EAAE,CAAC,gCAAc,CAAC;QAC7B,SAAS,EAAE;YACT,0BAAW;YACX,8BAAa;YACb,6CAAoB;YACpB,6CAAoB;YACpB,2CAAmB;YACnB,EAAE,OAAO,EAAE,sBAAK,EAAE,QAAQ,EAAE,6CAAoB,EAAE;YAClD,EAAE,OAAO,EAAE,sBAAK,EAAE,QAAQ,EAAE,6CAAoB,EAAE;YAClD,EAAE,OAAO,EAAE,2BAAW,EAAE,QAAQ,EAAE,+BAAa,EAAE;YAEjD,oDAAoD;YACpD,iCAAc;YACd,6CAAoB;YAEpB,mBAAmB;YACnB,0BAAW;YACX,mCAAe;YACf,qCAAgB;YAChB,8CAAqB;YACrB,4BAAQ;YACR,4BAAY;YACZ,4BAAY;SACb;QACD,OAAO,EAAE,CAAC,0BAAW,EAAE,0BAAW,EAAE,mCAAe,EAAE,8CAAqB,EAAE,4BAAQ,CAAC;KACtF,CAAC;GACW,UAAU,CAAG"}
|
||||
Vendored
+209
@@ -0,0 +1,209 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
const jwt_1 = require("@nestjs/jwt");
|
||||
const sync_identity_handler_1 = require("../identity/application/handlers/user/sync-identity.handler");
|
||||
const user_interface_1 = require("../identity/domain/repositories/user.interface");
|
||||
const prisma_service_1 = require("../../shared/prisma.service");
|
||||
const redis_pkce_store_1 = require("./pkce/redis-pkce.store");
|
||||
const inmemory_refresh_store_1 = require("./refresh/inmemory-refresh.store");
|
||||
const openidClient = require('openid-client');
|
||||
let AuthService = class AuthService {
|
||||
config;
|
||||
jwtService;
|
||||
prisma;
|
||||
userRepository;
|
||||
syncIdentityHandler;
|
||||
pkceStore;
|
||||
refreshStore;
|
||||
constructor(config, jwtService, prisma, userRepository, syncIdentityHandler, pkceStore, refreshStore) {
|
||||
this.config = config;
|
||||
this.jwtService = jwtService;
|
||||
this.prisma = prisma;
|
||||
this.userRepository = userRepository;
|
||||
this.syncIdentityHandler = syncIdentityHandler;
|
||||
this.pkceStore = pkceStore;
|
||||
this.refreshStore = refreshStore;
|
||||
}
|
||||
issuer = null;
|
||||
client = null;
|
||||
async getIssuer() {
|
||||
if (this.issuer)
|
||||
return this.issuer;
|
||||
const issuerUrl = this.config.get('AUTHENTIK_ISSUER');
|
||||
if (!issuerUrl)
|
||||
throw new Error('AUTHENTIK_ISSUER not configured');
|
||||
this.issuer = await openidClient.Issuer.discover(issuerUrl);
|
||||
return this.issuer;
|
||||
}
|
||||
async getClient() {
|
||||
if (this.client)
|
||||
return this.client;
|
||||
const issuer = await this.getIssuer();
|
||||
const clientId = this.config.get('AUTHENTIK_CLIENT_ID');
|
||||
const clientSecret = this.config.get('AUTHENTIK_CLIENT_SECRET');
|
||||
if (!clientId)
|
||||
throw new Error('AUTHENTIK_CLIENT_ID not configured');
|
||||
this.client = new issuer.Client({ client_id: clientId, client_secret: clientSecret });
|
||||
return this.client;
|
||||
}
|
||||
async createAuthorizationRedirect(returnTo) {
|
||||
const client = await this.getClient();
|
||||
const redirectUri = this.config.get('AUTH_CALLBACK_URL') || `${this.config.get('APP_URL') || ''}/auth/callback`;
|
||||
const state = require('crypto').randomUUID();
|
||||
const code_verifier = openidClient.generators.codeVerifier();
|
||||
const code_challenge = await openidClient.generators.codeChallenge(code_verifier);
|
||||
const nonce = openidClient.generators.nonce();
|
||||
await this.pkceStore.save(state, { code_verifier, nonce, returnTo }, 300);
|
||||
const url = client.authorizationUrl({
|
||||
redirect_uri: redirectUri,
|
||||
scope: this.config.get('AUTHENTIK_DEFAULT_SCOPE') || 'openid email profile',
|
||||
response_type: 'code',
|
||||
code_challenge,
|
||||
code_challenge_method: 'S256',
|
||||
state,
|
||||
nonce,
|
||||
});
|
||||
return url;
|
||||
}
|
||||
async handleCallback(code, state) {
|
||||
const client = await this.getClient();
|
||||
const pkce = await this.pkceStore.get(state);
|
||||
if (!pkce)
|
||||
throw new common_1.UnauthorizedException('Invalid or expired state');
|
||||
// remove one-time state
|
||||
await this.pkceStore.remove(state);
|
||||
const redirectUri = this.config.get('AUTH_CALLBACK_URL') || `${this.config.get('APP_URL') || ''}/auth/callback`;
|
||||
// exchange code
|
||||
const tokenSet = await client.callback(redirectUri, { code, state }, { code_verifier: pkce.code_verifier, nonce: pkce.nonce });
|
||||
// verify id_token and get claims
|
||||
const claims = tokenSet.claims();
|
||||
// fetch userinfo if available
|
||||
let userInfo = null;
|
||||
try {
|
||||
if (tokenSet.access_token && client.userinfo) {
|
||||
userInfo = await client.userinfo(tokenSet.access_token);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// ignore
|
||||
}
|
||||
const identity = {
|
||||
sub: userInfo?.sub || claims.sub || null,
|
||||
preferred_username: userInfo?.preferred_username || userInfo?.username || userInfo?.email || claims.preferred_username || claims.email,
|
||||
email: userInfo?.email || claims.email,
|
||||
raw: { tokenSet, userInfo, claims },
|
||||
};
|
||||
// Sync identity to local user (create if needed)
|
||||
const domainUser = await this.syncIdentityHandler.execute(identity);
|
||||
// ensure active/not deleted
|
||||
if (!domainUser.isActive)
|
||||
throw new common_1.UnauthorizedException('User is not active');
|
||||
if (domainUser.deletedAt)
|
||||
throw new common_1.UnauthorizedException('User is deleted');
|
||||
// create internal JWT
|
||||
const jwtPayload = {
|
||||
sub: domainUser.id,
|
||||
preferred_username: domainUser.username,
|
||||
email: domainUser.email,
|
||||
};
|
||||
const expiresIn = Number(this.config.get('RAYLAB_JWT_EXPIRES_IN') || 3600);
|
||||
const access = this.jwtService.sign(jwtPayload, { expiresIn });
|
||||
// create internal refresh token
|
||||
const refreshToken = require('crypto').randomUUID();
|
||||
const refreshTtl = Number(this.config.get('RAYLAB_REFRESH_EXPIRES_IN') || 30 * 24 * 3600); // default 30 days
|
||||
await this.refreshStore.set(refreshToken, { userId: domainUser.id }, refreshTtl);
|
||||
return {
|
||||
accessToken: access,
|
||||
refreshToken,
|
||||
expiresIn,
|
||||
refreshTtl,
|
||||
user: {
|
||||
id: domainUser.id,
|
||||
username: domainUser.username,
|
||||
email: domainUser.email,
|
||||
roles: domainUser.roles || [],
|
||||
},
|
||||
returnTo: pkce.returnTo,
|
||||
};
|
||||
}
|
||||
async refresh(refreshToken) {
|
||||
if (!refreshToken)
|
||||
throw new common_1.UnauthorizedException('Missing refresh token');
|
||||
const data = await this.refreshStore.get(refreshToken);
|
||||
if (!data)
|
||||
throw new common_1.UnauthorizedException('Invalid refresh token');
|
||||
const userId = data.userId;
|
||||
// load user
|
||||
const domainUser = await this.userRepository.getById(userId);
|
||||
if (!domainUser)
|
||||
throw new common_1.UnauthorizedException('User not found');
|
||||
if (!domainUser.isActive)
|
||||
throw new common_1.UnauthorizedException('User is not active');
|
||||
// rotate refresh token
|
||||
await this.refreshStore.del(refreshToken);
|
||||
const newRefresh = require('crypto').randomUUID();
|
||||
const refreshTtl = Number(this.config.get('RAYLAB_REFRESH_EXPIRES_IN') || 30 * 24 * 3600);
|
||||
await this.refreshStore.set(newRefresh, { userId }, refreshTtl);
|
||||
const expiresIn = Number(this.config.get('RAYLAB_JWT_EXPIRES_IN') || 3600);
|
||||
const access = this.jwtService.sign({ sub: domainUser.id, preferred_username: domainUser.username, email: domainUser.email }, { expiresIn });
|
||||
return { accessToken: access, refreshToken: newRefresh, expiresIn, refreshTtl };
|
||||
}
|
||||
async logout(refreshToken) {
|
||||
if (refreshToken) {
|
||||
await this.refreshStore.del(refreshToken);
|
||||
}
|
||||
const issuer = await this.getIssuer();
|
||||
const endSession = issuer.metadata.end_session_endpoint;
|
||||
const postLogout = this.config.get('APP_URL') || '/';
|
||||
if (endSession) {
|
||||
// Redirect to identity provider logout
|
||||
const url = new URL(endSession);
|
||||
if (postLogout)
|
||||
url.searchParams.set('post_logout_redirect_uri', postLogout);
|
||||
return url.toString();
|
||||
}
|
||||
return postLogout;
|
||||
}
|
||||
async me(token) {
|
||||
if (!token)
|
||||
throw new common_1.UnauthorizedException('Missing token');
|
||||
try {
|
||||
const payload = this.jwtService.verify(token);
|
||||
const user = await this.userRepository.getById(payload.sub);
|
||||
if (!user)
|
||||
throw new common_1.UnauthorizedException('User not found');
|
||||
return { id: user.id, username: user.username, email: user.email, roles: user.roles || [] };
|
||||
}
|
||||
catch (e) {
|
||||
throw new common_1.UnauthorizedException('Invalid token');
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.AuthService = AuthService;
|
||||
exports.AuthService = AuthService = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(3, (0, common_1.Inject)(user_interface_1.IUser)),
|
||||
__metadata("design:paramtypes", [config_1.ConfigService,
|
||||
jwt_1.JwtService,
|
||||
prisma_service_1.PrismaService,
|
||||
user_interface_1.IUser,
|
||||
sync_identity_handler_1.SyncIdentityHandler,
|
||||
redis_pkce_store_1.RedisPkceStore,
|
||||
inmemory_refresh_store_1.InMemoryRefreshStore])
|
||||
], AuthService);
|
||||
//# sourceMappingURL=auth.service.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+70
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var AuthenticationService_1;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthenticationService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const oidc_service_1 = require("./oidc.service");
|
||||
const prisma_service_1 = require("../../shared/prisma.service");
|
||||
const role_sync_service_1 = require("./role-sync.service");
|
||||
const authorization_service_1 = require("../authorization/authorization.service");
|
||||
const event_bus_service_1 = require("../../core/event-bus/event-bus.service");
|
||||
let AuthenticationService = AuthenticationService_1 = class AuthenticationService {
|
||||
oidc;
|
||||
prisma;
|
||||
roleSync;
|
||||
authorization;
|
||||
events;
|
||||
logger = new common_1.Logger(AuthenticationService_1.name);
|
||||
constructor(oidc, prisma, roleSync, authorization, events) {
|
||||
this.oidc = oidc;
|
||||
this.prisma = prisma;
|
||||
this.roleSync = roleSync;
|
||||
this.authorization = authorization;
|
||||
this.events = events;
|
||||
}
|
||||
async authenticate(bearerToken) {
|
||||
// Validate token (signature/iss/aud/exp)
|
||||
const claims = await this.oidc.verifyToken(bearerToken);
|
||||
const sub = claims.sub;
|
||||
if (!sub)
|
||||
throw new Error('Invalid token: missing sub');
|
||||
// Resolve identity
|
||||
const identity = { sub, email: claims.email, preferred_username: claims.preferred_username, raw: claims };
|
||||
// Find or create user (materialize)
|
||||
let user = await this.prisma.user.findUnique({ where: { authentikId: sub } });
|
||||
if (!user) {
|
||||
user = await this.prisma.user.create({ data: { authentikId: sub, username: identity.preferred_username || identity.email || sub, email: identity.email || null } });
|
||||
}
|
||||
// Synchronize roles
|
||||
const groups = Array.isArray(claims.groups) ? claims.groups : [];
|
||||
await this.roleSync.syncUserRolesFromAuthentik(user.id, groups);
|
||||
// Load permissions
|
||||
const permissions = await this.authorization.getUserPermissions(user.id);
|
||||
// Build request context
|
||||
const rolesRows = await this.prisma.userRole.findMany({ where: { userId: user.id } });
|
||||
const roles = rolesRows.map((r) => r.roleId);
|
||||
const ctx = { user, identity, roles, permissions };
|
||||
// Publish domain event
|
||||
this.events.publish({ id: require('crypto').randomUUID(), timestamp: new Date().toISOString(), type: 'UserAuthenticated', payload: { userId: user.id, identity } });
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
exports.AuthenticationService = AuthenticationService;
|
||||
exports.AuthenticationService = AuthenticationService = AuthenticationService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [oidc_service_1.OidcService,
|
||||
prisma_service_1.PrismaService,
|
||||
role_sync_service_1.RoleSyncService,
|
||||
authorization_service_1.AuthorizationService,
|
||||
event_bus_service_1.EventBus])
|
||||
], AuthenticationService);
|
||||
//# sourceMappingURL=authentication.service.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"authentication.service.js","sourceRoot":"","sources":["../../../src/modules/auth/authentication.service.ts"],"names":[],"mappings":"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"}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
// Login DTO removed. Password grant has been removed in favor of Authorization Code + PKCE flow.
|
||||
// Formerly contained username/password properties.
|
||||
//# sourceMappingURL=login.dto.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"login.dto.js","sourceRoot":"","sources":["../../../../src/modules/auth/dto/login.dto.ts"],"names":[],"mappings":";AAAA,iGAAiG;AACjG,mDAAmD"}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.GroupHashService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const crypto = __importStar(require("crypto"));
|
||||
let GroupHashService = class GroupHashService {
|
||||
compute(groups) {
|
||||
const sorted = (groups || []).slice().sort();
|
||||
const data = sorted.join(',');
|
||||
return crypto.createHash('sha256').update(data, 'utf8').digest('hex');
|
||||
}
|
||||
};
|
||||
exports.GroupHashService = GroupHashService;
|
||||
exports.GroupHashService = GroupHashService = __decorate([
|
||||
(0, common_1.Injectable)()
|
||||
], GroupHashService);
|
||||
//# sourceMappingURL=group-hash.service.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"group-hash.service.js","sourceRoot":"","sources":["../../../src/modules/auth/group-hash.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+CAAiC;AAG1B,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAC3B,OAAO,CAAC,MAAgB;QACtB,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC;CACF,CAAA;AANY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;GACA,gBAAgB,CAM5B"}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var OidcGuard_1;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OidcGuard = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const oidc_service_1 = require("../oidc.service");
|
||||
const authentication_service_1 = require("../authentication.service");
|
||||
let OidcGuard = OidcGuard_1 = class OidcGuard {
|
||||
oidc;
|
||||
authn;
|
||||
logger = new common_1.Logger(OidcGuard_1.name);
|
||||
constructor(oidc, authn) {
|
||||
this.oidc = oidc;
|
||||
this.authn = authn;
|
||||
}
|
||||
async canActivate(context) {
|
||||
const req = context.switchToHttp().getRequest();
|
||||
const auth = req.headers['authorization'] || req.headers['Authorization'];
|
||||
if (!auth || typeof auth !== 'string' || !auth.startsWith('Bearer '))
|
||||
throw new common_1.UnauthorizedException('Missing bearer token');
|
||||
const token = auth.substring(7).trim();
|
||||
try {
|
||||
const ctx = await this.authn.authenticate(token);
|
||||
// attach context to request under a structured key
|
||||
req.raylabContext = ctx;
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
this.logger.debug('Authentication failed', e.message);
|
||||
throw new common_1.UnauthorizedException('Invalid token or authentication failed');
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.OidcGuard = OidcGuard;
|
||||
exports.OidcGuard = OidcGuard = OidcGuard_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [oidc_service_1.OidcService, authentication_service_1.AuthenticationService])
|
||||
], OidcGuard);
|
||||
//# sourceMappingURL=oidc.guard.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"oidc.guard.js","sourceRoot":"","sources":["../../../../src/modules/auth/guards/oidc.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAkH;AAClH,kDAA8C;AAC9C,sEAAkE;AAG3D,IAAM,SAAS,iBAAf,MAAM,SAAS;IAES;IAAoC;IADhD,MAAM,GAAG,IAAI,eAAM,CAAC,WAAS,CAAC,IAAI,CAAC,CAAC;IACrD,YAA6B,IAAiB,EAAmB,KAA4B;QAAhE,SAAI,GAAJ,IAAI,CAAa;QAAmB,UAAK,GAAL,KAAK,CAAuB;IAAG,CAAC;IAEjG,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,MAAM,IAAI,8BAAqB,CAAC,sBAAsB,CAAC,CAAC;QAC9H,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACjD,mDAAmD;YACnD,GAAG,CAAC,aAAa,GAAG,GAAG,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAG,CAAS,CAAC,OAAO,CAAC,CAAC;YAC/D,MAAM,IAAI,8BAAqB,CAAC,wCAAwC,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;CACF,CAAA;AApBY,8BAAS;oBAAT,SAAS;IADrB,IAAA,mBAAU,GAAE;qCAGwB,0BAAW,EAA0B,8CAAqB;GAFlF,SAAS,CAoBrB"}
|
||||
Vendored
+89
@@ -0,0 +1,89 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var OidcService_1;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OidcService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const config_1 = require("@nestjs/config");
|
||||
let OidcService = OidcService_1 = class OidcService {
|
||||
config;
|
||||
jwksUri = null;
|
||||
issuer;
|
||||
audience;
|
||||
logger = new common_1.Logger(OidcService_1.name);
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
this.issuer = this.config.get('AUTHENTIK_ISSUER') || '';
|
||||
this.audience = this.config.get('AUTHENTIK_AUDIENCE') || undefined;
|
||||
const jwksUri = this.config.get('AUTHENTIK_JWKS_URI');
|
||||
if (jwksUri)
|
||||
this.jwksUri = jwksUri;
|
||||
else if (this.issuer)
|
||||
this.jwksUri = `${this.issuer.replace(/\/+$/, '')}/.well-known/jwks.json`;
|
||||
}
|
||||
async verifyToken(token) {
|
||||
if (!this.jwksUri)
|
||||
throw new Error('JWKS not configured');
|
||||
try {
|
||||
// dynamic import to avoid ESM loading issues in test environment
|
||||
const jose = await Promise.resolve().then(() => __importStar(require('jose')));
|
||||
const jwks = jose.createRemoteJWKSet(new URL(this.jwksUri));
|
||||
const { payload } = await jose.jwtVerify(token, jwks, {
|
||||
issuer: this.issuer || undefined,
|
||||
audience: this.audience,
|
||||
});
|
||||
return payload;
|
||||
}
|
||||
catch (e) {
|
||||
this.logger.debug('Token verification failed', e.message);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.OidcService = OidcService;
|
||||
exports.OidcService = OidcService = OidcService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [config_1.ConfigService])
|
||||
], OidcService);
|
||||
//# sourceMappingURL=oidc.service.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"oidc.service.js","sourceRoot":"","sources":["../../../src/modules/auth/oidc.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,2CAA+C;AAGxC,IAAM,WAAW,mBAAjB,MAAM,WAAW;IAMO;IALrB,OAAO,GAAkB,IAAI,CAAC;IAC9B,MAAM,CAAS;IACf,QAAQ,CAAgC;IACxC,MAAM,GAAG,IAAI,eAAM,CAAC,aAAW,CAAC,IAAI,CAAC,CAAC;IAE9C,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;QAChD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAS,kBAAkB,CAAC,IAAI,EAAE,CAAC;QAChE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAS,oBAAoB,CAAC,IAAI,SAAS,CAAC;QAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAS,oBAAoB,CAAC,CAAC;QAC9D,IAAI,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;aAC/B,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,wBAAwB,CAAC;IAClG,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAE1D,IAAI,CAAC;YACH,iEAAiE;YACjE,MAAM,IAAI,GAAG,wDAAa,MAAM,GAAC,CAAC;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAC5D,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;gBACpD,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,SAAS;gBAChC,QAAQ,EAAE,IAAI,CAAC,QAAQ;aACjB,CAAC,CAAC;YAEV,OAAO,OAA8B,CAAC;QACxC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;CACF,CAAA;AAhCY,kCAAW;sBAAX,WAAW;IADvB,IAAA,mBAAU,GAAE;qCAO0B,sBAAa;GANvC,WAAW,CAgCvB"}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RedisPkceStore = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
let RedisPkceStore = class RedisPkceStore {
|
||||
// In-memory PKCE store replacing Redis-backed implementation
|
||||
map = new Map();
|
||||
cleanupInterval;
|
||||
constructor() {
|
||||
// periodic cleanup
|
||||
this.cleanupInterval = setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [k, v] of this.map.entries()) {
|
||||
if (v.expiresAt <= now)
|
||||
this.map.delete(k);
|
||||
}
|
||||
}, 60 * 1000);
|
||||
}
|
||||
key(state) { return state; }
|
||||
async save(state, data, ttlSeconds = 300) {
|
||||
const expiresAt = Date.now() + ttlSeconds * 1000;
|
||||
this.map.set(this.key(state), { ...data, expiresAt });
|
||||
}
|
||||
async get(state) {
|
||||
const v = this.map.get(this.key(state));
|
||||
if (!v)
|
||||
return null;
|
||||
if (v.expiresAt <= Date.now()) {
|
||||
this.map.delete(this.key(state));
|
||||
return null;
|
||||
}
|
||||
return { code_verifier: v.code_verifier, nonce: v.nonce, returnTo: v.returnTo };
|
||||
}
|
||||
async remove(state) {
|
||||
this.map.delete(this.key(state));
|
||||
}
|
||||
onModuleDestroy() {
|
||||
if (this.cleanupInterval)
|
||||
clearInterval(this.cleanupInterval);
|
||||
}
|
||||
};
|
||||
exports.RedisPkceStore = RedisPkceStore;
|
||||
exports.RedisPkceStore = RedisPkceStore = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [])
|
||||
], RedisPkceStore);
|
||||
//# sourceMappingURL=redis-pkce.store.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"redis-pkce.store.js","sourceRoot":"","sources":["../../../../src/modules/auth/pkce/redis-pkce.store.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA6D;AAKtD,IAAM,cAAc,GAApB,MAAM,cAAc;IACzB,6DAA6D;IACrD,GAAG,GAAG,IAAI,GAAG,EAAqB,CAAC;IACnC,eAAe,CAAkB;IAEzC;QACE,mBAAmB;QACnB,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;gBACxC,IAAI,CAAC,CAAC,SAAS,IAAI,GAAG;oBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IAChB,CAAC;IAEO,GAAG,CAAC,KAAa,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC;IAE5C,KAAK,CAAC,IAAI,CAAC,KAAa,EAAE,IAAiE,EAAE,UAAU,GAAG,GAAG;QAC3G,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;QACjD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAa;QACrB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACxC,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QACjF,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IAClF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa;QACxB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACnC,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,eAAe;YAAE,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChE,CAAC;CACF,CAAA;AApCY,wCAAc;yBAAd,cAAc;IAD1B,IAAA,mBAAU,GAAE;;GACA,cAAc,CAoC1B"}
|
||||
@@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.InMemoryRefreshStore = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
let InMemoryRefreshStore = class InMemoryRefreshStore {
|
||||
map = new Map();
|
||||
cleanupInterval;
|
||||
constructor() {
|
||||
this.cleanupInterval = setInterval(() => {
|
||||
const now = Date.now();
|
||||
for (const [k, v] of this.map.entries()) {
|
||||
if (v.expiresAt <= now)
|
||||
this.map.delete(k);
|
||||
}
|
||||
}, 60 * 1000);
|
||||
}
|
||||
async set(token, data, ttlSeconds) {
|
||||
const expiresAt = Date.now() + ttlSeconds * 1000;
|
||||
this.map.set(token, { userId: data.userId, expiresAt });
|
||||
}
|
||||
async get(token) {
|
||||
const v = this.map.get(token);
|
||||
if (!v)
|
||||
return null;
|
||||
if (v.expiresAt <= Date.now()) {
|
||||
this.map.delete(token);
|
||||
return null;
|
||||
}
|
||||
return { userId: v.userId };
|
||||
}
|
||||
async del(token) {
|
||||
this.map.delete(token);
|
||||
}
|
||||
onModuleDestroy() {
|
||||
if (this.cleanupInterval)
|
||||
clearInterval(this.cleanupInterval);
|
||||
}
|
||||
};
|
||||
exports.InMemoryRefreshStore = InMemoryRefreshStore;
|
||||
exports.InMemoryRefreshStore = InMemoryRefreshStore = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__metadata("design:paramtypes", [])
|
||||
], InMemoryRefreshStore);
|
||||
//# sourceMappingURL=inmemory-refresh.store.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"inmemory-refresh.store.js","sourceRoot":"","sources":["../../../../src/modules/auth/refresh/inmemory-refresh.store.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA6D;AAKtD,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IACvB,GAAG,GAAG,IAAI,GAAG,EAAwB,CAAC;IACtC,eAAe,CAAkB;IAEzC;QACE,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;gBACxC,IAAI,CAAC,CAAC,SAAS,IAAI,GAAG;oBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAa,EAAE,IAAwB,EAAE,UAAkB;QACnE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,CAAC;QACjD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAa;QACrB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QACvE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAAa;QACrB,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,eAAe;QACb,IAAI,IAAI,CAAC,eAAe;YAAE,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChE,CAAC;CACF,CAAA;AAhCY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;;GACA,oBAAoB,CAgChC"}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); }
|
||||
};
|
||||
var RoleSyncService_1;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RoleSyncService = void 0;
|
||||
const common_1 = require("@nestjs/common");
|
||||
const prisma_service_1 = require("../../shared/prisma.service");
|
||||
const event_bus_service_1 = require("../../core/event-bus/event-bus.service");
|
||||
const group_hash_service_1 = require("./group-hash.service");
|
||||
const authorization_service_1 = require("../authorization/authorization.service");
|
||||
let RoleSyncService = RoleSyncService_1 = class RoleSyncService {
|
||||
prisma;
|
||||
groupHash;
|
||||
permissionCache;
|
||||
events;
|
||||
logger = new common_1.Logger(RoleSyncService_1.name);
|
||||
constructor(prisma, groupHash, permissionCache, events) {
|
||||
this.prisma = prisma;
|
||||
this.groupHash = groupHash;
|
||||
this.permissionCache = permissionCache;
|
||||
this.events = events;
|
||||
}
|
||||
computeGroupHash(groups) {
|
||||
return this.groupHash.compute(groups || []);
|
||||
}
|
||||
async mapGroupsToRoleIds(groups) {
|
||||
if (!groups || groups.length === 0)
|
||||
return [];
|
||||
const mappings = await this.prisma.authGroupRoleMapping.findMany({ where: { authGroup: { in: groups } } });
|
||||
const roleIds = mappings.map((m) => m.roleId);
|
||||
return Array.from(new Set(roleIds));
|
||||
}
|
||||
async syncUserRolesFromAuthentik(userId, groups) {
|
||||
const groupHash = this.computeGroupHash(groups || []);
|
||||
const user = await this.prisma.user.findUnique({ where: { id: userId } });
|
||||
if (!user)
|
||||
throw new Error('User not found');
|
||||
if (user.lastGroupHash === groupHash) {
|
||||
this.logger.debug('Group hash unchanged, skipping sync');
|
||||
return { skipped: true };
|
||||
}
|
||||
const roleIds = await this.mapGroupsToRoleIds(groups || []);
|
||||
const previousRoleRows = await this.prisma.userRole.findMany({ where: { userId, source: 'AUTHENTIK' }, select: { roleId: true } });
|
||||
const previousRoles = previousRoleRows.map((r) => r.roleId);
|
||||
await this.prisma.$transaction(async (tx) => {
|
||||
await tx.userRole.deleteMany({ where: { userId: userId, source: 'AUTHENTIK' } });
|
||||
if (roleIds.length > 0) {
|
||||
const createData = roleIds.map((rid) => ({ userId, roleId: rid, source: 'AUTHENTIK' }));
|
||||
await tx.userRole.createMany({ data: createData, skipDuplicates: true });
|
||||
}
|
||||
await tx.user.update({ where: { id: userId }, data: { lastGroupHash: groupHash } });
|
||||
});
|
||||
// Invalidate permission cache through abstraction
|
||||
try {
|
||||
await this.permissionCache.invalidate(userId);
|
||||
}
|
||||
catch (e) {
|
||||
this.logger.error('Failed to invalidate permission cache', e);
|
||||
}
|
||||
// Publish event for audit and other subscribers
|
||||
this.events.publish({
|
||||
id: require('crypto').randomUUID(),
|
||||
timestamp: new Date().toISOString(),
|
||||
type: 'RolesSynchronized',
|
||||
payload: { userId, groups, assignedRoleIds: roleIds, previousRoles },
|
||||
});
|
||||
return { skipped: false, assignedRoleIds: roleIds };
|
||||
}
|
||||
};
|
||||
exports.RoleSyncService = RoleSyncService;
|
||||
exports.RoleSyncService = RoleSyncService = RoleSyncService_1 = __decorate([
|
||||
(0, common_1.Injectable)(),
|
||||
__param(2, (0, common_1.Inject)(authorization_service_1.PERMISSION_CACHE)),
|
||||
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
|
||||
group_hash_service_1.GroupHashService, Object, event_bus_service_1.EventBus])
|
||||
], RoleSyncService);
|
||||
//# sourceMappingURL=role-sync.service.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"role-sync.service.js","sourceRoot":"","sources":["../../../src/modules/auth/role-sync.service.ts"],"names":[],"mappings":"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"}
|
||||
Reference in New Issue
Block a user