@rekog/mcp-nest 1.7.1 → 1.7.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.
- package/README.md +1 -1
- package/dist/authz/adapters/github.adapter.d.ts +40 -0
- package/dist/authz/adapters/github.adapter.d.ts.map +1 -0
- package/dist/authz/adapters/github.adapter.js +212 -0
- package/dist/authz/adapters/github.adapter.js.map +1 -0
- package/dist/authz/adapters/oidc.adapter.d.ts +21 -0
- package/dist/authz/adapters/oidc.adapter.d.ts.map +1 -0
- package/dist/authz/adapters/oidc.adapter.js +125 -0
- package/dist/authz/adapters/oidc.adapter.js.map +1 -0
- package/dist/authz/controllers/resource-metadata.controller.d.ts +62 -0
- package/dist/authz/controllers/resource-metadata.controller.d.ts.map +1 -0
- package/dist/authz/controllers/resource-metadata.controller.js +84 -0
- package/dist/authz/controllers/resource-metadata.controller.js.map +1 -0
- package/dist/authz/controllers/well-known.controller.d.ts +63 -0
- package/dist/authz/controllers/well-known.controller.d.ts.map +1 -0
- package/dist/authz/controllers/well-known.controller.js +131 -0
- package/dist/authz/controllers/well-known.controller.js.map +1 -0
- package/dist/authz/examples/oidc-provider-example.d.ts +3 -0
- package/dist/authz/examples/oidc-provider-example.d.ts.map +1 -0
- package/dist/authz/examples/oidc-provider-example.js +51 -0
- package/dist/authz/examples/oidc-provider-example.js.map +1 -0
- package/dist/authz/guards/jwt-auth.guard.js +1 -1
- package/dist/authz/guards/jwt-auth.guard.js.map +1 -1
- package/dist/authz/mcp-oauth.controller.d.ts +20 -11
- package/dist/authz/mcp-oauth.controller.d.ts.map +1 -1
- package/dist/authz/mcp-oauth.controller.js +91 -17
- package/dist/authz/mcp-oauth.controller.js.map +1 -1
- package/dist/authz/mcp-oauth.module.d.ts.map +1 -1
- package/dist/authz/mcp-oauth.module.js +2 -2
- package/dist/authz/mcp-oauth.module.js.map +1 -1
- package/dist/authz/oidc-provider.controller.d.ts +48 -0
- package/dist/authz/oidc-provider.controller.d.ts.map +1 -0
- package/dist/authz/oidc-provider.controller.js +194 -0
- package/dist/authz/oidc-provider.controller.js.map +1 -0
- package/dist/authz/oidc-provider.module.d.ts +11 -0
- package/dist/authz/oidc-provider.module.d.ts.map +1 -0
- package/dist/authz/oidc-provider.module.js +275 -0
- package/dist/authz/oidc-provider.module.js.map +1 -0
- package/dist/authz/providers/oauth-provider.interface.d.ts +1 -1
- package/dist/authz/providers/oauth-provider.interface.d.ts.map +1 -1
- package/dist/authz/providers/oauth-provider.interface.js.map +1 -1
- package/dist/authz/services/client.service.d.ts.map +1 -1
- package/dist/authz/services/client.service.js +14 -1
- package/dist/authz/services/client.service.js.map +1 -1
- package/dist/authz/services/jwt-token.service.d.ts +1 -0
- package/dist/authz/services/jwt-token.service.d.ts.map +1 -1
- package/dist/authz/services/jwt-token.service.js +10 -6
- package/dist/authz/services/jwt-token.service.js.map +1 -1
- package/dist/authz/stores/oauth-store.interface.d.ts +1 -0
- package/dist/authz/stores/oauth-store.interface.d.ts.map +1 -1
- package/dist/authz/stores/oauth-store.interface.js.map +1 -1
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts +1 -0
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.d.ts.map +1 -1
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.js +4 -0
- package/dist/authz/stores/typeorm/entities/authorization-code.entity.js.map +1 -1
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts +1 -0
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.d.ts.map +1 -1
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.js +4 -0
- package/dist/authz/stores/typeorm/entities/oauth-client.entity.js.map +1 -1
- package/dist/mcp/decorators/prompt.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/resource-template.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/resource.decorator.d.ts.map +1 -1
- package/dist/mcp/decorators/tool.decorator.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/authz/guards/jwt-auth.guard.ts +1 -1
- package/src/authz/mcp-oauth.controller.ts +152 -15
- package/src/authz/mcp-oauth.module.ts +4 -2
- package/src/authz/providers/oauth-provider.interface.ts +1 -1
- package/src/authz/services/client.service.ts +25 -1
- package/src/authz/services/jwt-token.service.ts +16 -8
- package/src/authz/stores/oauth-store.interface.ts +1 -0
- package/src/authz/stores/typeorm/entities/authorization-code.entity.ts +3 -0
- package/src/authz/stores/typeorm/entities/oauth-client.entity.ts +3 -0
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ With `@rekog/mcp-nest` you define tools, resources, and prompts in a way that's
|
|
|
33
33
|
## Installation
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
npm install @rekog/mcp-nest @modelcontextprotocol/sdk zod
|
|
36
|
+
npm install @rekog/mcp-nest @modelcontextprotocol/sdk zod@^3
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
## Quick Start
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Logger } from '@nestjs/common';
|
|
2
|
+
import { IOAuthStore } from '../stores/oauth-store.interface';
|
|
3
|
+
import { OAuthModuleOptions } from '../providers/oauth-provider.interface';
|
|
4
|
+
export declare class GitHubAdapter {
|
|
5
|
+
private readonly store;
|
|
6
|
+
private readonly options;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
constructor(store: IOAuthStore, options: OAuthModuleOptions);
|
|
9
|
+
static create(name: string): {
|
|
10
|
+
new (name: string): {
|
|
11
|
+
readonly logger: Logger;
|
|
12
|
+
readonly name: string;
|
|
13
|
+
find(id: string): Promise<any | null>;
|
|
14
|
+
findClient(clientId: string): Promise<any | null>;
|
|
15
|
+
findSession(sessionId: string): Promise<any | null>;
|
|
16
|
+
findToken(tokenId: string): Promise<any | null>;
|
|
17
|
+
findGrant(grantId: string): Promise<any | null>;
|
|
18
|
+
formatClientForOidc(client: any): any;
|
|
19
|
+
findByUserCode(userCode: string): Promise<any | null>;
|
|
20
|
+
findByDeviceInfo(deviceInfo: any): Promise<any | null>;
|
|
21
|
+
upsert(id: string, payload: any, expiresIn?: number): Promise<void>;
|
|
22
|
+
upsertClient(clientId: string, payload: any): Promise<void>;
|
|
23
|
+
upsertSession(sessionId: string, payload: any, expiresAt?: number): Promise<void>;
|
|
24
|
+
upsertToken(tokenId: string, payload: any, expiresAt?: number): Promise<void>;
|
|
25
|
+
upsertGrant(grantId: string, payload: any, expiresAt?: number): Promise<void>;
|
|
26
|
+
destroy(id: string): Promise<void>;
|
|
27
|
+
destroyClient(clientId: string): Promise<void>;
|
|
28
|
+
destroySession(sessionId: string): Promise<void>;
|
|
29
|
+
destroyToken(tokenId: string): Promise<void>;
|
|
30
|
+
destroyGrant(grantId: string): Promise<void>;
|
|
31
|
+
revokeByGrantId(grantId: string): Promise<void>;
|
|
32
|
+
consume(id: string): Promise<void>;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
static findAccount(ctx: any, id: string): Promise<{
|
|
36
|
+
accountId: string;
|
|
37
|
+
claims(use: string, scope: string): Promise<any>;
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=github.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.adapter.d.ts","sourceRoot":"","sources":["../../../src/authz/adapters/github.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAS3E,qBACa,aAAa;IAIC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAE7C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAL1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAGf,KAAK,EAAE,WAAW,EAEzC,OAAO,EAAE,kBAAkB;IAO9C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM;mBAIY,MAAM;6BAFhB,MAAM;2BAEI,MAAM;qBAOzB,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;iCAmCT,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;mCAgB1B,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;+BAShC,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;+BAS5B,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;wCAQzB,GAAG,GAAG,GAAG;qCAgBb,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;yCAQxB,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;uBAStD,MAAM,WACD,GAAG,cACA,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;mCAwCoB,MAAM,WAAW,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;qCAS3D,MAAM,WACR,GAAG,cACA,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;iCASL,MAAM,WACN,GAAG,cACA,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;iCASL,MAAM,WACN,GAAG,cACA,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;wBAQE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;oCAsCH,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;sCAOpB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;kCAO1B,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;kCAOtB,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;qCAO1B,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;wBAQnC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;;;WAW/B,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM;;oBAOvB,MAAM,SAAS,MAAM;;CA0B5C"}
|
|
@@ -0,0 +1,212 @@
|
|
|
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
|
+
var GitHubAdapter_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.GitHubAdapter = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
let GitHubAdapter = GitHubAdapter_1 = class GitHubAdapter {
|
|
19
|
+
constructor(store, options) {
|
|
20
|
+
this.store = store;
|
|
21
|
+
this.options = options;
|
|
22
|
+
this.logger = new common_1.Logger(GitHubAdapter_1.name);
|
|
23
|
+
}
|
|
24
|
+
static create(name) {
|
|
25
|
+
return class OidcAdapterInstance {
|
|
26
|
+
constructor(name) {
|
|
27
|
+
this.name = name;
|
|
28
|
+
this.logger = new common_1.Logger(`OidcAdapter:${name}`);
|
|
29
|
+
}
|
|
30
|
+
async find(id) {
|
|
31
|
+
this.logger.debug(`Finding ${this.name} with id: ${id}`);
|
|
32
|
+
try {
|
|
33
|
+
switch (this.name) {
|
|
34
|
+
case 'Client':
|
|
35
|
+
const client = await this.findClient(id);
|
|
36
|
+
return client ? this.formatClientForOidc(client) : null;
|
|
37
|
+
case 'Session':
|
|
38
|
+
return await this.findSession(id);
|
|
39
|
+
case 'AccessToken':
|
|
40
|
+
case 'RefreshToken':
|
|
41
|
+
case 'AuthorizationCode':
|
|
42
|
+
case 'IdToken':
|
|
43
|
+
return await this.findToken(id);
|
|
44
|
+
case 'Grant':
|
|
45
|
+
return await this.findGrant(id);
|
|
46
|
+
default:
|
|
47
|
+
this.logger.warn(`Unknown adapter type: ${this.name}`);
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
this.logger.error(`Error finding ${this.name}:`, error);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async findClient(clientId) {
|
|
57
|
+
return {
|
|
58
|
+
client_id: clientId,
|
|
59
|
+
client_secret: 'dummy_secret',
|
|
60
|
+
redirect_uris: ['http://localhost:3000/callback'],
|
|
61
|
+
grant_types: ['authorization_code', 'refresh_token'],
|
|
62
|
+
response_types: ['code'],
|
|
63
|
+
token_endpoint_auth_method: 'client_secret_basic',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async findSession(sessionId) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
async findToken(tokenId) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
async findGrant(grantId) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
formatClientForOidc(client) {
|
|
76
|
+
return {
|
|
77
|
+
client_id: client.client_id,
|
|
78
|
+
client_secret: client.client_secret,
|
|
79
|
+
redirect_uris: client.redirect_uris || [],
|
|
80
|
+
grant_types: client.grant_types || ['authorization_code'],
|
|
81
|
+
response_types: client.response_types || ['code'],
|
|
82
|
+
token_endpoint_auth_method: client.token_endpoint_auth_method || 'client_secret_basic',
|
|
83
|
+
scope: client.scope || 'openid profile email',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async findByUserCode(userCode) {
|
|
87
|
+
this.logger.debug(`Finding ${this.name} by user code: ${userCode}`);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
async findByDeviceInfo(deviceInfo) {
|
|
91
|
+
this.logger.debug(`Finding ${this.name} by device info`);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
async upsert(id, payload, expiresIn) {
|
|
95
|
+
this.logger.debug(`Upserting ${this.name} with id: ${id}`);
|
|
96
|
+
try {
|
|
97
|
+
const expiresAt = expiresIn
|
|
98
|
+
? Date.now() + expiresIn * 1000
|
|
99
|
+
: undefined;
|
|
100
|
+
switch (this.name) {
|
|
101
|
+
case 'Client':
|
|
102
|
+
await this.upsertClient(id, payload);
|
|
103
|
+
break;
|
|
104
|
+
case 'Session':
|
|
105
|
+
await this.upsertSession(id, payload, expiresAt);
|
|
106
|
+
break;
|
|
107
|
+
case 'AccessToken':
|
|
108
|
+
case 'RefreshToken':
|
|
109
|
+
case 'AuthorizationCode':
|
|
110
|
+
case 'IdToken':
|
|
111
|
+
await this.upsertToken(id, payload, expiresAt);
|
|
112
|
+
break;
|
|
113
|
+
case 'Grant':
|
|
114
|
+
await this.upsertGrant(id, payload, expiresAt);
|
|
115
|
+
break;
|
|
116
|
+
default:
|
|
117
|
+
this.logger.warn(`Unknown adapter type for upsert: ${this.name}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
this.logger.error(`Error upserting ${this.name}:`, error);
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async upsertClient(clientId, payload) {
|
|
126
|
+
this.logger.debug(`Client upsert: ${clientId}`, payload);
|
|
127
|
+
}
|
|
128
|
+
async upsertSession(sessionId, payload, expiresAt) {
|
|
129
|
+
this.logger.debug(`Session upsert: ${sessionId}`);
|
|
130
|
+
}
|
|
131
|
+
async upsertToken(tokenId, payload, expiresAt) {
|
|
132
|
+
this.logger.debug(`Token upsert: ${tokenId}, expires: ${expiresAt}`);
|
|
133
|
+
}
|
|
134
|
+
async upsertGrant(grantId, payload, expiresAt) {
|
|
135
|
+
this.logger.debug(`Grant upsert: ${grantId}`);
|
|
136
|
+
}
|
|
137
|
+
async destroy(id) {
|
|
138
|
+
this.logger.debug(`Destroying ${this.name} with id: ${id}`);
|
|
139
|
+
try {
|
|
140
|
+
switch (this.name) {
|
|
141
|
+
case 'Client':
|
|
142
|
+
await this.destroyClient(id);
|
|
143
|
+
break;
|
|
144
|
+
case 'Session':
|
|
145
|
+
await this.destroySession(id);
|
|
146
|
+
break;
|
|
147
|
+
case 'AccessToken':
|
|
148
|
+
case 'RefreshToken':
|
|
149
|
+
case 'AuthorizationCode':
|
|
150
|
+
case 'IdToken':
|
|
151
|
+
await this.destroyToken(id);
|
|
152
|
+
break;
|
|
153
|
+
case 'Grant':
|
|
154
|
+
await this.destroyGrant(id);
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
this.logger.warn(`Unknown adapter type for destroy: ${this.name}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
this.logger.error(`Error destroying ${this.name}:`, error);
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async destroyClient(clientId) {
|
|
166
|
+
this.logger.debug(`Client destroy: ${clientId}`);
|
|
167
|
+
}
|
|
168
|
+
async destroySession(sessionId) {
|
|
169
|
+
this.logger.debug(`Session destroy: ${sessionId}`);
|
|
170
|
+
}
|
|
171
|
+
async destroyToken(tokenId) {
|
|
172
|
+
this.logger.debug(`Token destroy: ${tokenId}`);
|
|
173
|
+
}
|
|
174
|
+
async destroyGrant(grantId) {
|
|
175
|
+
this.logger.debug(`Grant destroy: ${grantId}`);
|
|
176
|
+
}
|
|
177
|
+
async revokeByGrantId(grantId) {
|
|
178
|
+
this.logger.debug(`Revoking ${this.name} by grant id: ${grantId}`);
|
|
179
|
+
}
|
|
180
|
+
async consume(id) {
|
|
181
|
+
this.logger.debug(`Consuming ${this.name} with id: ${id}`);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
static async findAccount(ctx, id) {
|
|
186
|
+
const logger = new common_1.Logger('GitHubAdapter:findAccount');
|
|
187
|
+
logger.debug(`Finding account: ${id}`);
|
|
188
|
+
return {
|
|
189
|
+
accountId: id,
|
|
190
|
+
async claims(use, scope) {
|
|
191
|
+
logger.debug(`Getting claims for account ${id}, use: ${use}, scope: ${scope}`);
|
|
192
|
+
const claims = {
|
|
193
|
+
sub: id,
|
|
194
|
+
};
|
|
195
|
+
if (scope.includes('profile')) {
|
|
196
|
+
claims.preferred_username = id;
|
|
197
|
+
}
|
|
198
|
+
if (scope.includes('email')) {
|
|
199
|
+
}
|
|
200
|
+
return claims;
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
exports.GitHubAdapter = GitHubAdapter;
|
|
206
|
+
exports.GitHubAdapter = GitHubAdapter = GitHubAdapter_1 = __decorate([
|
|
207
|
+
(0, common_1.Injectable)(),
|
|
208
|
+
__param(0, (0, common_1.Inject)('IOAuthStore')),
|
|
209
|
+
__param(1, (0, common_1.Inject)('OAUTH_MODULE_OPTIONS')),
|
|
210
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
211
|
+
], GitHubAdapter);
|
|
212
|
+
//# sourceMappingURL=github.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.adapter.js","sourceRoot":"","sources":["../../../src/authz/adapters/github.adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Inject, Logger } from '@nestjs/common';\nimport { IOAuthStore } from '../stores/oauth-store.interface';\nimport { OAuthModuleOptions } from '../providers/oauth-provider.interface';\n\n/**\n * GitHub Adapter for OIDC Provider\n *\n * This adapter bridges the gap between the OIDC provider and GitHub authentication.\n * It implements the oidc-provider adapter interface to store and retrieve\n * OIDC-related data while integrating with GitHub for user identity.\n */\n@Injectable()\nexport class GitHubAdapter {\n private readonly logger = new Logger(GitHubAdapter.name);\n\n constructor(\n @Inject('IOAuthStore') private readonly store: IOAuthStore,\n @Inject('OAUTH_MODULE_OPTIONS')\n private readonly options: OAuthModuleOptions,\n ) {}\n\n /**\n * OIDC Provider Adapter Factory Function\n * This is called by oidc-provider to create adapter instances\n */\n static create(name: string) {\n return class OidcAdapterInstance {\n public readonly logger: Logger;\n\n constructor(public readonly name: string) {\n this.logger = new Logger(`OidcAdapter:${name}`);\n }\n\n /**\n * Find a stored value by key\n */\n async find(id: string): Promise<any | null> {\n this.logger.debug(`Finding ${this.name} with id: ${id}`);\n\n try {\n switch (this.name) {\n case 'Client':\n // Use existing client service to find clients\n const client = await this.findClient(id);\n return client ? this.formatClientForOidc(client) : null;\n\n case 'Session':\n return await this.findSession(id);\n\n case 'AccessToken':\n case 'RefreshToken':\n case 'AuthorizationCode':\n case 'IdToken':\n return await this.findToken(id);\n\n case 'Grant':\n return await this.findGrant(id);\n\n default:\n this.logger.warn(`Unknown adapter type: ${this.name}`);\n return null;\n }\n } catch (error) {\n this.logger.error(`Error finding ${this.name}:`, error);\n return null;\n }\n }\n\n /**\n * Find a client by client_id\n */\n public async findClient(clientId: string): Promise<any | null> {\n // This would typically use your ClientService\n // For now, return a basic client structure\n return {\n client_id: clientId,\n client_secret: 'dummy_secret', // Should come from your client store\n redirect_uris: ['http://localhost:3000/callback'],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'client_secret_basic',\n };\n }\n\n /**\n * Find a session by session ID\n */\n public async findSession(sessionId: string): Promise<any | null> {\n // Sessions are typically stored in memory or cache\n // Return null for now - sessions will be handled by the interaction flow\n return null;\n }\n\n /**\n * Find a token (access token, refresh token, etc.)\n */\n public async findToken(tokenId: string): Promise<any | null> {\n // Tokens would be stored with their type and relevant data\n // This is a simplified implementation\n return null;\n }\n\n /**\n * Find a grant by grant ID\n */\n public async findGrant(grantId: string): Promise<any | null> {\n // Grants represent the consent given by the user\n return null;\n }\n\n /**\n * Format client data for OIDC provider consumption\n */\n public formatClientForOidc(client: any): any {\n return {\n client_id: client.client_id,\n client_secret: client.client_secret,\n redirect_uris: client.redirect_uris || [],\n grant_types: client.grant_types || ['authorization_code'],\n response_types: client.response_types || ['code'],\n token_endpoint_auth_method:\n client.token_endpoint_auth_method || 'client_secret_basic',\n scope: client.scope || 'openid profile email',\n };\n }\n\n /**\n * Find a stored value by user account and client\n */\n async findByUserCode(userCode: string): Promise<any | null> {\n this.logger.debug(`Finding ${this.name} by user code: ${userCode}`);\n return null;\n }\n\n /**\n * Find a stored value by device info\n */\n async findByDeviceInfo(deviceInfo: any): Promise<any | null> {\n this.logger.debug(`Finding ${this.name} by device info`);\n return null;\n }\n\n /**\n * Store or update a value\n */\n async upsert(\n id: string,\n payload: any,\n expiresIn?: number,\n ): Promise<void> {\n this.logger.debug(`Upserting ${this.name} with id: ${id}`);\n\n try {\n const expiresAt = expiresIn\n ? Date.now() + expiresIn * 1000\n : undefined;\n\n switch (this.name) {\n case 'Client':\n await this.upsertClient(id, payload);\n break;\n\n case 'Session':\n await this.upsertSession(id, payload, expiresAt);\n break;\n\n case 'AccessToken':\n case 'RefreshToken':\n case 'AuthorizationCode':\n case 'IdToken':\n await this.upsertToken(id, payload, expiresAt);\n break;\n\n case 'Grant':\n await this.upsertGrant(id, payload, expiresAt);\n break;\n\n default:\n this.logger.warn(`Unknown adapter type for upsert: ${this.name}`);\n }\n } catch (error) {\n this.logger.error(`Error upserting ${this.name}:`, error);\n throw error;\n }\n }\n\n /**\n * Store or update a client\n */\n public async upsertClient(clientId: string, payload: any): Promise<void> {\n // This would typically use your ClientService\n this.logger.debug(`Client upsert: ${clientId}`, payload);\n }\n\n /**\n * Store or update a session\n */\n public async upsertSession(\n sessionId: string,\n payload: any,\n expiresAt?: number,\n ): Promise<void> {\n // Store session data - typically in cache or memory\n this.logger.debug(`Session upsert: ${sessionId}`);\n }\n\n /**\n * Store or update a token\n */\n public async upsertToken(\n tokenId: string,\n payload: any,\n expiresAt?: number,\n ): Promise<void> {\n // Store token with expiration\n this.logger.debug(`Token upsert: ${tokenId}, expires: ${expiresAt}`);\n }\n\n /**\n * Store or update a grant\n */\n public async upsertGrant(\n grantId: string,\n payload: any,\n expiresAt?: number,\n ): Promise<void> {\n // Store grant information\n this.logger.debug(`Grant upsert: ${grantId}`);\n }\n\n /**\n * Remove a stored value\n */\n async destroy(id: string): Promise<void> {\n this.logger.debug(`Destroying ${this.name} with id: ${id}`);\n\n try {\n switch (this.name) {\n case 'Client':\n await this.destroyClient(id);\n break;\n\n case 'Session':\n await this.destroySession(id);\n break;\n\n case 'AccessToken':\n case 'RefreshToken':\n case 'AuthorizationCode':\n case 'IdToken':\n await this.destroyToken(id);\n break;\n\n case 'Grant':\n await this.destroyGrant(id);\n break;\n\n default:\n this.logger.warn(\n `Unknown adapter type for destroy: ${this.name}`,\n );\n }\n } catch (error) {\n this.logger.error(`Error destroying ${this.name}:`, error);\n throw error;\n }\n }\n\n /**\n * Remove a client\n */\n public async destroyClient(clientId: string): Promise<void> {\n this.logger.debug(`Client destroy: ${clientId}`);\n }\n\n /**\n * Remove a session\n */\n public async destroySession(sessionId: string): Promise<void> {\n this.logger.debug(`Session destroy: ${sessionId}`);\n }\n\n /**\n * Remove a token\n */\n public async destroyToken(tokenId: string): Promise<void> {\n this.logger.debug(`Token destroy: ${tokenId}`);\n }\n\n /**\n * Remove a grant\n */\n public async destroyGrant(grantId: string): Promise<void> {\n this.logger.debug(`Grant destroy: ${grantId}`);\n }\n\n /**\n * Remove expired entries\n */\n async revokeByGrantId(grantId: string): Promise<void> {\n this.logger.debug(`Revoking ${this.name} by grant id: ${grantId}`);\n // Remove all tokens/entries associated with a specific grant\n }\n\n /**\n * Consume a token (mark it as used)\n */\n async consume(id: string): Promise<void> {\n this.logger.debug(`Consuming ${this.name} with id: ${id}`);\n // Mark token as consumed (for one-time use tokens like authorization codes)\n }\n };\n }\n\n /**\n * Account finder for OIDC provider\n * This is called to resolve account information during authentication\n */\n static async findAccount(ctx: any, id: string) {\n const logger = new Logger('GitHubAdapter:findAccount');\n logger.debug(`Finding account: ${id}`);\n\n // Return account information based on the GitHub user ID\n return {\n accountId: id,\n async claims(use: string, scope: string) {\n logger.debug(\n `Getting claims for account ${id}, use: ${use}, scope: ${scope}`,\n );\n\n // Base claims\n const claims: any = {\n sub: id,\n };\n\n // Add claims based on scope\n if (scope.includes('profile')) {\n claims.preferred_username = id;\n // Additional profile claims would be populated here\n // based on stored GitHub user data\n }\n\n if (scope.includes('email')) {\n // Email claims would be populated here\n // based on stored GitHub user data\n }\n\n return claims;\n },\n };\n }\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class OidcMemoryAdapter {
|
|
2
|
+
private readonly name;
|
|
3
|
+
private static storage;
|
|
4
|
+
private logger;
|
|
5
|
+
constructor(name: string);
|
|
6
|
+
find(id: string): Promise<any | null>;
|
|
7
|
+
findByUserCode(userCode: string): Promise<any | null>;
|
|
8
|
+
findByDeviceInfo(deviceInfo: any): Promise<any | null>;
|
|
9
|
+
upsert(id: string, payload: any, expiresIn?: number): Promise<void>;
|
|
10
|
+
destroy(id: string): Promise<void>;
|
|
11
|
+
revokeByGrantId(grantId: string): Promise<void>;
|
|
12
|
+
consume(id: string): Promise<void>;
|
|
13
|
+
private key;
|
|
14
|
+
static create(name: string): any;
|
|
15
|
+
static clearAll(): void;
|
|
16
|
+
static getStats(): {
|
|
17
|
+
total: number;
|
|
18
|
+
byType: Record<string, number>;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=oidc.adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.adapter.d.ts","sourceRoot":"","sources":["../../../src/authz/adapters/oidc.adapter.ts"],"names":[],"mappings":"AAQA,qBAAa,iBAAiB;IAIhB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA0B;IAChD,OAAO,CAAC,MAAM,CAA0C;gBAE3B,IAAI,EAAE,MAAM;IAEnC,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAsBrC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAiBrD,gBAAgB,CAAC,UAAU,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;IAkBtD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnE,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAalC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBxC,OAAO,CAAC,GAAG;IAOX,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM;IAO1B,MAAM,CAAC,QAAQ,IAAI,IAAI;IAQvB,MAAM,CAAC,QAAQ;;;;CAahB"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OidcMemoryAdapter = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
class OidcMemoryAdapter {
|
|
6
|
+
constructor(name) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
this.logger = new common_1.Logger(`OidcAdapter:${this.name}`);
|
|
9
|
+
}
|
|
10
|
+
async find(id) {
|
|
11
|
+
this.logger.debug(`Finding ${this.name} with id: ${id}`);
|
|
12
|
+
const key = this.key(id);
|
|
13
|
+
const item = OidcMemoryAdapter.storage.get(key);
|
|
14
|
+
if (!item) {
|
|
15
|
+
this.logger.debug(`${this.name} not found: ${id}`);
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
if (item.expiresAt && item.expiresAt < Date.now()) {
|
|
19
|
+
this.logger.debug(`${this.name} expired: ${id}`);
|
|
20
|
+
OidcMemoryAdapter.storage.delete(key);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
this.logger.debug(`Found ${this.name}: ${id}`);
|
|
24
|
+
return item.payload;
|
|
25
|
+
}
|
|
26
|
+
async findByUserCode(userCode) {
|
|
27
|
+
this.logger.debug(`Finding ${this.name} by user code: ${userCode}`);
|
|
28
|
+
for (const [key, item] of OidcMemoryAdapter.storage.entries()) {
|
|
29
|
+
if (key.startsWith(`${this.name}:`) && item.payload?.userCode === userCode) {
|
|
30
|
+
if (item.expiresAt && item.expiresAt < Date.now()) {
|
|
31
|
+
OidcMemoryAdapter.storage.delete(key);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
return item.payload;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
async findByDeviceInfo(deviceInfo) {
|
|
40
|
+
this.logger.debug(`Finding ${this.name} by device info`);
|
|
41
|
+
for (const [key, item] of OidcMemoryAdapter.storage.entries()) {
|
|
42
|
+
if (key.startsWith(`${this.name}:`) &&
|
|
43
|
+
item.payload?.deviceInfo === deviceInfo) {
|
|
44
|
+
if (item.expiresAt && item.expiresAt < Date.now()) {
|
|
45
|
+
OidcMemoryAdapter.storage.delete(key);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
return item.payload;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
async upsert(id, payload, expiresIn) {
|
|
54
|
+
this.logger.debug(`Upserting ${this.name} with id: ${id}`);
|
|
55
|
+
const key = this.key(id);
|
|
56
|
+
const expiresAt = expiresIn ? Date.now() + (expiresIn * 1000) : undefined;
|
|
57
|
+
OidcMemoryAdapter.storage.set(key, {
|
|
58
|
+
payload,
|
|
59
|
+
expiresAt,
|
|
60
|
+
});
|
|
61
|
+
this.logger.debug(`Upserted ${this.name}: ${id}${expiresAt ? ` (expires: ${new Date(expiresAt).toISOString()})` : ''}`);
|
|
62
|
+
}
|
|
63
|
+
async destroy(id) {
|
|
64
|
+
this.logger.debug(`Destroying ${this.name} with id: ${id}`);
|
|
65
|
+
const key = this.key(id);
|
|
66
|
+
const deleted = OidcMemoryAdapter.storage.delete(key);
|
|
67
|
+
if (deleted) {
|
|
68
|
+
this.logger.debug(`Destroyed ${this.name}: ${id}`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.logger.debug(`${this.name} not found for destruction: ${id}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async revokeByGrantId(grantId) {
|
|
75
|
+
this.logger.debug(`Revoking ${this.name} by grant id: ${grantId}`);
|
|
76
|
+
const keysToDelete = [];
|
|
77
|
+
for (const [key, item] of OidcMemoryAdapter.storage.entries()) {
|
|
78
|
+
if (key.startsWith(`${this.name}:`) && item.payload?.grantId === grantId) {
|
|
79
|
+
keysToDelete.push(key);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
keysToDelete.forEach(key => {
|
|
83
|
+
OidcMemoryAdapter.storage.delete(key);
|
|
84
|
+
this.logger.debug(`Revoked ${this.name} with key: ${key}`);
|
|
85
|
+
});
|
|
86
|
+
this.logger.debug(`Revoked ${keysToDelete.length} ${this.name} entries for grant: ${grantId}`);
|
|
87
|
+
}
|
|
88
|
+
async consume(id) {
|
|
89
|
+
this.logger.debug(`Consuming ${this.name} with id: ${id}`);
|
|
90
|
+
const key = this.key(id);
|
|
91
|
+
const item = OidcMemoryAdapter.storage.get(key);
|
|
92
|
+
if (item) {
|
|
93
|
+
item.payload.consumed = Date.now();
|
|
94
|
+
OidcMemoryAdapter.storage.set(key, item);
|
|
95
|
+
this.logger.debug(`Consumed ${this.name}: ${id}`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this.logger.debug(`${this.name} not found for consumption: ${id}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
key(id) {
|
|
102
|
+
return `${this.name}:${id}`;
|
|
103
|
+
}
|
|
104
|
+
static create(name) {
|
|
105
|
+
return OidcMemoryAdapter.bind(null, name);
|
|
106
|
+
}
|
|
107
|
+
static clearAll() {
|
|
108
|
+
OidcMemoryAdapter.storage.clear();
|
|
109
|
+
new common_1.Logger('OidcMemoryAdapter').debug('Cleared all stored data');
|
|
110
|
+
}
|
|
111
|
+
static getStats() {
|
|
112
|
+
const stats = {};
|
|
113
|
+
for (const key of OidcMemoryAdapter.storage.keys()) {
|
|
114
|
+
const [type] = key.split(':', 1);
|
|
115
|
+
stats[type] = (stats[type] || 0) + 1;
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
total: OidcMemoryAdapter.storage.size,
|
|
119
|
+
byType: stats,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.OidcMemoryAdapter = OidcMemoryAdapter;
|
|
124
|
+
OidcMemoryAdapter.storage = new Map();
|
|
125
|
+
//# sourceMappingURL=oidc.adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.adapter.js","sourceRoot":"","sources":["../../../src/authz/adapters/oidc.adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger } from '@nestjs/common';\n\n/**\n * Simple Memory Adapter for OIDC Provider\n * \n * This is a basic in-memory adapter for oidc-provider.\n * For production, you should implement persistent storage.\n */\nexport class OidcMemoryAdapter {\n private static storage = new Map<string, any>();\n private logger = new Logger(`OidcAdapter:${this.name}`);\n\n constructor(private readonly name: string) {}\n\n async find(id: string): Promise<any | null> {\n this.logger.debug(`Finding ${this.name} with id: ${id}`);\n \n const key = this.key(id);\n const item = OidcMemoryAdapter.storage.get(key);\n \n if (!item) {\n this.logger.debug(`${this.name} not found: ${id}`);\n return null;\n }\n\n // Check if item has expired\n if (item.expiresAt && item.expiresAt < Date.now()) {\n this.logger.debug(`${this.name} expired: ${id}`);\n OidcMemoryAdapter.storage.delete(key);\n return null;\n }\n\n this.logger.debug(`Found ${this.name}: ${id}`);\n return item.payload;\n }\n\n async findByUserCode(userCode: string): Promise<any | null> {\n this.logger.debug(`Finding ${this.name} by user code: ${userCode}`);\n \n for (const [key, item] of OidcMemoryAdapter.storage.entries()) {\n if (key.startsWith(`${this.name}:`) && item.payload?.userCode === userCode) {\n // Check if expired\n if (item.expiresAt && item.expiresAt < Date.now()) {\n OidcMemoryAdapter.storage.delete(key);\n continue;\n }\n return item.payload;\n }\n }\n \n return null;\n }\n\n async findByDeviceInfo(deviceInfo: any): Promise<any | null> {\n this.logger.debug(`Finding ${this.name} by device info`);\n \n for (const [key, item] of OidcMemoryAdapter.storage.entries()) {\n if (key.startsWith(`${this.name}:`) && \n item.payload?.deviceInfo === deviceInfo) {\n // Check if expired\n if (item.expiresAt && item.expiresAt < Date.now()) {\n OidcMemoryAdapter.storage.delete(key);\n continue;\n }\n return item.payload;\n }\n }\n \n return null;\n }\n\n async upsert(id: string, payload: any, expiresIn?: number): Promise<void> {\n this.logger.debug(`Upserting ${this.name} with id: ${id}`);\n \n const key = this.key(id);\n const expiresAt = expiresIn ? Date.now() + (expiresIn * 1000) : undefined;\n \n OidcMemoryAdapter.storage.set(key, {\n payload,\n expiresAt,\n });\n \n this.logger.debug(`Upserted ${this.name}: ${id}${expiresAt ? ` (expires: ${new Date(expiresAt).toISOString()})` : ''}`);\n }\n\n async destroy(id: string): Promise<void> {\n this.logger.debug(`Destroying ${this.name} with id: ${id}`);\n \n const key = this.key(id);\n const deleted = OidcMemoryAdapter.storage.delete(key);\n \n if (deleted) {\n this.logger.debug(`Destroyed ${this.name}: ${id}`);\n } else {\n this.logger.debug(`${this.name} not found for destruction: ${id}`);\n }\n }\n\n async revokeByGrantId(grantId: string): Promise<void> {\n this.logger.debug(`Revoking ${this.name} by grant id: ${grantId}`);\n \n const keysToDelete: string[] = [];\n \n for (const [key, item] of OidcMemoryAdapter.storage.entries()) {\n if (key.startsWith(`${this.name}:`) && item.payload?.grantId === grantId) {\n keysToDelete.push(key);\n }\n }\n \n keysToDelete.forEach(key => {\n OidcMemoryAdapter.storage.delete(key);\n this.logger.debug(`Revoked ${this.name} with key: ${key}`);\n });\n \n this.logger.debug(`Revoked ${keysToDelete.length} ${this.name} entries for grant: ${grantId}`);\n }\n\n async consume(id: string): Promise<void> {\n this.logger.debug(`Consuming ${this.name} with id: ${id}`);\n \n const key = this.key(id);\n const item = OidcMemoryAdapter.storage.get(key);\n \n if (item) {\n // Mark as consumed\n item.payload.consumed = Date.now();\n OidcMemoryAdapter.storage.set(key, item);\n this.logger.debug(`Consumed ${this.name}: ${id}`);\n } else {\n this.logger.debug(`${this.name} not found for consumption: ${id}`);\n }\n }\n\n private key(id: string): string {\n return `${this.name}:${id}`;\n }\n\n /**\n * Static factory method for oidc-provider\n */\n static create(name: string) {\n return OidcMemoryAdapter.bind(null, name);\n }\n\n /**\n * Clear all stored data (useful for testing)\n */\n static clearAll(): void {\n OidcMemoryAdapter.storage.clear();\n new Logger('OidcMemoryAdapter').debug('Cleared all stored data');\n }\n\n /**\n * Get storage statistics\n */\n static getStats() {\n const stats: Record<string, number> = {};\n \n for (const key of OidcMemoryAdapter.storage.keys()) {\n const [type] = key.split(':', 1);\n stats[type] = (stats[type] || 0) + 1;\n }\n \n return {\n total: OidcMemoryAdapter.storage.size,\n byType: stats,\n };\n }\n}"]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { OAuthModuleOptions } from '../providers/oauth-provider.interface';
|
|
2
|
+
export declare class ResourceMetadataController {
|
|
3
|
+
private readonly options;
|
|
4
|
+
constructor(options: OAuthModuleOptions);
|
|
5
|
+
getProtectedResourceMetadata(): {
|
|
6
|
+
resource: string;
|
|
7
|
+
authorization_server: string;
|
|
8
|
+
scopes_supported: string[];
|
|
9
|
+
bearer_methods_supported: string[];
|
|
10
|
+
resource_documentation: string;
|
|
11
|
+
authorization_server_metadata_uri: string;
|
|
12
|
+
token_types_supported: string[];
|
|
13
|
+
capabilities: string[];
|
|
14
|
+
api_version: string;
|
|
15
|
+
mcp_version: string;
|
|
16
|
+
security_requirements: {
|
|
17
|
+
oauth2: {
|
|
18
|
+
flows: {
|
|
19
|
+
authorizationCode: {
|
|
20
|
+
authorizationUrl: string;
|
|
21
|
+
tokenUrl: string;
|
|
22
|
+
scopes: {
|
|
23
|
+
openid: string;
|
|
24
|
+
profile: string;
|
|
25
|
+
email: string;
|
|
26
|
+
offline_access: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
getResourceServerMetadata(): {
|
|
34
|
+
resource: string;
|
|
35
|
+
authorization_server: string;
|
|
36
|
+
scopes_supported: string[];
|
|
37
|
+
bearer_methods_supported: string[];
|
|
38
|
+
resource_documentation: string;
|
|
39
|
+
authorization_server_metadata_uri: string;
|
|
40
|
+
token_types_supported: string[];
|
|
41
|
+
capabilities: string[];
|
|
42
|
+
api_version: string;
|
|
43
|
+
mcp_version: string;
|
|
44
|
+
security_requirements: {
|
|
45
|
+
oauth2: {
|
|
46
|
+
flows: {
|
|
47
|
+
authorizationCode: {
|
|
48
|
+
authorizationUrl: string;
|
|
49
|
+
tokenUrl: string;
|
|
50
|
+
scopes: {
|
|
51
|
+
openid: string;
|
|
52
|
+
profile: string;
|
|
53
|
+
email: string;
|
|
54
|
+
offline_access: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=resource-metadata.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-metadata.controller.d.ts","sourceRoot":"","sources":["../../../src/authz/controllers/resource-metadata.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAS3E,qBACa,0BAA0B;IAGnC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,kBAAkB;IAW9C,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkE5B,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAG1B"}
|
|
@@ -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.ResourceMetadataController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
let ResourceMetadataController = class ResourceMetadataController {
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.options = options;
|
|
20
|
+
}
|
|
21
|
+
getProtectedResourceMetadata() {
|
|
22
|
+
return {
|
|
23
|
+
resource: this.options.resource,
|
|
24
|
+
authorization_server: this.options.serverUrl,
|
|
25
|
+
scopes_supported: ['openid', 'profile', 'email', 'offline_access'],
|
|
26
|
+
bearer_methods_supported: [
|
|
27
|
+
'header',
|
|
28
|
+
'body',
|
|
29
|
+
'query',
|
|
30
|
+
],
|
|
31
|
+
resource_documentation: `${this.options.serverUrl}/docs`,
|
|
32
|
+
authorization_server_metadata_uri: `${this.options.serverUrl}/.well-known/oauth-authorization-server`,
|
|
33
|
+
token_types_supported: ['Bearer'],
|
|
34
|
+
capabilities: [
|
|
35
|
+
'mcp-server',
|
|
36
|
+
'tools',
|
|
37
|
+
'resources',
|
|
38
|
+
'prompts',
|
|
39
|
+
'server-side-events',
|
|
40
|
+
'streamable-http',
|
|
41
|
+
],
|
|
42
|
+
api_version: '1.0',
|
|
43
|
+
mcp_version: '2025-06-18',
|
|
44
|
+
security_requirements: {
|
|
45
|
+
oauth2: {
|
|
46
|
+
flows: {
|
|
47
|
+
authorizationCode: {
|
|
48
|
+
authorizationUrl: `${this.options.serverUrl}/oidc/auth`,
|
|
49
|
+
tokenUrl: `${this.options.serverUrl}/oidc/token`,
|
|
50
|
+
scopes: {
|
|
51
|
+
openid: 'OpenID Connect authentication',
|
|
52
|
+
profile: 'Access to user profile information',
|
|
53
|
+
email: 'Access to user email address',
|
|
54
|
+
offline_access: 'Refresh token for offline access',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
getResourceServerMetadata() {
|
|
63
|
+
return this.getProtectedResourceMetadata();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
exports.ResourceMetadataController = ResourceMetadataController;
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, common_1.Get)('.well-known/oauth-protected-resource'),
|
|
69
|
+
__metadata("design:type", Function),
|
|
70
|
+
__metadata("design:paramtypes", []),
|
|
71
|
+
__metadata("design:returntype", void 0)
|
|
72
|
+
], ResourceMetadataController.prototype, "getProtectedResourceMetadata", null);
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, common_1.Get)('.well-known/resource-server'),
|
|
75
|
+
__metadata("design:type", Function),
|
|
76
|
+
__metadata("design:paramtypes", []),
|
|
77
|
+
__metadata("design:returntype", void 0)
|
|
78
|
+
], ResourceMetadataController.prototype, "getResourceServerMetadata", null);
|
|
79
|
+
exports.ResourceMetadataController = ResourceMetadataController = __decorate([
|
|
80
|
+
(0, common_1.Controller)(),
|
|
81
|
+
__param(0, (0, common_1.Inject)('OAUTH_MODULE_OPTIONS')),
|
|
82
|
+
__metadata("design:paramtypes", [Object])
|
|
83
|
+
], ResourceMetadataController);
|
|
84
|
+
//# sourceMappingURL=resource-metadata.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-metadata.controller.js","sourceRoot":"","sources":["../../../src/authz/controllers/resource-metadata.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAyD;AAWlD,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IACrC,YAEmB,OAA2B;QAA3B,YAAO,GAAP,OAAO,CAAoB;IAC3C,CAAC;IAUJ,4BAA4B;QAC1B,OAAO;YAEL,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAG/B,oBAAoB,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YAG5C,gBAAgB,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,CAAC;YAGlE,wBAAwB,EAAE;gBACxB,QAAQ;gBACR,MAAM;gBACN,OAAO;aACR;YAGD,sBAAsB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,OAAO;YAGxD,iCAAiC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,yCAAyC;YAGrG,qBAAqB,EAAE,CAAC,QAAQ,CAAC;YAGjC,YAAY,EAAE;gBACZ,YAAY;gBACZ,OAAO;gBACP,WAAW;gBACX,SAAS;gBACT,oBAAoB;gBACpB,iBAAiB;aAClB;YAGD,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,YAAY;YAGzB,qBAAqB,EAAE;gBACrB,MAAM,EAAE;oBACN,KAAK,EAAE;wBACL,iBAAiB,EAAE;4BACjB,gBAAgB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,YAAY;4BACvD,QAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,aAAa;4BAChD,MAAM,EAAE;gCACN,MAAM,EAAE,+BAA+B;gCACvC,OAAO,EAAE,oCAAoC;gCAC7C,KAAK,EAAE,8BAA8B;gCACrC,cAAc,EAAE,kCAAkC;6BACnD;yBACF;qBACF;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAOD,yBAAyB;QACvB,OAAO,IAAI,CAAC,4BAA4B,EAAE,CAAC;IAC7C,CAAC;CACF,CAAA;AAnFY,gEAA0B;AAcrC;IADC,IAAA,YAAG,EAAC,sCAAsC,CAAC;;;;8EA4D3C;AAOD;IADC,IAAA,YAAG,EAAC,6BAA6B,CAAC;;;;2EAGlC;qCAlFU,0BAA0B;IADtC,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,sBAAsB,CAAC,CAAA;;GAFtB,0BAA0B,CAmFtC","sourcesContent":["import { Controller, Get, Inject } from '@nestjs/common';\nimport { OAuthModuleOptions } from '../providers/oauth-provider.interface';\n\n/**\n * OAuth Protected Resource Metadata Controller\n *\n * Implements RFC 8705 - OAuth 2.0 Resource Server Metadata\n * This endpoint describes the protected resource (MCP server) and points\n * to the authorization server that protects it.\n */\n@Controller()\nexport class ResourceMetadataController {\n constructor(\n @Inject('OAUTH_MODULE_OPTIONS')\n private readonly options: OAuthModuleOptions,\n ) {}\n\n /**\n * OAuth Protected Resource Metadata Endpoint\n * GET /.well-known/oauth-protected-resource\n *\n * This endpoint provides metadata about the protected resource (MCP server)\n * including the authorization server that protects it.\n */\n @Get('.well-known/oauth-protected-resource')\n getProtectedResourceMetadata() {\n return {\n // The resource identifier - this is your MCP server\n resource: this.options.resource,\n\n // The authorization server that protects this resource\n authorization_server: this.options.serverUrl,\n\n // Additional metadata about the protected resource\n scopes_supported: ['openid', 'profile', 'email', 'offline_access'],\n\n // Bearer token methods supported\n bearer_methods_supported: [\n 'header', // Authorization: Bearer <token>\n 'body', // access_token in request body\n 'query', // access_token as query parameter\n ],\n\n // Indicate that this resource supports RFC 7662 token introspection\n resource_documentation: `${this.options.serverUrl}/docs`,\n\n // Additional OAuth 2.0 Resource Server metadata\n authorization_server_metadata_uri: `${this.options.serverUrl}/.well-known/oauth-authorization-server`,\n\n // Supported token types\n token_types_supported: ['Bearer'],\n\n // Resource server capabilities\n capabilities: [\n 'mcp-server', // This is an MCP (Model Context Protocol) server\n 'tools', // Supports MCP tools\n 'resources', // Supports MCP resources\n 'prompts', // Supports MCP prompts\n 'server-side-events', // Supports SSE transport\n 'streamable-http', // Supports streamable HTTP transport\n ],\n\n // API version information\n api_version: '1.0',\n mcp_version: '2025-06-18',\n\n // Security requirements\n security_requirements: {\n oauth2: {\n flows: {\n authorizationCode: {\n authorizationUrl: `${this.options.serverUrl}/oidc/auth`,\n tokenUrl: `${this.options.serverUrl}/oidc/token`,\n scopes: {\n openid: 'OpenID Connect authentication',\n profile: 'Access to user profile information',\n email: 'Access to user email address',\n offline_access: 'Refresh token for offline access',\n },\n },\n },\n },\n },\n };\n }\n\n /**\n * Alternative endpoint for OAuth Resource Server Metadata\n * Some clients may look for this alternative path\n */\n @Get('.well-known/resource-server')\n getResourceServerMetadata() {\n return this.getProtectedResourceMetadata();\n }\n}\n"]}
|