@rekog/mcp-nest 1.7.0-alpha.0 → 1.7.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/authz/guards/jwt-auth.guard.d.ts +13 -0
  2. package/dist/authz/guards/jwt-auth.guard.d.ts.map +1 -0
  3. package/dist/authz/guards/jwt-auth.guard.js +46 -0
  4. package/dist/authz/guards/jwt-auth.guard.js.map +1 -0
  5. package/dist/authz/index.d.ts +8 -1
  6. package/dist/authz/index.d.ts.map +1 -1
  7. package/dist/authz/index.js +22 -0
  8. package/dist/authz/index.js.map +1 -1
  9. package/dist/authz/interfaces/index.d.ts +3 -0
  10. package/dist/authz/interfaces/index.d.ts.map +1 -0
  11. package/dist/authz/interfaces/index.js +19 -0
  12. package/dist/authz/interfaces/index.js.map +1 -0
  13. package/dist/authz/mcp-oauth.controller.d.ts +53 -0
  14. package/dist/authz/mcp-oauth.controller.d.ts.map +1 -0
  15. package/dist/authz/mcp-oauth.controller.js +305 -0
  16. package/dist/authz/mcp-oauth.controller.js.map +1 -0
  17. package/dist/authz/mcp-oauth.module.d.ts +11 -0
  18. package/dist/authz/mcp-oauth.module.d.ts.map +1 -0
  19. package/dist/authz/mcp-oauth.module.js +173 -0
  20. package/dist/authz/mcp-oauth.module.js.map +1 -0
  21. package/dist/authz/providers/github.provider.d.ts +3 -0
  22. package/dist/authz/providers/github.provider.d.ts.map +1 -0
  23. package/dist/authz/providers/github.provider.js +23 -0
  24. package/dist/authz/providers/github.provider.js.map +1 -0
  25. package/dist/authz/providers/google.provider.d.ts +3 -0
  26. package/dist/authz/providers/google.provider.d.ts.map +1 -0
  27. package/dist/authz/providers/google.provider.js +24 -0
  28. package/dist/authz/providers/google.provider.js.map +1 -0
  29. package/dist/authz/providers/oauth-provider.interface.d.ts +75 -0
  30. package/dist/authz/providers/oauth-provider.interface.d.ts.map +1 -0
  31. package/dist/authz/providers/oauth-provider.interface.js +3 -0
  32. package/dist/authz/providers/oauth-provider.interface.js.map +1 -0
  33. package/dist/authz/services/client.service.d.ts +10 -0
  34. package/dist/authz/services/client.service.d.ts.map +1 -0
  35. package/dist/authz/services/client.service.js +84 -0
  36. package/dist/authz/services/client.service.js.map +1 -0
  37. package/dist/authz/services/jwt-token.service.d.ts +29 -0
  38. package/dist/authz/services/jwt-token.service.d.ts.map +1 -0
  39. package/dist/authz/services/jwt-token.service.js +103 -0
  40. package/dist/authz/services/jwt-token.service.js.map +1 -0
  41. package/dist/authz/services/oauth-strategy.service.d.ts +11 -0
  42. package/dist/authz/services/oauth-strategy.service.d.ts.map +1 -0
  43. package/dist/authz/services/oauth-strategy.service.js +64 -0
  44. package/dist/authz/services/oauth-strategy.service.js.map +1 -0
  45. package/dist/authz/stores/memory-store.service.d.ts +19 -0
  46. package/dist/authz/stores/memory-store.service.d.ts.map +1 -0
  47. package/dist/authz/stores/memory-store.service.js +84 -0
  48. package/dist/authz/stores/memory-store.service.js.map +1 -0
  49. package/dist/authz/stores/memory-store.service.spec.d.ts +2 -0
  50. package/dist/authz/stores/memory-store.service.spec.d.ts.map +1 -0
  51. package/dist/authz/stores/memory-store.service.spec.js +195 -0
  52. package/dist/authz/stores/memory-store.service.spec.js.map +1 -0
  53. package/dist/authz/stores/oauth-store.interface.d.ts +52 -0
  54. package/dist/authz/stores/oauth-store.interface.d.ts.map +1 -0
  55. package/dist/authz/stores/oauth-store.interface.js +3 -0
  56. package/dist/authz/stores/oauth-store.interface.js.map +1 -0
  57. package/dist/authz/stores/sqlite/sqlite-store.service.d.ts +18 -0
  58. package/dist/authz/stores/sqlite/sqlite-store.service.d.ts.map +1 -0
  59. package/dist/authz/stores/sqlite/sqlite-store.service.js +206 -0
  60. package/dist/authz/stores/sqlite/sqlite-store.service.js.map +1 -0
  61. package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts +13 -0
  62. package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts.map +1 -0
  63. package/dist/authz/stores/typeorm/entities/authorization-code.entity.js +60 -0
  64. package/dist/authz/stores/typeorm/entities/authorization-code.entity.js.map +1 -0
  65. package/dist/authz/stores/typeorm/entities/index.d.ts +4 -0
  66. package/dist/authz/stores/typeorm/entities/index.d.ts.map +1 -0
  67. package/dist/authz/stores/typeorm/entities/index.js +10 -0
  68. package/dist/authz/stores/typeorm/entities/index.js.map +1 -0
  69. package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts +16 -0
  70. package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts.map +1 -0
  71. package/dist/authz/stores/typeorm/entities/oauth-client.entity.js +72 -0
  72. package/dist/authz/stores/typeorm/entities/oauth-client.entity.js.map +1 -0
  73. package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts +13 -0
  74. package/dist/authz/stores/typeorm/entities/oauth-session.entity.d.ts.map +1 -0
  75. package/dist/authz/stores/typeorm/entities/oauth-session.entity.js +60 -0
  76. package/dist/authz/stores/typeorm/entities/oauth-session.entity.js.map +1 -0
  77. package/dist/authz/stores/typeorm/typeorm-store.service.d.ts +21 -0
  78. package/dist/authz/stores/typeorm/typeorm-store.service.d.ts.map +1 -0
  79. package/dist/authz/stores/typeorm/typeorm-store.service.js +87 -0
  80. package/dist/authz/stores/typeorm/typeorm-store.service.js.map +1 -0
  81. package/dist/mcp/services/handlers/mcp-tools.handler.d.ts.map +1 -1
  82. package/dist/mcp/services/handlers/mcp-tools.handler.js.map +1 -1
  83. package/package.json +17 -2
  84. package/src/authz/guards/jwt-auth.guard.ts +45 -0
  85. package/src/authz/index.ts +8 -1
  86. package/src/authz/mcp-oauth.controller.ts +394 -0
  87. package/src/authz/mcp-oauth.module.ts +235 -0
  88. package/src/authz/providers/github.provider.ts +24 -0
  89. package/src/authz/providers/google.provider.ts +22 -0
  90. package/src/authz/providers/oauth-provider.interface.ts +102 -0
  91. package/src/authz/services/client.service.ts +110 -0
  92. package/src/authz/services/jwt-token.service.ts +127 -0
  93. package/src/authz/services/oauth-strategy.service.ts +55 -0
  94. package/src/authz/stores/memory-store.service.spec.ts +240 -0
  95. package/src/authz/stores/memory-store.service.ts +100 -0
  96. package/src/authz/stores/oauth-store.interface.ts +105 -0
  97. package/src/authz/stores/sqlite/sqlite-store.service.ts +279 -0
  98. package/src/authz/stores/typeorm/README.md +133 -0
  99. package/src/authz/stores/typeorm/entities/authorization-code.entity.ts +34 -0
  100. package/src/authz/stores/typeorm/entities/index.ts +3 -0
  101. package/src/authz/stores/typeorm/entities/oauth-client.entity.ts +49 -0
  102. package/src/authz/stores/typeorm/entities/oauth-session.entity.ts +34 -0
  103. package/src/authz/stores/typeorm/typeorm-store.service.ts +98 -0
  104. package/src/mcp/services/handlers/mcp-tools.handler.ts +5 -2
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var McpAuthModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.McpAuthModule = exports.DEFAULT_OPTIONS = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const config_1 = require("@nestjs/config");
13
+ const jwt_1 = require("@nestjs/jwt");
14
+ const passport_1 = require("@nestjs/passport");
15
+ const typeorm_1 = require("@nestjs/typeorm");
16
+ const jwt_auth_guard_1 = require("./guards/jwt-auth.guard");
17
+ const mcp_oauth_controller_1 = require("./mcp-oauth.controller");
18
+ const client_service_1 = require("./services/client.service");
19
+ const jwt_token_service_1 = require("./services/jwt-token.service");
20
+ const oauth_strategy_service_1 = require("./services/oauth-strategy.service");
21
+ const typeorm_store_service_1 = require("./stores/typeorm/typeorm-store.service");
22
+ const memory_store_service_1 = require("./stores/memory-store.service");
23
+ const entities_1 = require("./stores/typeorm/entities");
24
+ exports.DEFAULT_OPTIONS = {
25
+ serverUrl: 'https://localhost:3000',
26
+ jwtIssuer: 'https://localhost:3000',
27
+ jwtAudience: 'mcp-client',
28
+ jwtAccessTokenExpiresIn: '60s',
29
+ jwtRefreshTokenExpiresIn: '30d',
30
+ cookieMaxAge: 24 * 60 * 60 * 1000,
31
+ oauthSessionExpiresIn: 10 * 60 * 1000,
32
+ authCodeExpiresIn: 10 * 60 * 1000,
33
+ nodeEnv: 'development',
34
+ };
35
+ let McpAuthModule = McpAuthModule_1 = class McpAuthModule {
36
+ static forRoot(options) {
37
+ const resolvedOptions = this.mergeAndValidateOptions(options, exports.DEFAULT_OPTIONS);
38
+ const oauthModuleOptions = {
39
+ provide: 'OAUTH_MODULE_OPTIONS',
40
+ useValue: resolvedOptions,
41
+ };
42
+ const imports = [
43
+ config_1.ConfigModule,
44
+ passport_1.PassportModule.register({
45
+ defaultStrategy: 'jwt',
46
+ session: false,
47
+ }),
48
+ jwt_1.JwtModule.register({
49
+ secret: resolvedOptions.jwtSecret,
50
+ signOptions: {
51
+ issuer: resolvedOptions.jwtIssuer,
52
+ audience: resolvedOptions.jwtAudience,
53
+ },
54
+ }),
55
+ ];
56
+ const storeConfig = resolvedOptions.storeConfiguration;
57
+ const isTypeOrmStore = storeConfig?.type === 'typeorm';
58
+ if (storeConfig && storeConfig.type === 'typeorm') {
59
+ const typeormOptions = storeConfig.options;
60
+ imports.push(typeorm_1.TypeOrmModule.forRoot({
61
+ ...typeormOptions,
62
+ entities: [
63
+ ...(typeormOptions.entities || []),
64
+ entities_1.OAuthClientEntity,
65
+ entities_1.AuthorizationCodeEntity,
66
+ entities_1.OAuthSessionEntity,
67
+ ],
68
+ }), typeorm_1.TypeOrmModule.forFeature([
69
+ entities_1.OAuthClientEntity,
70
+ entities_1.AuthorizationCodeEntity,
71
+ entities_1.OAuthSessionEntity,
72
+ ]));
73
+ }
74
+ const oauthStoreProvider = this.createStoreProvider(resolvedOptions.storeConfiguration);
75
+ const oauthStoreAliasProvider = {
76
+ provide: memory_store_service_1.MemoryStore,
77
+ useExisting: 'IOAuthStore',
78
+ };
79
+ const providers = [
80
+ oauthModuleOptions,
81
+ oauthStoreProvider,
82
+ oauthStoreAliasProvider,
83
+ oauth_strategy_service_1.OAuthStrategyService,
84
+ client_service_1.ClientService,
85
+ jwt_token_service_1.JwtTokenService,
86
+ jwt_auth_guard_1.JwtAuthGuard,
87
+ ];
88
+ if (isTypeOrmStore) {
89
+ providers.push(typeorm_store_service_1.TypeOrmStore);
90
+ }
91
+ return {
92
+ module: McpAuthModule_1,
93
+ imports,
94
+ controllers: [mcp_oauth_controller_1.McpOAuthController],
95
+ providers,
96
+ exports: [
97
+ jwt_token_service_1.JwtTokenService,
98
+ 'IOAuthStore',
99
+ memory_store_service_1.MemoryStore,
100
+ jwt_auth_guard_1.JwtAuthGuard,
101
+ oauth_strategy_service_1.OAuthStrategyService,
102
+ ],
103
+ };
104
+ }
105
+ static mergeAndValidateOptions(options, defaults) {
106
+ this.validateRequiredOptions(options);
107
+ const resolvedOptions = {
108
+ ...defaults,
109
+ ...options,
110
+ jwtIssuer: options.jwtIssuer || options.serverUrl || exports.DEFAULT_OPTIONS.jwtIssuer,
111
+ cookieSecure: options.cookieSecure !== undefined
112
+ ? options.cookieSecure
113
+ : (options.nodeEnv || exports.DEFAULT_OPTIONS.nodeEnv) === 'production',
114
+ };
115
+ this.validateResolvedOptions(resolvedOptions);
116
+ return resolvedOptions;
117
+ }
118
+ static validateRequiredOptions(options) {
119
+ const requiredFields = [
120
+ 'provider',
121
+ 'clientId',
122
+ 'clientSecret',
123
+ 'jwtSecret',
124
+ ];
125
+ for (const field of requiredFields) {
126
+ if (!options[field]) {
127
+ throw new Error(`OAuthModuleOptions: ${String(field)} is required and must be provided by the user`);
128
+ }
129
+ }
130
+ }
131
+ static validateResolvedOptions(options) {
132
+ if (options.jwtSecret.length < 32) {
133
+ throw new Error('OAuthModuleOptions: jwtSecret must be at least 32 characters long');
134
+ }
135
+ try {
136
+ new URL(options.serverUrl);
137
+ new URL(options.jwtIssuer);
138
+ }
139
+ catch (error) {
140
+ throw new Error('OAuthModuleOptions: serverUrl and jwtIssuer must be valid URLs');
141
+ }
142
+ if (!options.provider.name || !options.provider.strategy) {
143
+ throw new Error('OAuthModuleOptions: provider must have name and strategy');
144
+ }
145
+ }
146
+ static createStoreProvider(storeConfiguration) {
147
+ if (!storeConfiguration || storeConfiguration.type === 'memory') {
148
+ return {
149
+ provide: 'IOAuthStore',
150
+ useValue: new memory_store_service_1.MemoryStore(),
151
+ };
152
+ }
153
+ if (storeConfiguration.type === 'typeorm') {
154
+ return {
155
+ provide: 'IOAuthStore',
156
+ useClass: typeorm_store_service_1.TypeOrmStore,
157
+ };
158
+ }
159
+ if (storeConfiguration.type === 'custom') {
160
+ return {
161
+ provide: 'IOAuthStore',
162
+ useValue: storeConfiguration.store,
163
+ };
164
+ }
165
+ throw new Error(`Unknown store configuration type: ${storeConfiguration.type}`);
166
+ }
167
+ };
168
+ exports.McpAuthModule = McpAuthModule;
169
+ exports.McpAuthModule = McpAuthModule = McpAuthModule_1 = __decorate([
170
+ (0, common_1.Global)(),
171
+ (0, common_1.Module)({})
172
+ ], McpAuthModule);
173
+ //# sourceMappingURL=mcp-oauth.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-oauth.module.js","sourceRoot":"","sources":["../../src/authz/mcp-oauth.module.ts"],"names":[],"mappings":"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","sourcesContent":["import { DynamicModule, Global, Module } from '@nestjs/common';\nimport { ConfigModule } from '@nestjs/config';\nimport { JwtModule } from '@nestjs/jwt';\nimport { PassportModule } from '@nestjs/passport';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { JwtAuthGuard } from './guards/jwt-auth.guard';\nimport { McpOAuthController } from './mcp-oauth.controller';\nimport { ClientService } from './services/client.service';\nimport { JwtTokenService } from './services/jwt-token.service';\nimport { OAuthStrategyService } from './services/oauth-strategy.service';\nimport {\n OAuthModuleDefaults,\n OAuthModuleOptions,\n OAuthUserModuleOptions as AuthUserModuleOptions,\n} from './providers/oauth-provider.interface';\nimport { TypeOrmStore } from './stores/typeorm/typeorm-store.service';\nimport { MemoryStore } from './stores/memory-store.service';\nimport {\n AuthorizationCodeEntity,\n OAuthClientEntity,\n OAuthSessionEntity,\n} from './stores/typeorm/entities';\n\n// Default configuration values\nexport const DEFAULT_OPTIONS: OAuthModuleDefaults = {\n serverUrl: 'https://localhost:3000',\n jwtIssuer: 'https://localhost:3000',\n jwtAudience: 'mcp-client',\n jwtAccessTokenExpiresIn: '60s',\n jwtRefreshTokenExpiresIn: '30d',\n cookieMaxAge: 24 * 60 * 60 * 1000, // 24 hours\n oauthSessionExpiresIn: 10 * 60 * 1000, // 10 minutes\n authCodeExpiresIn: 10 * 60 * 1000, // 10 minutes\n nodeEnv: 'development',\n};\n\n@Global()\n@Module({})\nexport class McpAuthModule {\n static forRoot(options: AuthUserModuleOptions): DynamicModule {\n // Merge user options with defaults and validate\n const resolvedOptions = this.mergeAndValidateOptions(\n options,\n DEFAULT_OPTIONS,\n );\n\n const oauthModuleOptions = {\n provide: 'OAUTH_MODULE_OPTIONS',\n useValue: resolvedOptions,\n };\n\n // Determine imports based on configuration\n const imports = [\n ConfigModule,\n PassportModule.register({\n defaultStrategy: 'jwt',\n session: false,\n }),\n JwtModule.register({\n secret: resolvedOptions.jwtSecret,\n signOptions: {\n issuer: resolvedOptions.jwtIssuer,\n audience: resolvedOptions.jwtAudience,\n },\n }),\n ];\n\n // Add TypeORM configuration if using TypeORM store\n const storeConfig = resolvedOptions.storeConfiguration;\n const isTypeOrmStore = storeConfig?.type === 'typeorm';\n if (storeConfig && storeConfig.type === 'typeorm') {\n const typeormOptions = storeConfig.options;\n imports.push(\n TypeOrmModule.forRoot({\n ...typeormOptions,\n entities: [\n ...((typeormOptions.entities || []) as any[]),\n OAuthClientEntity,\n AuthorizationCodeEntity,\n OAuthSessionEntity,\n ],\n }),\n TypeOrmModule.forFeature([\n OAuthClientEntity,\n AuthorizationCodeEntity,\n OAuthSessionEntity,\n ]),\n );\n }\n\n // Create store provider based on configuration\n const oauthStoreProvider = this.createStoreProvider(\n resolvedOptions.storeConfiguration,\n );\n\n // Create alias for compatibility with injection\n const oauthStoreAliasProvider = {\n provide: MemoryStore,\n useExisting: 'IOAuthStore',\n };\n\n const providers: any[] = [\n oauthModuleOptions,\n oauthStoreProvider,\n oauthStoreAliasProvider,\n OAuthStrategyService,\n ClientService,\n JwtTokenService,\n JwtAuthGuard,\n ];\n\n // Add TypeOrmStore to providers if using TypeORM\n if (isTypeOrmStore) {\n providers.push(TypeOrmStore);\n }\n\n return {\n module: McpAuthModule,\n imports,\n controllers: [McpOAuthController],\n providers,\n exports: [\n JwtTokenService,\n 'IOAuthStore',\n MemoryStore,\n JwtAuthGuard,\n OAuthStrategyService,\n ],\n };\n }\n\n private static mergeAndValidateOptions(\n options: AuthUserModuleOptions,\n defaults: OAuthModuleDefaults,\n ): OAuthModuleOptions {\n // Validate required options first\n this.validateRequiredOptions(options);\n\n // Merge with defaults\n const resolvedOptions: OAuthModuleOptions = {\n ...defaults,\n ...options,\n // Ensure jwtIssuer defaults to serverUrl if not provided\n jwtIssuer:\n options.jwtIssuer || options.serverUrl || DEFAULT_OPTIONS.jwtIssuer,\n // Derive cookieSecure from nodeEnv if not explicitly provided\n cookieSecure:\n options.cookieSecure !== undefined\n ? options.cookieSecure\n : (options.nodeEnv || DEFAULT_OPTIONS.nodeEnv) === 'production',\n };\n\n // Final validation of resolved options\n this.validateResolvedOptions(resolvedOptions);\n\n return resolvedOptions;\n }\n\n private static validateRequiredOptions(\n options: AuthUserModuleOptions,\n ): void {\n const requiredFields: (keyof AuthUserModuleOptions)[] = [\n 'provider',\n 'clientId',\n 'clientSecret',\n 'jwtSecret',\n ];\n\n for (const field of requiredFields) {\n if (!options[field]) {\n throw new Error(\n `OAuthModuleOptions: ${String(field)} is required and must be provided by the user`,\n );\n }\n }\n }\n\n private static validateResolvedOptions(options: OAuthModuleOptions): void {\n // Validate JWT secret is strong enough\n if (options.jwtSecret.length < 32) {\n throw new Error(\n 'OAuthModuleOptions: jwtSecret must be at least 32 characters long',\n );\n }\n\n // Validate URLs are proper format\n try {\n new URL(options.serverUrl);\n new URL(options.jwtIssuer);\n } catch (error) {\n throw new Error(\n 'OAuthModuleOptions: serverUrl and jwtIssuer must be valid URLs',\n );\n }\n\n // Validate provider configuration\n if (!options.provider.name || !options.provider.strategy) {\n throw new Error(\n 'OAuthModuleOptions: provider must have name and strategy',\n );\n }\n }\n\n private static createStoreProvider(\n storeConfiguration: OAuthModuleOptions['storeConfiguration'],\n ) {\n if (!storeConfiguration || storeConfiguration.type === 'memory') {\n // Default memory store\n return {\n provide: 'IOAuthStore',\n useValue: new MemoryStore(),\n };\n }\n\n if (storeConfiguration.type === 'typeorm') {\n // TypeORM store\n return {\n provide: 'IOAuthStore',\n useClass: TypeOrmStore,\n };\n }\n\n if (storeConfiguration.type === 'custom') {\n // Custom store\n return {\n provide: 'IOAuthStore',\n useValue: storeConfiguration.store,\n };\n }\n\n throw new Error(\n `Unknown store configuration type: ${(storeConfiguration as any).type}`,\n );\n }\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { OAuthProviderConfig } from './oauth-provider.interface';
2
+ export declare const GitHubOAuthProvider: OAuthProviderConfig;
3
+ //# sourceMappingURL=github.provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.provider.d.ts","sourceRoot":"","sources":["../../../src/authz/providers/github.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAKjE,eAAO,MAAM,mBAAmB,EAAE,mBAkBjC,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitHubOAuthProvider = void 0;
4
+ exports.GitHubOAuthProvider = {
5
+ name: 'github',
6
+ displayName: 'GitHub',
7
+ strategy: require('passport-github').Strategy,
8
+ strategyOptions: ({ serverUrl, clientId, clientSecret }) => ({
9
+ clientID: clientId,
10
+ clientSecret: clientSecret,
11
+ callbackURL: `${serverUrl}/auth/callback`,
12
+ }),
13
+ scope: ['user:email'],
14
+ profileMapper: (profile) => ({
15
+ id: profile.id,
16
+ username: profile.username || profile.login,
17
+ email: profile.emails?.[0]?.value,
18
+ displayName: profile.displayName || profile.name,
19
+ avatarUrl: profile.photos?.[0]?.value || profile.avatar_url,
20
+ raw: profile,
21
+ }),
22
+ };
23
+ //# sourceMappingURL=github.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.provider.js","sourceRoot":"","sources":["../../../src/authz/providers/github.provider.ts"],"names":[],"mappings":";;;AAKa,QAAA,mBAAmB,GAAwB;IACtD,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,QAAQ;IACrB,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,QAAQ;IAC7C,eAAe,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3D,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,YAAY;QAC1B,WAAW,EAAE,GAAG,SAAS,gBAAgB;KAC1C,CAAC;IACF,KAAK,EAAE,CAAC,YAAY,CAAC;IACrB,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC3B,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK;QAC3C,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK;QACjC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI;QAChD,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,OAAO,CAAC,UAAU;QAC3D,GAAG,EAAE,OAAO;KACb,CAAC;CACH,CAAC","sourcesContent":["import { OAuthProviderConfig } from './oauth-provider.interface';\n\n// Note: You'll need to install passport-github2\n// npm install passport-github2 @types/passport-github2\n\nexport const GitHubOAuthProvider: OAuthProviderConfig = {\n name: 'github',\n displayName: 'GitHub',\n strategy: require('passport-github').Strategy,\n strategyOptions: ({ serverUrl, clientId, clientSecret }) => ({\n clientID: clientId,\n clientSecret: clientSecret,\n callbackURL: `${serverUrl}/auth/callback`,\n }),\n scope: ['user:email'],\n profileMapper: (profile) => ({\n id: profile.id,\n username: profile.username || profile.login,\n email: profile.emails?.[0]?.value,\n displayName: profile.displayName || profile.name,\n avatarUrl: profile.photos?.[0]?.value || profile.avatar_url,\n raw: profile,\n }),\n};\n"]}
@@ -0,0 +1,3 @@
1
+ import { OAuthProviderConfig } from './oauth-provider.interface';
2
+ export declare const GoogleOAuthProvider: OAuthProviderConfig;
3
+ //# sourceMappingURL=google.provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.provider.d.ts","sourceRoot":"","sources":["../../../src/authz/providers/google.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE,eAAO,MAAM,mBAAmB,EAAE,mBAkBjC,CAAC"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GoogleOAuthProvider = void 0;
4
+ const passport_google_oauth20_1 = require("passport-google-oauth20");
5
+ exports.GoogleOAuthProvider = {
6
+ name: 'google',
7
+ strategy: passport_google_oauth20_1.Strategy,
8
+ strategyOptions: ({ serverUrl, clientId, clientSecret }) => ({
9
+ clientID: clientId,
10
+ clientSecret: clientSecret,
11
+ callbackURL: `${serverUrl}/auth/callback`,
12
+ scope: ['profile', 'email'],
13
+ }),
14
+ scope: ['profile', 'email'],
15
+ profileMapper: (profile) => ({
16
+ id: profile.id,
17
+ username: profile.emails?.[0]?.value?.split('@')[0] || profile.id,
18
+ email: profile.emails?.[0]?.value,
19
+ displayName: profile.displayName,
20
+ avatarUrl: profile.photos?.[0]?.value,
21
+ raw: profile,
22
+ }),
23
+ };
24
+ //# sourceMappingURL=google.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.provider.js","sourceRoot":"","sources":["../../../src/authz/providers/google.provider.ts"],"names":[],"mappings":";;;AACA,qEAAmD;AAEtC,QAAA,mBAAmB,GAAwB;IACtD,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,kCAAQ;IAClB,eAAe,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3D,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,YAAY;QAC1B,WAAW,EAAE,GAAG,SAAS,gBAAgB;QACzC,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF,KAAK,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC3B,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,EAAE;QACjE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK;QACjC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK;QACrC,GAAG,EAAE,OAAO;KACb,CAAC;CACH,CAAC","sourcesContent":["import { OAuthProviderConfig } from './oauth-provider.interface';\nimport { Strategy } from 'passport-google-oauth20';\n\nexport const GoogleOAuthProvider: OAuthProviderConfig = {\n name: 'google',\n strategy: Strategy,\n strategyOptions: ({ serverUrl, clientId, clientSecret }) => ({\n clientID: clientId,\n clientSecret: clientSecret,\n callbackURL: `${serverUrl}/auth/callback`,\n scope: ['profile', 'email'],\n }),\n scope: ['profile', 'email'],\n profileMapper: (profile) => ({\n id: profile.id,\n username: profile.emails?.[0]?.value?.split('@')[0] || profile.id,\n email: profile.emails?.[0]?.value,\n displayName: profile.displayName,\n avatarUrl: profile.photos?.[0]?.value,\n raw: profile,\n }),\n};\n"]}
@@ -0,0 +1,75 @@
1
+ import { TypeOrmModuleOptions } from '@nestjs/typeorm';
2
+ import { IOAuthStore } from '../stores/oauth-store.interface';
3
+ export interface OAuthProviderConfig {
4
+ name: string;
5
+ displayName?: string;
6
+ strategy: any;
7
+ strategyOptions: (options: {
8
+ serverUrl: string;
9
+ clientId: string;
10
+ clientSecret: string;
11
+ }) => any;
12
+ scope?: string[];
13
+ profileMapper: (profile: any) => OAuthUserProfile;
14
+ }
15
+ export interface OAuthUserProfile {
16
+ id: string;
17
+ username: string;
18
+ email?: string;
19
+ displayName?: string;
20
+ avatarUrl?: string;
21
+ raw?: any;
22
+ }
23
+ export type StoreConfiguration = {
24
+ type: 'typeorm';
25
+ options: TypeOrmModuleOptions;
26
+ } | {
27
+ type: 'custom';
28
+ store: IOAuthStore;
29
+ } | {
30
+ type: 'memory';
31
+ } | undefined;
32
+ export interface OAuthUserModuleOptions {
33
+ provider: OAuthProviderConfig;
34
+ clientId: string;
35
+ clientSecret: string;
36
+ jwtSecret: string;
37
+ serverUrl?: string;
38
+ jwtIssuer?: string;
39
+ jwtAudience?: string;
40
+ jwtAccessTokenExpiresIn?: string;
41
+ jwtRefreshTokenExpiresIn?: string;
42
+ cookieSecure?: boolean;
43
+ cookieMaxAge?: number;
44
+ oauthSessionExpiresIn?: number;
45
+ authCodeExpiresIn?: number;
46
+ nodeEnv?: string;
47
+ storeConfiguration?: StoreConfiguration;
48
+ }
49
+ export interface OAuthModuleDefaults {
50
+ serverUrl: string;
51
+ jwtIssuer: string;
52
+ jwtAudience: string;
53
+ jwtAccessTokenExpiresIn: string;
54
+ jwtRefreshTokenExpiresIn: string;
55
+ cookieMaxAge: number;
56
+ oauthSessionExpiresIn: number;
57
+ authCodeExpiresIn: number;
58
+ nodeEnv: string;
59
+ }
60
+ export type OAuthModuleOptions = Required<Pick<OAuthUserModuleOptions, 'provider' | 'clientId' | 'clientSecret' | 'jwtSecret'>> & Required<OAuthModuleDefaults> & {
61
+ cookieSecure: boolean;
62
+ storeConfiguration?: StoreConfiguration;
63
+ };
64
+ export interface OAuthSession {
65
+ sessionId: string;
66
+ state: string;
67
+ clientId?: string;
68
+ redirectUri?: string;
69
+ codeChallenge?: string;
70
+ codeChallengeMethod?: string;
71
+ oauthState?: string;
72
+ resource?: string;
73
+ expiresAt: number;
74
+ }
75
+ //# sourceMappingURL=oauth-provider.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-provider.interface.d.ts","sourceRoot":"","sources":["../../../src/authz/providers/oauth-provider.interface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=oauth-provider.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth-provider.interface.js","sourceRoot":"","sources":["../../../src/authz/providers/oauth-provider.interface.ts"],"names":[],"mappings":"","sourcesContent":["import { TypeOrmModuleOptions } from '@nestjs/typeorm';\nimport { IOAuthStore } from '../stores/oauth-store.interface';\n\nexport interface OAuthProviderConfig {\n name: string;\n displayName?: string;\n strategy: any; // Passport Strategy constructor\n strategyOptions: (options: {\n serverUrl: string;\n clientId: string;\n clientSecret: string;\n }) => any;\n scope?: string[];\n profileMapper: (profile: any) => OAuthUserProfile;\n}\n\nexport interface OAuthUserProfile {\n id: string;\n username: string;\n email?: string;\n displayName?: string;\n avatarUrl?: string;\n raw?: any; // Original profile data\n}\n\n// Store configuration union type\nexport type StoreConfiguration =\n | { type: 'typeorm'; options: TypeOrmModuleOptions }\n | { type: 'custom'; store: IOAuthStore }\n | { type: 'memory' }\n | undefined; // Default to memory store\n\nexport interface OAuthUserModuleOptions {\n provider: OAuthProviderConfig;\n\n // Required OAuth Provider Credentials\n clientId: string;\n clientSecret: string;\n\n // Required JWT Configuration\n jwtSecret: string;\n\n // Server Configuration\n serverUrl?: string;\n\n // JWT Configuration\n jwtIssuer?: string;\n jwtAudience?: string;\n jwtAccessTokenExpiresIn?: string;\n jwtRefreshTokenExpiresIn?: string;\n\n // Cookie Configuration\n cookieSecure?: boolean;\n cookieMaxAge?: number;\n\n // OAuth Session Configuration\n oauthSessionExpiresIn?: number; // in milliseconds\n authCodeExpiresIn?: number; // in milliseconds\n\n // Environment Configuration\n nodeEnv?: string; // 'development' | 'production'\n\n // Storage Configuration - single property for all storage options\n storeConfiguration?: StoreConfiguration;\n}\n\nexport interface OAuthModuleDefaults {\n serverUrl: string;\n jwtIssuer: string;\n jwtAudience: string;\n jwtAccessTokenExpiresIn: string;\n jwtRefreshTokenExpiresIn: string;\n cookieMaxAge: number;\n oauthSessionExpiresIn: number;\n authCodeExpiresIn: number;\n nodeEnv: string;\n}\n\n// Resolved options after merging with defaults\nexport type OAuthModuleOptions = Required<\n Pick<\n OAuthUserModuleOptions,\n 'provider' | 'clientId' | 'clientSecret' | 'jwtSecret'\n >\n> &\n Required<OAuthModuleDefaults> & {\n // Optional fields that may remain undefined\n cookieSecure: boolean;\n storeConfiguration?: StoreConfiguration;\n };\n\nexport interface OAuthSession {\n sessionId: string;\n state: string;\n clientId?: string;\n redirectUri?: string;\n codeChallenge?: string;\n codeChallengeMethod?: string;\n oauthState?: string;\n resource?: string;\n expiresAt: number;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import { ClientRegistrationDto, IOAuthStore, OAuthClient } from '../stores/oauth-store.interface';
2
+ export declare class ClientService {
3
+ private readonly store;
4
+ constructor(store: IOAuthStore);
5
+ registerClient(registrationDto: ClientRegistrationDto): Promise<OAuthClient>;
6
+ getClient(clientId: string): Promise<OAuthClient | null>;
7
+ validateRedirectUri(clientId: string, redirectUri: string): Promise<boolean>;
8
+ private findClientByName;
9
+ }
10
+ //# sourceMappingURL=client.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.service.d.ts","sourceRoot":"","sources":["../../../src/authz/services/client.service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,WAAW,EACZ,MAAM,iCAAiC,CAAC;AAEzC,qBACa,aAAa;IACW,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,WAAW;IAMhE,cAAc,CAClB,eAAe,EAAE,qBAAqB,GACrC,OAAO,CAAC,WAAW,CAAC;IAgEjB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAcxD,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC;YAKL,gBAAgB;CAM/B"}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ClientService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ let ClientService = class ClientService {
18
+ constructor(store) {
19
+ this.store = store;
20
+ }
21
+ async registerClient(registrationDto) {
22
+ if (!registrationDto.redirect_uris ||
23
+ !Array.isArray(registrationDto.redirect_uris)) {
24
+ throw new common_1.BadRequestException('redirect_uris is required and must be an array');
25
+ }
26
+ const defaultClientValues = {
27
+ grant_types: ['authorization_code', 'refresh_token'],
28
+ response_types: ['code'],
29
+ token_endpoint_auth_method: 'none',
30
+ };
31
+ const existingClient = await this.findClientByName(registrationDto.client_name);
32
+ const now = new Date();
33
+ if (existingClient) {
34
+ const updatedClient = {
35
+ ...existingClient,
36
+ ...defaultClientValues,
37
+ ...registrationDto,
38
+ redirect_uris: [
39
+ ...new Set([
40
+ ...existingClient.redirect_uris,
41
+ ...registrationDto.redirect_uris,
42
+ ]),
43
+ ],
44
+ updated_at: now,
45
+ };
46
+ const nc = await this.store.storeClient(updatedClient);
47
+ const filteredClient = Object.fromEntries(Object.entries(nc).filter(([, value]) => value !== null));
48
+ return filteredClient;
49
+ }
50
+ const client_id = this.store.generateClientId(registrationDto);
51
+ const newClient = {
52
+ ...defaultClientValues,
53
+ ...registrationDto,
54
+ client_id,
55
+ created_at: now,
56
+ updated_at: now,
57
+ };
58
+ const client = await this.store.storeClient(newClient);
59
+ const filteredClient = Object.fromEntries(Object.entries(client).filter(([, value]) => value !== null));
60
+ return filteredClient;
61
+ }
62
+ async getClient(clientId) {
63
+ const client = await this.store.getClient(clientId);
64
+ if (!client) {
65
+ return null;
66
+ }
67
+ const filteredClient = Object.fromEntries(Object.entries(client).filter(([, value]) => value !== null));
68
+ return filteredClient;
69
+ }
70
+ async validateRedirectUri(clientId, redirectUri) {
71
+ const client = await this.getClient(clientId);
72
+ return client ? client.redirect_uris.includes(redirectUri) : false;
73
+ }
74
+ async findClientByName(clientName) {
75
+ return await this.store.findClient(clientName);
76
+ }
77
+ };
78
+ exports.ClientService = ClientService;
79
+ exports.ClientService = ClientService = __decorate([
80
+ (0, common_1.Injectable)(),
81
+ __param(0, (0, common_1.Inject)('IOAuthStore')),
82
+ __metadata("design:paramtypes", [Object])
83
+ ], ClientService);
84
+ //# sourceMappingURL=client.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.service.js","sourceRoot":"","sources":["../../../src/authz/services/client.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BadRequestException, Injectable, Inject } from '@nestjs/common';\nimport {\n ClientRegistrationDto,\n IOAuthStore,\n OAuthClient,\n} from '../stores/oauth-store.interface';\n\n@Injectable()\nexport class ClientService {\n constructor(@Inject('IOAuthStore') private readonly store: IOAuthStore) {}\n\n /**\n * Register or update a client application\n * If client with same name exists, update it; otherwise create new\n */\n async registerClient(\n registrationDto: ClientRegistrationDto,\n ): Promise<OAuthClient> {\n // Validate required fields\n if (\n !registrationDto.redirect_uris ||\n !Array.isArray(registrationDto.redirect_uris)\n ) {\n throw new BadRequestException(\n 'redirect_uris is required and must be an array',\n );\n }\n\n // Default values for new clients\n const defaultClientValues = {\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n };\n\n // Check if client with same name already exists\n const existingClient = await this.findClientByName(\n registrationDto.client_name,\n );\n const now = new Date();\n\n if (existingClient) {\n // Update existing client - merge existing, defaults, and new values\n const updatedClient: OAuthClient = {\n ...existingClient,\n ...defaultClientValues,\n ...registrationDto,\n redirect_uris: [\n ...new Set([\n ...existingClient.redirect_uris,\n ...registrationDto.redirect_uris,\n ]),\n ],\n updated_at: now,\n };\n const nc = await this.store.storeClient(updatedClient);\n const filteredClient = Object.fromEntries(\n Object.entries(nc).filter(([, value]) => value !== null),\n ) as OAuthClient;\n return filteredClient;\n }\n\n // Create new client - merge defaults with registration data\n const client_id = this.store.generateClientId(\n registrationDto as OAuthClient,\n );\n const newClient: OAuthClient = {\n ...defaultClientValues,\n ...registrationDto,\n client_id,\n created_at: now,\n updated_at: now,\n };\n const client = await this.store.storeClient(newClient);\n const filteredClient = Object.fromEntries(\n Object.entries(client).filter(([, value]) => value !== null),\n ) as OAuthClient;\n\n return filteredClient;\n }\n\n async getClient(clientId: string): Promise<OAuthClient | null> {\n const client = await this.store.getClient(clientId);\n if (!client) {\n return null;\n }\n\n // Remove null fields from the client object\n const filteredClient = Object.fromEntries(\n Object.entries(client).filter(([, value]) => value !== null),\n ) as OAuthClient;\n\n return filteredClient;\n }\n\n async validateRedirectUri(\n clientId: string,\n redirectUri: string,\n ): Promise<boolean> {\n const client = await this.getClient(clientId);\n return client ? client.redirect_uris.includes(redirectUri) : false;\n }\n\n private async findClientByName(\n clientName: string,\n ): Promise<OAuthClient | undefined> {\n // Use the new findClient method for efficient lookup\n return await this.store.findClient(clientName);\n }\n}\n"]}
@@ -0,0 +1,29 @@
1
+ import { JwtService as NestJwtService } from '@nestjs/jwt';
2
+ import { OAuthModuleOptions } from '../providers/oauth-provider.interface';
3
+ export interface JwtPayload {
4
+ sub: string;
5
+ client_id?: string;
6
+ scope?: string;
7
+ type: 'access' | 'refresh' | 'user';
8
+ user_data?: any;
9
+ iat?: number;
10
+ exp?: number;
11
+ }
12
+ export interface TokenPair {
13
+ access_token: string;
14
+ refresh_token: string;
15
+ token_type: string;
16
+ expires_in: number;
17
+ scope: string;
18
+ }
19
+ export declare class JwtTokenService {
20
+ private readonly jwtService;
21
+ private options;
22
+ constructor(jwtService: NestJwtService, options: OAuthModuleOptions);
23
+ generateTokenPair(userId: string, clientId: string, scope?: string): TokenPair;
24
+ validateToken(token: string): JwtPayload | null;
25
+ refreshAccessToken(refreshToken: string): TokenPair | null;
26
+ generateUserToken(userId: string, userData: any): string;
27
+ private parseExpiresIn;
28
+ }
29
+ //# sourceMappingURL=jwt-token.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-token.service.d.ts","sourceRoot":"","sources":["../../../src/authz/services/jwt-token.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,aAAa,CAAC;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBACa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,UAAU;IACK,OAAO,CAAC,OAAO;gBAD9B,UAAU,EAAE,cAAc,EACH,OAAO,EAAE,kBAAkB;IAGrE,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,SAAS;IAsC1E,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAQ/C,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAkB1D,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,MAAM;IAaxD,OAAO,CAAC,cAAc;CAmBvB"}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.JwtTokenService = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const jwt_1 = require("@nestjs/jwt");
18
+ const crypto_1 = require("crypto");
19
+ let JwtTokenService = class JwtTokenService {
20
+ constructor(jwtService, options) {
21
+ this.jwtService = jwtService;
22
+ this.options = options;
23
+ }
24
+ generateTokenPair(userId, clientId, scope = '') {
25
+ const jti = (0, crypto_1.randomBytes)(16).toString('hex');
26
+ const accessToken = this.jwtService.sign({
27
+ sub: userId,
28
+ client_id: clientId,
29
+ scope,
30
+ type: 'access',
31
+ jti: `access_${jti}`,
32
+ }, {
33
+ expiresIn: this.options.jwtAccessTokenExpiresIn,
34
+ });
35
+ const refreshToken = this.jwtService.sign({
36
+ sub: userId,
37
+ client_id: clientId,
38
+ scope,
39
+ type: 'refresh',
40
+ jti: `refresh_${jti}`,
41
+ }, {
42
+ expiresIn: this.options.jwtRefreshTokenExpiresIn,
43
+ });
44
+ return {
45
+ access_token: accessToken,
46
+ refresh_token: refreshToken,
47
+ token_type: 'Bearer',
48
+ expires_in: this.parseExpiresIn(this.options.jwtAccessTokenExpiresIn),
49
+ scope,
50
+ };
51
+ }
52
+ validateToken(token) {
53
+ try {
54
+ return this.jwtService.verify(token);
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ refreshAccessToken(refreshToken) {
61
+ try {
62
+ const payload = this.jwtService.verify(refreshToken);
63
+ if (payload.type !== 'refresh') {
64
+ return null;
65
+ }
66
+ return this.generateTokenPair(payload.sub, payload.client_id, payload.scope);
67
+ }
68
+ catch (error) {
69
+ return null;
70
+ }
71
+ }
72
+ generateUserToken(userId, userData) {
73
+ return this.jwtService.sign({
74
+ sub: userId,
75
+ type: 'user',
76
+ user_data: userData,
77
+ }, {
78
+ expiresIn: `${Math.floor(this.options.cookieMaxAge / 1000)}s`,
79
+ });
80
+ }
81
+ parseExpiresIn(expiresIn) {
82
+ const match = expiresIn.match(/^(\d+)([smhd]?)$/);
83
+ if (!match) {
84
+ throw new Error(`Invalid expiresIn format: ${expiresIn}`);
85
+ }
86
+ const value = parseInt(match[1], 10);
87
+ const unit = match[2] || 's';
88
+ const multipliers = {
89
+ s: 1,
90
+ m: 60,
91
+ h: 60 * 60,
92
+ d: 24 * 60 * 60,
93
+ };
94
+ return value * multipliers[unit];
95
+ }
96
+ };
97
+ exports.JwtTokenService = JwtTokenService;
98
+ exports.JwtTokenService = JwtTokenService = __decorate([
99
+ (0, common_1.Injectable)(),
100
+ __param(1, (0, common_1.Inject)('OAUTH_MODULE_OPTIONS')),
101
+ __metadata("design:paramtypes", [jwt_1.JwtService, Object])
102
+ ], JwtTokenService);
103
+ //# sourceMappingURL=jwt-token.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-token.service.js","sourceRoot":"","sources":["../../../src/authz/services/jwt-token.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Inject } from '@nestjs/common';\nimport { JwtService as NestJwtService } from '@nestjs/jwt';\nimport { randomBytes } from 'crypto';\nimport { OAuthModuleOptions } from '../providers/oauth-provider.interface';\n\nexport interface JwtPayload {\n sub: string; // user_id\n client_id?: string;\n scope?: string;\n type: 'access' | 'refresh' | 'user';\n user_data?: any;\n iat?: number;\n exp?: number;\n}\n\nexport interface TokenPair {\n access_token: string;\n refresh_token: string;\n token_type: string;\n expires_in: number;\n scope: string;\n}\n\n@Injectable()\nexport class JwtTokenService {\n constructor(\n private readonly jwtService: NestJwtService,\n @Inject('OAUTH_MODULE_OPTIONS') private options: OAuthModuleOptions,\n ) {}\n\n generateTokenPair(userId: string, clientId: string, scope = ''): TokenPair {\n const jti = randomBytes(16).toString('hex'); // JWT ID for tracking\n\n const accessToken = this.jwtService.sign(\n {\n sub: userId,\n client_id: clientId,\n scope,\n type: 'access',\n jti: `access_${jti}`,\n } as JwtPayload,\n {\n expiresIn: this.options.jwtAccessTokenExpiresIn,\n },\n );\n\n const refreshToken = this.jwtService.sign(\n {\n sub: userId,\n client_id: clientId,\n scope,\n type: 'refresh',\n jti: `refresh_${jti}`,\n } as JwtPayload,\n {\n expiresIn: this.options.jwtRefreshTokenExpiresIn,\n },\n );\n\n return {\n access_token: accessToken,\n refresh_token: refreshToken,\n token_type: 'Bearer',\n expires_in: this.parseExpiresIn(this.options.jwtAccessTokenExpiresIn),\n scope,\n };\n }\n\n validateToken(token: string): JwtPayload | null {\n try {\n return this.jwtService.verify<JwtPayload>(token);\n } catch {\n return null;\n }\n }\n\n refreshAccessToken(refreshToken: string): TokenPair | null {\n try {\n const payload = this.jwtService.verify(refreshToken) as JwtPayload;\n\n if (payload.type !== 'refresh') {\n return null;\n }\n\n return this.generateTokenPair(\n payload.sub,\n payload.client_id!,\n payload.scope,\n );\n } catch (error) {\n return null;\n }\n }\n\n generateUserToken(userId: string, userData: any): string {\n return this.jwtService.sign(\n {\n sub: userId,\n type: 'user',\n user_data: userData,\n } as JwtPayload,\n {\n expiresIn: `${Math.floor(this.options.cookieMaxAge / 1000)}s`,\n },\n );\n }\n\n private parseExpiresIn(expiresIn: string): number {\n // Handle formats like \"60s\", \"30d\", \"24h\", \"1440m\"\n const match = expiresIn.match(/^(\\d+)([smhd]?)$/);\n if (!match) {\n throw new Error(`Invalid expiresIn format: ${expiresIn}`);\n }\n\n const value = parseInt(match[1], 10);\n const unit = match[2] || 's'; // default to seconds\n\n const multipliers = {\n s: 1,\n m: 60,\n h: 60 * 60,\n d: 24 * 60 * 60,\n };\n\n return value * multipliers[unit as keyof typeof multipliers];\n }\n}\n"]}