@marxbiotech/signet-integration 0.1.0
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/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/bearer-challenge.d.ts +27 -0
- package/dist/bearer-challenge.filter.d.ts +13 -0
- package/dist/bearer-challenge.filter.js +76 -0
- package/dist/bearer-challenge.filter.js.map +1 -0
- package/dist/bearer-challenge.js +120 -0
- package/dist/bearer-challenge.js.map +1 -0
- package/dist/config.d.ts +23 -0
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -0
- package/dist/deployment-profile.d.ts +25 -0
- package/dist/deployment-profile.js +103 -0
- package/dist/deployment-profile.js.map +1 -0
- package/dist/guard.d.ts +18 -0
- package/dist/guard.js +210 -0
- package/dist/guard.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt-verifier.d.ts +36 -0
- package/dist/jwt-verifier.js +167 -0
- package/dist/jwt-verifier.js.map +1 -0
- package/dist/log-sanitise.d.ts +3 -0
- package/dist/log-sanitise.js +23 -0
- package/dist/log-sanitise.js.map +1 -0
- package/dist/module.d.ts +12 -0
- package/dist/module.js +61 -0
- package/dist/module.js.map +1 -0
- package/dist/options.d.ts +31 -0
- package/dist/options.js +9 -0
- package/dist/options.js.map +1 -0
- package/dist/principal-resolver.d.ts +19 -0
- package/dist/principal-resolver.js +25 -0
- package/dist/principal-resolver.js.map +1 -0
- package/dist/principal.decorator.d.ts +2 -0
- package/dist/principal.decorator.js +28 -0
- package/dist/principal.decorator.js.map +1 -0
- package/dist/protected-resource.controller.d.ts +11 -0
- package/dist/protected-resource.controller.js +130 -0
- package/dist/protected-resource.controller.js.map +1 -0
- package/dist/public.decorator.d.ts +2 -0
- package/dist/public.decorator.js +11 -0
- package/dist/public.decorator.js.map +1 -0
- package/dist/scope-vocabulary.d.ts +17 -0
- package/dist/scope-vocabulary.js +52 -0
- package/dist/scope-vocabulary.js.map +1 -0
- package/dist/strategy.d.ts +16 -0
- package/dist/strategy.js +89 -0
- package/dist/strategy.js.map +1 -0
- package/dist/testing/fixture.d.ts +8 -0
- package/dist/testing/fixture.js +38 -0
- package/dist/testing/fixture.js.map +1 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.js +11 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/jwks-server.d.ts +10 -0
- package/dist/testing/jwks-server.js +33 -0
- package/dist/testing/jwks-server.js.map +1 -0
- package/dist/testing/signet-token.d.ts +18 -0
- package/dist/testing/signet-token.js +31 -0
- package/dist/testing/signet-token.js.map +1 -0
- package/dist/validate-options.d.ts +8 -0
- package/dist/validate-options.js +88 -0
- package/dist/validate-options.js.map +1 -0
- package/package.json +93 -0
package/dist/guard.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
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.SignetBearerGuard = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const core_1 = require("@nestjs/core");
|
|
18
|
+
const passport_1 = require("@nestjs/passport");
|
|
19
|
+
const bearer_challenge_1 = require("./bearer-challenge");
|
|
20
|
+
const deployment_profile_1 = require("./deployment-profile");
|
|
21
|
+
const log_sanitise_1 = require("./log-sanitise");
|
|
22
|
+
const options_1 = require("./options");
|
|
23
|
+
const principal_resolver_1 = require("./principal-resolver");
|
|
24
|
+
const public_decorator_1 = require("./public.decorator");
|
|
25
|
+
const strategy_1 = require("./strategy");
|
|
26
|
+
// The decision line's own keys. A resolver's `logFields` may not reuse them:
|
|
27
|
+
// a second `metric=` or `clientId=` on one line is whichever copy the log
|
|
28
|
+
// parser keeps, and operators alert on these.
|
|
29
|
+
const RESERVED_LOG_KEYS = new Set([
|
|
30
|
+
'metric',
|
|
31
|
+
'reason',
|
|
32
|
+
'clientId',
|
|
33
|
+
'environment',
|
|
34
|
+
]);
|
|
35
|
+
// Nest's OPTIONAL_DEPS_METADATA. `@nestjs/common` does not re-export it.
|
|
36
|
+
const OPTIONAL_PARAMTYPES = 'optional:paramtypes';
|
|
37
|
+
// AuthGuard's mixin marks its constructor parameter 0 `@Optional()`.
|
|
38
|
+
// `Reflect.getMetadata` walks the constructor prototype chain, so a subclass
|
|
39
|
+
// that never writes its own list treats ITS parameter 0 — the principal
|
|
40
|
+
// resolver — as optional. `@Optional()` on a later parameter copies that
|
|
41
|
+
// inherited list onto this constructor before appending its own index.
|
|
42
|
+
// Parameter decorators run before this one, so the copy is already own
|
|
43
|
+
// metadata by the time this drops index 0 (and writes a list when absent).
|
|
44
|
+
function requirePrincipalResolver() {
|
|
45
|
+
return (target) => {
|
|
46
|
+
const own = Reflect.getOwnMetadata(OPTIONAL_PARAMTYPES, target);
|
|
47
|
+
const optionalIndexes = Array.isArray(own)
|
|
48
|
+
? own.filter((index) => index !== 0)
|
|
49
|
+
: [];
|
|
50
|
+
Reflect.defineMetadata(OPTIONAL_PARAMTYPES, optionalIndexes, target);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// The Bearer channel's guard: Passport dispatches SignetJwtStrategy, and a
|
|
54
|
+
// false from it is a uniform 401. A route marked `@Public()` (on the handler
|
|
55
|
+
// or its class) is let through first, so the guard can be an APP_GUARD on
|
|
56
|
+
// its own; a consumer with a credential dispatcher of its own decides
|
|
57
|
+
// `@Public()` there and never hands a public route to this guard. What
|
|
58
|
+
// follows is the layer on top:
|
|
59
|
+
//
|
|
60
|
+
// token lacks the admission scope → 403 (service scope), with an
|
|
61
|
+
// insufficient_scope challenge
|
|
62
|
+
// resolver says { ok: false } → 403, bare
|
|
63
|
+
// resolver throws PrincipalStoreUnavailableError → 503, fail closed
|
|
64
|
+
// resolver throws an HttpException → its own status
|
|
65
|
+
// resolver throws anything else → 500, the error under its own name
|
|
66
|
+
// Passport passed but attached no user → 500, programming error
|
|
67
|
+
//
|
|
68
|
+
// None of these are 401: the token was valid. The 403 messages distinguish
|
|
69
|
+
// "get a token with the right scope" from "ask an administrator" without
|
|
70
|
+
// naming what the caller does not hold. The 500 is deliberately NOT a 503:
|
|
71
|
+
// a bug in the resolver must not send the operator to check the database.
|
|
72
|
+
let SignetBearerGuard = class SignetBearerGuard extends (0, passport_1.AuthGuard)(strategy_1.SIGNET_JWT_STRATEGY) {
|
|
73
|
+
resolver;
|
|
74
|
+
profiles;
|
|
75
|
+
signetOptions;
|
|
76
|
+
reflector;
|
|
77
|
+
// The subclass's name when a consumer subclasses this guard, so its log
|
|
78
|
+
// `context` keeps the name the consumer's operators filter on.
|
|
79
|
+
logger = new common_1.Logger(this.constructor.name);
|
|
80
|
+
constructor(resolver, profiles, signetOptions, reflector) {
|
|
81
|
+
super();
|
|
82
|
+
this.resolver = resolver;
|
|
83
|
+
this.profiles = profiles;
|
|
84
|
+
this.signetOptions = signetOptions;
|
|
85
|
+
this.reflector = reflector;
|
|
86
|
+
}
|
|
87
|
+
async canActivate(context) {
|
|
88
|
+
if (this.reflector.getAllAndOverride(public_decorator_1.IS_PUBLIC_ROUTE, [
|
|
89
|
+
context.getHandler(),
|
|
90
|
+
context.getClass(),
|
|
91
|
+
]) === true) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
// Typed unknown: the base declares boolean | Promise<boolean> |
|
|
95
|
+
// Observable<boolean>, and anything other than a literal true is treated
|
|
96
|
+
// as "did not pass".
|
|
97
|
+
let passed;
|
|
98
|
+
try {
|
|
99
|
+
passed = await super.canActivate(context);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
// Passport's own UnauthorizedException carries a message; the contract
|
|
103
|
+
// is one indistinguishable 401. Anything else is a programming error
|
|
104
|
+
// and must not be dressed up as an authentication failure.
|
|
105
|
+
if (error instanceof common_1.UnauthorizedException) {
|
|
106
|
+
throw new common_1.UnauthorizedException();
|
|
107
|
+
}
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
const request = context.switchToHttp().getRequest();
|
|
111
|
+
const identity = request.user;
|
|
112
|
+
if (passed !== true || identity === undefined) {
|
|
113
|
+
this.logFailure('signet strategy did not pass cleanly', 'signet_identity_missing', 'none');
|
|
114
|
+
throw new common_1.InternalServerErrorException('signet strategy did not pass cleanly');
|
|
115
|
+
}
|
|
116
|
+
const { admissionScope } = this.signetOptions;
|
|
117
|
+
if (!identity.scopes.includes(admissionScope)) {
|
|
118
|
+
this.logger.warn(`signet token lacks service scope: metric=signet_scope_missing source=${(0, log_sanitise_1.sanitiseLogToken)(request.ip ?? 'none')}`);
|
|
119
|
+
// A 403 a client CAN fix by re-authorising (RFC 6750 §3.1); the
|
|
120
|
+
// resolver's refusals below stay bare, because a wider OAuth scope
|
|
121
|
+
// would not supply a missing local authorization.
|
|
122
|
+
throw new bearer_challenge_1.InsufficientScopeException(admissionScope);
|
|
123
|
+
}
|
|
124
|
+
const environment = this.profiles.profile.environment;
|
|
125
|
+
let resolution;
|
|
126
|
+
try {
|
|
127
|
+
resolution = await this.resolver.resolve(identity);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
// An HttpException is a decision already taken below us; it is neither
|
|
131
|
+
// the store nor a bug, and it must reach the caller with its own status.
|
|
132
|
+
if (error instanceof common_1.HttpException)
|
|
133
|
+
throw error;
|
|
134
|
+
if (error instanceof principal_resolver_1.PrincipalStoreUnavailableError) {
|
|
135
|
+
// The line names what actually failed (the cause's class), not the
|
|
136
|
+
// wrapper; the driver's message travels in the stack, never on the
|
|
137
|
+
// key=value line.
|
|
138
|
+
this.logFailure('authorization store unavailable', 'auth_store_unavailable', error.causeName, error.causeStack);
|
|
139
|
+
throw new common_1.ServiceUnavailableException('authorization store unavailable');
|
|
140
|
+
}
|
|
141
|
+
const errorName = error instanceof Error && error.name ? error.name : typeof error;
|
|
142
|
+
const stack = error instanceof Error ? error.stack : undefined;
|
|
143
|
+
// A bug: rethrow unchanged so Nest answers 500 and the error keeps its
|
|
144
|
+
// own name in the exception filter.
|
|
145
|
+
this.logFailure('authorization load failed', 'auth_store_error', errorName, stack);
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
if (!resolution.ok) {
|
|
149
|
+
// The reason is logged for the operator and NOT returned.
|
|
150
|
+
this.logDecision('refused', identity.clientId, environment, resolution);
|
|
151
|
+
throw new common_1.ForbiddenException(this.signetOptions.principalRefusalMessage ??
|
|
152
|
+
'this identity holds no authorization in this service');
|
|
153
|
+
}
|
|
154
|
+
this.logDecision('authorized', identity.clientId, environment, resolution);
|
|
155
|
+
request[this.signetOptions.requestPrincipalKey] = resolution.principal;
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
// The one rendering of this guard's authorization DECISION: the line that
|
|
159
|
+
// lets a request through and the line that refuses one, so their field set
|
|
160
|
+
// and its order cannot drift apart -- metric, reason, the resolver's
|
|
161
|
+
// logFields in the order given, clientId, environment.
|
|
162
|
+
//
|
|
163
|
+
// What these lines disclose about the caller: the client id (software, not
|
|
164
|
+
// a person; a registration identifier, not a credential) and whatever the
|
|
165
|
+
// resolver chose to put in `logFields`. No `sub`, no issuer.
|
|
166
|
+
//
|
|
167
|
+
// Levels: a refusal is a `warn`, an authorization a `log` (info). One line
|
|
168
|
+
// per authorized request is the price of having any record of which client
|
|
169
|
+
// acted; it is paid deliberately, because the alternative is no record.
|
|
170
|
+
logDecision(outcome, clientId, environment, resolution) {
|
|
171
|
+
const consumerFields = Object.entries(resolution.logFields ?? {});
|
|
172
|
+
for (const [key] of consumerFields) {
|
|
173
|
+
if (RESERVED_LOG_KEYS.has(key)) {
|
|
174
|
+
// A programming error in the resolver, not a decision: surfaces as
|
|
175
|
+
// a 500 under its own name rather than a forged log line.
|
|
176
|
+
throw new Error(`resolver logFields must not use the reserved key ${key}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const pairs = [
|
|
180
|
+
['reason', resolution.ok ? 'none' : resolution.reason],
|
|
181
|
+
...consumerFields,
|
|
182
|
+
['clientId', clientId],
|
|
183
|
+
['environment', environment],
|
|
184
|
+
];
|
|
185
|
+
const rendered = pairs
|
|
186
|
+
.map(([key, value]) => `${(0, log_sanitise_1.sanitiseLogToken)(key)}=${(0, log_sanitise_1.sanitiseLogToken)(value)}`)
|
|
187
|
+
.join(' ');
|
|
188
|
+
if (outcome === 'refused') {
|
|
189
|
+
this.logger.warn(`signet principal refused: metric=signet_principal_refused ${rendered}`);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
this.logger.log(`signet principal authorized: metric=signet_principal_authorized ${rendered}`);
|
|
193
|
+
}
|
|
194
|
+
// The one rendering of this guard's failure lines. Only the error's class
|
|
195
|
+
// name goes into the key=value line: the driver's message can carry the
|
|
196
|
+
// DSN or the SQL, so it travels in the stack as the SECOND argument, where
|
|
197
|
+
// a structured logger renders it after the filterable fields.
|
|
198
|
+
logFailure(message, metric, errorName, stack) {
|
|
199
|
+
this.logger.error(`${message}: metric=${metric} errorName=${(0, log_sanitise_1.sanitiseLogToken)(errorName)}`, stack);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
exports.SignetBearerGuard = SignetBearerGuard;
|
|
203
|
+
exports.SignetBearerGuard = SignetBearerGuard = __decorate([
|
|
204
|
+
(0, common_1.Injectable)(),
|
|
205
|
+
requirePrincipalResolver(),
|
|
206
|
+
__param(0, (0, common_1.Inject)(principal_resolver_1.SIGNET_PRINCIPAL_RESOLVER)),
|
|
207
|
+
__param(2, (0, common_1.Inject)(options_1.SIGNET_INTEGRATION_OPTIONS)),
|
|
208
|
+
__metadata("design:paramtypes", [Object, deployment_profile_1.SignetDeploymentProfileService, Object, core_1.Reflector])
|
|
209
|
+
], SignetBearerGuard);
|
|
210
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../src/guard.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { bearerChallenge, carriesScopeChallenge, type ChallengeDecision, challengeFor, insufficientScopeChallenge, InsufficientScopeException, isResourceRequest, protectedResourceMetadataPath, protectedResourceMetadataUrl, type ScopeChallengeCarrier, } from './bearer-challenge';
|
|
2
|
+
export { BearerChallengeFilter } from './bearer-challenge.filter';
|
|
3
|
+
export { type ChannelFlags, type JwtSettings, readChannelFlags, readSignetAuthConfig, type SignetAuthConfig, type SignetEnvOptions, } from './config';
|
|
4
|
+
export { type DeploymentProfile, type DeploymentProfileInput, type DeploymentProfileResolution, resolveDeploymentProfile, SignetDeploymentProfileService, } from './deployment-profile';
|
|
5
|
+
export { SignetBearerGuard } from './guard';
|
|
6
|
+
export { type JwtRejection, JwtRejectionEnum, JwtVerifier, REMOTE_JWKS_OPTIONS, type VerifiedSignetIdentity, type VerifyResult, } from './jwt-verifier';
|
|
7
|
+
export { type ResolverProvider, SignetIntegrationModule, type SignetIntegrationModuleOptions, } from './module';
|
|
8
|
+
export { DEVELOPMENT_ENVIRONMENT, SIGNET_INTEGRATION_OPTIONS, type SignetDeployedProfile, type SignetDevelopmentProfile, type SignetEnvNames, type SignetIntegrationOptions, } from './options';
|
|
9
|
+
export { createSignetPrincipalDecorator } from './principal.decorator';
|
|
10
|
+
export { type PrincipalResolution, PrincipalStoreUnavailableError, SIGNET_PRINCIPAL_RESOLVER, type SignetPrincipalResolver, } from './principal-resolver';
|
|
11
|
+
export { createProtectedResourceController, type ProtectedResourceMetadata, } from './protected-resource.controller';
|
|
12
|
+
export { IS_PUBLIC_ROUTE, Public } from './public.decorator';
|
|
13
|
+
export { createScopeVocabulary, type ScopeVocabulary, type ScopeVocabularyInput, type TokenScopeRead, } from './scope-vocabulary';
|
|
14
|
+
export { bearerToken, SIGNET_JWT_STRATEGY, SignetJwtStrategy, } from './strategy';
|
|
15
|
+
export { validateSignetIntegrationOptions } from './validate-options';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateSignetIntegrationOptions = exports.SignetJwtStrategy = exports.SIGNET_JWT_STRATEGY = exports.bearerToken = exports.createScopeVocabulary = exports.Public = exports.IS_PUBLIC_ROUTE = exports.createProtectedResourceController = exports.SIGNET_PRINCIPAL_RESOLVER = exports.PrincipalStoreUnavailableError = exports.createSignetPrincipalDecorator = exports.SIGNET_INTEGRATION_OPTIONS = exports.DEVELOPMENT_ENVIRONMENT = exports.SignetIntegrationModule = exports.REMOTE_JWKS_OPTIONS = exports.JwtVerifier = exports.JwtRejectionEnum = exports.SignetBearerGuard = exports.SignetDeploymentProfileService = exports.resolveDeploymentProfile = exports.readSignetAuthConfig = exports.readChannelFlags = exports.BearerChallengeFilter = exports.protectedResourceMetadataUrl = exports.protectedResourceMetadataPath = exports.isResourceRequest = exports.InsufficientScopeException = exports.insufficientScopeChallenge = exports.challengeFor = exports.carriesScopeChallenge = exports.bearerChallenge = void 0;
|
|
4
|
+
var bearer_challenge_1 = require("./bearer-challenge");
|
|
5
|
+
Object.defineProperty(exports, "bearerChallenge", { enumerable: true, get: function () { return bearer_challenge_1.bearerChallenge; } });
|
|
6
|
+
Object.defineProperty(exports, "carriesScopeChallenge", { enumerable: true, get: function () { return bearer_challenge_1.carriesScopeChallenge; } });
|
|
7
|
+
Object.defineProperty(exports, "challengeFor", { enumerable: true, get: function () { return bearer_challenge_1.challengeFor; } });
|
|
8
|
+
Object.defineProperty(exports, "insufficientScopeChallenge", { enumerable: true, get: function () { return bearer_challenge_1.insufficientScopeChallenge; } });
|
|
9
|
+
Object.defineProperty(exports, "InsufficientScopeException", { enumerable: true, get: function () { return bearer_challenge_1.InsufficientScopeException; } });
|
|
10
|
+
Object.defineProperty(exports, "isResourceRequest", { enumerable: true, get: function () { return bearer_challenge_1.isResourceRequest; } });
|
|
11
|
+
Object.defineProperty(exports, "protectedResourceMetadataPath", { enumerable: true, get: function () { return bearer_challenge_1.protectedResourceMetadataPath; } });
|
|
12
|
+
Object.defineProperty(exports, "protectedResourceMetadataUrl", { enumerable: true, get: function () { return bearer_challenge_1.protectedResourceMetadataUrl; } });
|
|
13
|
+
var bearer_challenge_filter_1 = require("./bearer-challenge.filter");
|
|
14
|
+
Object.defineProperty(exports, "BearerChallengeFilter", { enumerable: true, get: function () { return bearer_challenge_filter_1.BearerChallengeFilter; } });
|
|
15
|
+
var config_1 = require("./config");
|
|
16
|
+
Object.defineProperty(exports, "readChannelFlags", { enumerable: true, get: function () { return config_1.readChannelFlags; } });
|
|
17
|
+
Object.defineProperty(exports, "readSignetAuthConfig", { enumerable: true, get: function () { return config_1.readSignetAuthConfig; } });
|
|
18
|
+
var deployment_profile_1 = require("./deployment-profile");
|
|
19
|
+
Object.defineProperty(exports, "resolveDeploymentProfile", { enumerable: true, get: function () { return deployment_profile_1.resolveDeploymentProfile; } });
|
|
20
|
+
Object.defineProperty(exports, "SignetDeploymentProfileService", { enumerable: true, get: function () { return deployment_profile_1.SignetDeploymentProfileService; } });
|
|
21
|
+
var guard_1 = require("./guard");
|
|
22
|
+
Object.defineProperty(exports, "SignetBearerGuard", { enumerable: true, get: function () { return guard_1.SignetBearerGuard; } });
|
|
23
|
+
var jwt_verifier_1 = require("./jwt-verifier");
|
|
24
|
+
Object.defineProperty(exports, "JwtRejectionEnum", { enumerable: true, get: function () { return jwt_verifier_1.JwtRejectionEnum; } });
|
|
25
|
+
Object.defineProperty(exports, "JwtVerifier", { enumerable: true, get: function () { return jwt_verifier_1.JwtVerifier; } });
|
|
26
|
+
Object.defineProperty(exports, "REMOTE_JWKS_OPTIONS", { enumerable: true, get: function () { return jwt_verifier_1.REMOTE_JWKS_OPTIONS; } });
|
|
27
|
+
var module_1 = require("./module");
|
|
28
|
+
Object.defineProperty(exports, "SignetIntegrationModule", { enumerable: true, get: function () { return module_1.SignetIntegrationModule; } });
|
|
29
|
+
var options_1 = require("./options");
|
|
30
|
+
Object.defineProperty(exports, "DEVELOPMENT_ENVIRONMENT", { enumerable: true, get: function () { return options_1.DEVELOPMENT_ENVIRONMENT; } });
|
|
31
|
+
Object.defineProperty(exports, "SIGNET_INTEGRATION_OPTIONS", { enumerable: true, get: function () { return options_1.SIGNET_INTEGRATION_OPTIONS; } });
|
|
32
|
+
var principal_decorator_1 = require("./principal.decorator");
|
|
33
|
+
Object.defineProperty(exports, "createSignetPrincipalDecorator", { enumerable: true, get: function () { return principal_decorator_1.createSignetPrincipalDecorator; } });
|
|
34
|
+
var principal_resolver_1 = require("./principal-resolver");
|
|
35
|
+
Object.defineProperty(exports, "PrincipalStoreUnavailableError", { enumerable: true, get: function () { return principal_resolver_1.PrincipalStoreUnavailableError; } });
|
|
36
|
+
Object.defineProperty(exports, "SIGNET_PRINCIPAL_RESOLVER", { enumerable: true, get: function () { return principal_resolver_1.SIGNET_PRINCIPAL_RESOLVER; } });
|
|
37
|
+
var protected_resource_controller_1 = require("./protected-resource.controller");
|
|
38
|
+
Object.defineProperty(exports, "createProtectedResourceController", { enumerable: true, get: function () { return protected_resource_controller_1.createProtectedResourceController; } });
|
|
39
|
+
var public_decorator_1 = require("./public.decorator");
|
|
40
|
+
Object.defineProperty(exports, "IS_PUBLIC_ROUTE", { enumerable: true, get: function () { return public_decorator_1.IS_PUBLIC_ROUTE; } });
|
|
41
|
+
Object.defineProperty(exports, "Public", { enumerable: true, get: function () { return public_decorator_1.Public; } });
|
|
42
|
+
var scope_vocabulary_1 = require("./scope-vocabulary");
|
|
43
|
+
Object.defineProperty(exports, "createScopeVocabulary", { enumerable: true, get: function () { return scope_vocabulary_1.createScopeVocabulary; } });
|
|
44
|
+
var strategy_1 = require("./strategy");
|
|
45
|
+
Object.defineProperty(exports, "bearerToken", { enumerable: true, get: function () { return strategy_1.bearerToken; } });
|
|
46
|
+
Object.defineProperty(exports, "SIGNET_JWT_STRATEGY", { enumerable: true, get: function () { return strategy_1.SIGNET_JWT_STRATEGY; } });
|
|
47
|
+
Object.defineProperty(exports, "SignetJwtStrategy", { enumerable: true, get: function () { return strategy_1.SignetJwtStrategy; } });
|
|
48
|
+
var validate_options_1 = require("./validate-options");
|
|
49
|
+
Object.defineProperty(exports, "validateSignetIntegrationOptions", { enumerable: true, get: function () { return validate_options_1.validateSignetIntegrationOptions; } });
|
|
50
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uDAW4B;AAV1B,mHAAA,eAAe,OAAA;AACf,yHAAA,qBAAqB,OAAA;AAErB,gHAAA,YAAY,OAAA;AACZ,8HAAA,0BAA0B,OAAA;AAC1B,8HAAA,0BAA0B,OAAA;AAC1B,qHAAA,iBAAiB,OAAA;AACjB,iIAAA,6BAA6B,OAAA;AAC7B,gIAAA,4BAA4B,OAAA;AAG9B,qEAAkE;AAAzD,gIAAA,qBAAqB,OAAA;AAC9B,mCAOkB;AAJhB,0GAAA,gBAAgB,OAAA;AAChB,8GAAA,oBAAoB,OAAA;AAItB,2DAM8B;AAF5B,8HAAA,wBAAwB,OAAA;AACxB,oIAAA,8BAA8B,OAAA;AAEhC,iCAA4C;AAAnC,0GAAA,iBAAiB,OAAA;AAC1B,+CAOwB;AALtB,gHAAA,gBAAgB,OAAA;AAChB,2GAAA,WAAW,OAAA;AACX,mHAAA,mBAAmB,OAAA;AAIrB,mCAIkB;AAFhB,iHAAA,uBAAuB,OAAA;AAGzB,qCAOmB;AANjB,kHAAA,uBAAuB,OAAA;AACvB,qHAAA,0BAA0B,OAAA;AAM5B,6DAAuE;AAA9D,qIAAA,8BAA8B,OAAA;AACvC,2DAK8B;AAH5B,oIAAA,8BAA8B,OAAA;AAC9B,+HAAA,yBAAyB,OAAA;AAG3B,iFAGyC;AAFvC,kJAAA,iCAAiC,OAAA;AAGnC,uDAA6D;AAApD,mHAAA,eAAe,OAAA;AAAE,0GAAA,MAAM,OAAA;AAChC,uDAK4B;AAJ1B,yHAAA,qBAAqB,OAAA;AAKvB,uCAIoB;AAHlB,uGAAA,WAAW,OAAA;AACX,+GAAA,mBAAmB,OAAA;AACnB,6GAAA,iBAAiB,OAAA;AAEnB,uDAAsE;AAA7D,oIAAA,gCAAgC,OAAA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type JWTPayload } from 'jose';
|
|
2
|
+
import { type JwtSettings } from './config';
|
|
3
|
+
export declare const REMOTE_JWKS_OPTIONS: {
|
|
4
|
+
readonly cacheMaxAge: 600000;
|
|
5
|
+
readonly cooldownDuration: 30000;
|
|
6
|
+
readonly timeoutDuration: 3000;
|
|
7
|
+
};
|
|
8
|
+
export interface VerifiedSignetIdentity {
|
|
9
|
+
readonly claims: Readonly<JWTPayload>;
|
|
10
|
+
readonly clientId: string;
|
|
11
|
+
readonly issuer: string;
|
|
12
|
+
readonly scopes: readonly string[];
|
|
13
|
+
readonly subject: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const JwtRejectionEnum: {
|
|
16
|
+
readonly BAD_SCOPE: "ERR_JWT_BAD_SCOPE";
|
|
17
|
+
readonly JWKS_PARSE: "ERR_JOSE_GENERIC:jwks_parse";
|
|
18
|
+
readonly JWKS_STATUS: "ERR_JOSE_GENERIC:jwks_status";
|
|
19
|
+
readonly NO_CLIENT_ID: "ERR_JWT_NO_CLIENT_ID";
|
|
20
|
+
readonly NO_EXP: "ERR_JWT_NO_EXP";
|
|
21
|
+
readonly NO_SUB: "ERR_JWT_NO_SUB";
|
|
22
|
+
};
|
|
23
|
+
export type JwtRejection = (typeof JwtRejectionEnum)[keyof typeof JwtRejectionEnum];
|
|
24
|
+
export type VerifyResult = {
|
|
25
|
+
ok: false;
|
|
26
|
+
reason: string;
|
|
27
|
+
} | {
|
|
28
|
+
ok: true;
|
|
29
|
+
identity: VerifiedSignetIdentity;
|
|
30
|
+
};
|
|
31
|
+
export declare class JwtVerifier {
|
|
32
|
+
private readonly settings;
|
|
33
|
+
private readonly keys;
|
|
34
|
+
constructor(settings: JwtSettings);
|
|
35
|
+
verify(token: string): Promise<VerifyResult>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JwtVerifier = exports.JwtRejectionEnum = exports.REMOTE_JWKS_OPTIONS = void 0;
|
|
4
|
+
const jose_1 = require("jose");
|
|
5
|
+
// Asymmetric signatures only. Allowing HS* opens alg confusion: an attacker
|
|
6
|
+
// signs with our PUBLIC key bytes as the HMAC secret, and a verifier that
|
|
7
|
+
// follows the header's alg accepts it. jose's JWKS path already refuses
|
|
8
|
+
// non-RS/PS/ES/Ed algorithms and only imports public keys, but the keys
|
|
9
|
+
// arrive from a remote endpoint rather than from configuration we read, so
|
|
10
|
+
// the explicit allowlist stays as the second, stated line.
|
|
11
|
+
const ASYMMETRIC_ALGORITHMS = [
|
|
12
|
+
'RS256',
|
|
13
|
+
'RS384',
|
|
14
|
+
'RS512',
|
|
15
|
+
'PS256',
|
|
16
|
+
'PS384',
|
|
17
|
+
'PS512',
|
|
18
|
+
'ES256',
|
|
19
|
+
'ES384',
|
|
20
|
+
'ES512',
|
|
21
|
+
'EdDSA',
|
|
22
|
+
];
|
|
23
|
+
// The remote JWKS options, spelled out rather than left to jose's defaults so
|
|
24
|
+
// the contract is fixed. A longer cooldownDuration only delays the refetch an
|
|
25
|
+
// unknown kid triggers after a rotation, and buys no failure backoff -- a
|
|
26
|
+
// failed fetch clears the pending fetch and the next request tries again
|
|
27
|
+
// regardless.
|
|
28
|
+
exports.REMOTE_JWKS_OPTIONS = {
|
|
29
|
+
cacheMaxAge: 600_000,
|
|
30
|
+
cooldownDuration: 30_000,
|
|
31
|
+
timeoutDuration: 3_000,
|
|
32
|
+
};
|
|
33
|
+
// This package's own rejection codes, alongside the ERR_* codes jose throws.
|
|
34
|
+
exports.JwtRejectionEnum = {
|
|
35
|
+
BAD_SCOPE: 'ERR_JWT_BAD_SCOPE',
|
|
36
|
+
JWKS_PARSE: 'ERR_JOSE_GENERIC:jwks_parse',
|
|
37
|
+
JWKS_STATUS: 'ERR_JOSE_GENERIC:jwks_status',
|
|
38
|
+
NO_CLIENT_ID: 'ERR_JWT_NO_CLIENT_ID',
|
|
39
|
+
NO_EXP: 'ERR_JWT_NO_EXP',
|
|
40
|
+
NO_SUB: 'ERR_JWT_NO_SUB',
|
|
41
|
+
};
|
|
42
|
+
// jose reports both JWKS transport failures -- a non-200 status and an
|
|
43
|
+
// unparseable body -- as JOSEError with the same ERR_JOSE_GENERIC code; only
|
|
44
|
+
// the message tells them apart, and an operator reading logs during an
|
|
45
|
+
// outage needs to.
|
|
46
|
+
function joseRejection(error) {
|
|
47
|
+
if (error.code !== 'ERR_JOSE_GENERIC')
|
|
48
|
+
return error.code;
|
|
49
|
+
if (error.message.includes('Expected 200 OK')) {
|
|
50
|
+
return exports.JwtRejectionEnum.JWKS_STATUS;
|
|
51
|
+
}
|
|
52
|
+
if (error.message.includes('Failed to parse')) {
|
|
53
|
+
return exports.JwtRejectionEnum.JWKS_PARSE;
|
|
54
|
+
}
|
|
55
|
+
return error.code;
|
|
56
|
+
}
|
|
57
|
+
// Hydra's JWT access tokens carry the granted scopes as `scp` (an array);
|
|
58
|
+
// RFC 9068 §2.2.3 spells the same thing `scope` (a space-delimited string).
|
|
59
|
+
// Both are read. Neither present is an EMPTY scope set, which the guard
|
|
60
|
+
// refuses with a 403 for lacking the admission scope; either present with the
|
|
61
|
+
// wrong shape is null, a contract violation the caller answers with 401.
|
|
62
|
+
function scopesOf(payload) {
|
|
63
|
+
const { scope, scp } = payload;
|
|
64
|
+
const scopes = [];
|
|
65
|
+
if (scope !== undefined) {
|
|
66
|
+
if (typeof scope !== 'string')
|
|
67
|
+
return null;
|
|
68
|
+
scopes.push(...scope.split(' ').filter((value) => value !== ''));
|
|
69
|
+
}
|
|
70
|
+
if (scp !== undefined) {
|
|
71
|
+
if (!Array.isArray(scp))
|
|
72
|
+
return null;
|
|
73
|
+
for (const value of scp) {
|
|
74
|
+
if (typeof value !== 'string')
|
|
75
|
+
return null;
|
|
76
|
+
scopes.push(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return scopes;
|
|
80
|
+
}
|
|
81
|
+
// Verifies a Signet access token against the trusted issuer's JWKS and the
|
|
82
|
+
// deployment's canonical resource.
|
|
83
|
+
//
|
|
84
|
+
// Returns a result rather than throwing: the caller logs the reason and
|
|
85
|
+
// answers a uniform 401, so a rejection never tells the client WHICH check
|
|
86
|
+
// failed. Key fetch failures land in the same catch -- unreachable JWKS
|
|
87
|
+
// refuses, never admits.
|
|
88
|
+
//
|
|
89
|
+
// One instance for the life of the process: the remote key set's cache,
|
|
90
|
+
// cooldown and pending-fetch state live on it, so constructing one per
|
|
91
|
+
// request would refetch the whole JWKS on every request and defeat the
|
|
92
|
+
// cache.
|
|
93
|
+
class JwtVerifier {
|
|
94
|
+
settings;
|
|
95
|
+
keys;
|
|
96
|
+
constructor(settings) {
|
|
97
|
+
this.settings = settings;
|
|
98
|
+
this.keys = (0, jose_1.createRemoteJWKSet)(new URL(settings.jwksUri), exports.REMOTE_JWKS_OPTIONS);
|
|
99
|
+
}
|
|
100
|
+
async verify(token) {
|
|
101
|
+
let payload;
|
|
102
|
+
try {
|
|
103
|
+
// issuer / audience / exp / nbf are jose's. audience accepts a string
|
|
104
|
+
// or an array containing the expected value; the issuer's fixed client
|
|
105
|
+
// policy is what keeps a token single-audience.
|
|
106
|
+
({ payload } = await (0, jose_1.jwtVerify)(token, this.keys, {
|
|
107
|
+
algorithms: ASYMMETRIC_ALGORITHMS,
|
|
108
|
+
audience: this.settings.audience,
|
|
109
|
+
clockTolerance: this.settings.clockToleranceS,
|
|
110
|
+
issuer: this.settings.issuer,
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error instanceof jose_1.errors.JOSEError) {
|
|
115
|
+
return { ok: false, reason: joseRejection(error) };
|
|
116
|
+
}
|
|
117
|
+
// Errors from the JWKS fetch that are not jose's own -- Node system
|
|
118
|
+
// errors (ECONNREFUSED, ENOTFOUND, ETIMEDOUT, ...) and a key that Node
|
|
119
|
+
// cannot import (crypto's ERR_CRYPTO_* codes) -- carry a string code and
|
|
120
|
+
// refuse like any other unusable issuer. Matched by shape: Node creates
|
|
121
|
+
// them outside a test runner's vm realm, where instanceof Error is
|
|
122
|
+
// false.
|
|
123
|
+
const { code } = (error ?? {});
|
|
124
|
+
if (typeof code === 'string')
|
|
125
|
+
return { ok: false, reason: code };
|
|
126
|
+
// Anything else is a defect in this process, not a bad token: it must
|
|
127
|
+
// surface as a 500, not hide behind a 401.
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
// jose does not require exp: a token without one never expires, which
|
|
131
|
+
// is a long-lived credential minted by omission.
|
|
132
|
+
if (typeof payload.exp !== 'number') {
|
|
133
|
+
return { ok: false, reason: exports.JwtRejectionEnum.NO_EXP };
|
|
134
|
+
}
|
|
135
|
+
if (typeof payload.sub !== 'string' || payload.sub.length === 0) {
|
|
136
|
+
return { ok: false, reason: exports.JwtRejectionEnum.NO_SUB };
|
|
137
|
+
}
|
|
138
|
+
// RFC 9068 §2.2 makes client_id a required claim of a JWT access token
|
|
139
|
+
// and Signet issues it on every token, dynamically registered clients
|
|
140
|
+
// included -- so a token without one is not the shape this contract
|
|
141
|
+
// accepts, and its absence is an access-token contract failure (401). It
|
|
142
|
+
// is NOT a lookup key: the guard logs it as the software that presented
|
|
143
|
+
// the credential.
|
|
144
|
+
if (typeof payload.client_id !== 'string' || payload.client_id === '') {
|
|
145
|
+
return { ok: false, reason: exports.JwtRejectionEnum.NO_CLIENT_ID };
|
|
146
|
+
}
|
|
147
|
+
const scopes = scopesOf(payload);
|
|
148
|
+
if (scopes === null) {
|
|
149
|
+
return { ok: false, reason: exports.JwtRejectionEnum.BAD_SCOPE };
|
|
150
|
+
}
|
|
151
|
+
// iat is deliberately not required and no maxTokenAge is applied.
|
|
152
|
+
// Business roles the token might carry are ignored here: authorization
|
|
153
|
+
// is the consumer's resolver's alone.
|
|
154
|
+
return {
|
|
155
|
+
identity: {
|
|
156
|
+
claims: Object.freeze(payload),
|
|
157
|
+
clientId: payload.client_id,
|
|
158
|
+
issuer: this.settings.issuer,
|
|
159
|
+
scopes,
|
|
160
|
+
subject: payload.sub,
|
|
161
|
+
},
|
|
162
|
+
ok: true,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
exports.JwtVerifier = JwtVerifier;
|
|
167
|
+
//# sourceMappingURL=jwt-verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt-verifier.js","sourceRoot":"","sources":["../src/jwt-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REFUSAL_ROUTE_MAX = void 0;
|
|
4
|
+
exports.sanitiseLogToken = sanitiseLogToken;
|
|
5
|
+
exports.truncate = truncate;
|
|
6
|
+
// Strip everything that could break OUT of one field of an unquoted
|
|
7
|
+
// "key=value key=value" log record: C0 controls and DEL, all whitespace (the
|
|
8
|
+
// field separator), "=" (the key/value separator), and the double quote and
|
|
9
|
+
// backslash that consumers which do parse quoted values use for grouping and
|
|
10
|
+
// escaping. Applied to the values a caller chose or could influence --
|
|
11
|
+
// reasons, client ids, routes.
|
|
12
|
+
function sanitiseLogToken(value) {
|
|
13
|
+
// eslint-disable-next-line no-control-regex
|
|
14
|
+
return value.replace(/[\s\x00-\x1f\x7f="\\]/g, '_');
|
|
15
|
+
}
|
|
16
|
+
// Longest `route=` a refusal line will carry.
|
|
17
|
+
exports.REFUSAL_ROUTE_MAX = 300;
|
|
18
|
+
// Clips a value to `max` characters and MARKS THE CUT, so a clipped value
|
|
19
|
+
// cannot be read as a whole one.
|
|
20
|
+
function truncate(value, max) {
|
|
21
|
+
return value.length <= max ? value : `${value.slice(0, max)}…(truncated)`;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=log-sanitise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-sanitise.js","sourceRoot":"","sources":["../src/log-sanitise.ts"],"names":[],"mappings":";;;AAMA,4CAGC;AAOD,4BAEC;AAlBD,oEAAoE;AACpE,6EAA6E;AAC7E,4EAA4E;AAC5E,6EAA6E;AAC7E,uEAAuE;AACvE,+BAA+B;AAC/B,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,4CAA4C;IAC5C,OAAO,KAAK,CAAC,OAAO,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC;AAED,8CAA8C;AACjC,QAAA,iBAAiB,GAAG,GAAG,CAAC;AAErC,0EAA0E;AAC1E,iCAAiC;AACjC,SAAgB,QAAQ,CAAC,KAAa,EAAE,GAAW;IACjD,OAAO,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC;AAC5E,CAAC"}
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type DynamicModule, type ExistingProvider, type FactoryProvider, type Type, type ValueProvider } from '@nestjs/common';
|
|
2
|
+
import { type SignetIntegrationOptions } from './options';
|
|
3
|
+
import { type SignetPrincipalResolver } from './principal-resolver';
|
|
4
|
+
export type ResolverProvider = Omit<ExistingProvider<SignetPrincipalResolver>, 'provide'> | Omit<FactoryProvider<SignetPrincipalResolver>, 'provide'> | Omit<ValueProvider<SignetPrincipalResolver>, 'provide'> | Type<SignetPrincipalResolver>;
|
|
5
|
+
export interface SignetIntegrationModuleOptions {
|
|
6
|
+
readonly imports?: DynamicModule['imports'];
|
|
7
|
+
readonly options: SignetIntegrationOptions;
|
|
8
|
+
readonly resolver: ResolverProvider;
|
|
9
|
+
}
|
|
10
|
+
export declare class SignetIntegrationModule {
|
|
11
|
+
static forRoot(input: SignetIntegrationModuleOptions): DynamicModule;
|
|
12
|
+
}
|
package/dist/module.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
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 SignetIntegrationModule_1;
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SignetIntegrationModule = void 0;
|
|
11
|
+
const common_1 = require("@nestjs/common");
|
|
12
|
+
const deployment_profile_1 = require("./deployment-profile");
|
|
13
|
+
const guard_1 = require("./guard");
|
|
14
|
+
const options_1 = require("./options");
|
|
15
|
+
const principal_resolver_1 = require("./principal-resolver");
|
|
16
|
+
const strategy_1 = require("./strategy");
|
|
17
|
+
const validate_options_1 = require("./validate-options");
|
|
18
|
+
// Wires the Bearer channel: options behind their token, the consumer's
|
|
19
|
+
// resolver behind its token, the deployment profile, the Passport strategy
|
|
20
|
+
// (which registers itself by name in its constructor, so it must be a
|
|
21
|
+
// provider) and the guard. Exports everything a consumer's own auth module
|
|
22
|
+
// re-exports or a dispatcher injects.
|
|
23
|
+
//
|
|
24
|
+
// NOT here: the metadata controller (createProtectedResourceController --
|
|
25
|
+
// the consumer declares it in the module of the process that serves the
|
|
26
|
+
// resource), the exception filter (BearerChallengeFilter as APP_FILTER, or
|
|
27
|
+
// the consumer's own filter calling challengeFor), and the guard's mounting
|
|
28
|
+
// (APP_GUARD, or inside a consumer's credential dispatcher).
|
|
29
|
+
let SignetIntegrationModule = SignetIntegrationModule_1 = class SignetIntegrationModule {
|
|
30
|
+
static forRoot(input) {
|
|
31
|
+
const resolver = typeof input.resolver === 'function'
|
|
32
|
+
? { provide: principal_resolver_1.SIGNET_PRINCIPAL_RESOLVER, useClass: input.resolver }
|
|
33
|
+
: { ...input.resolver, provide: principal_resolver_1.SIGNET_PRINCIPAL_RESOLVER };
|
|
34
|
+
return {
|
|
35
|
+
exports: [
|
|
36
|
+
options_1.SIGNET_INTEGRATION_OPTIONS,
|
|
37
|
+
principal_resolver_1.SIGNET_PRINCIPAL_RESOLVER,
|
|
38
|
+
guard_1.SignetBearerGuard,
|
|
39
|
+
deployment_profile_1.SignetDeploymentProfileService,
|
|
40
|
+
strategy_1.SignetJwtStrategy,
|
|
41
|
+
],
|
|
42
|
+
imports: input.imports ?? [],
|
|
43
|
+
module: SignetIntegrationModule_1,
|
|
44
|
+
providers: [
|
|
45
|
+
{
|
|
46
|
+
provide: options_1.SIGNET_INTEGRATION_OPTIONS,
|
|
47
|
+
useValue: (0, validate_options_1.validateSignetIntegrationOptions)(input.options),
|
|
48
|
+
},
|
|
49
|
+
resolver,
|
|
50
|
+
guard_1.SignetBearerGuard,
|
|
51
|
+
deployment_profile_1.SignetDeploymentProfileService,
|
|
52
|
+
strategy_1.SignetJwtStrategy,
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
exports.SignetIntegrationModule = SignetIntegrationModule;
|
|
58
|
+
exports.SignetIntegrationModule = SignetIntegrationModule = SignetIntegrationModule_1 = __decorate([
|
|
59
|
+
(0, common_1.Module)({})
|
|
60
|
+
], SignetIntegrationModule);
|
|
61
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAQwB;AAExB,6DAAsE;AACtE,mCAA4C;AAC5C,uCAGmB;AACnB,6DAG8B;AAC9B,yCAA+C;AAC/C,yDAAsE;AAoBtE,uEAAuE;AACvE,2EAA2E;AAC3E,sEAAsE;AACtE,2EAA2E;AAC3E,sCAAsC;AACtC,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,2EAA2E;AAC3E,4EAA4E;AAC5E,6DAA6D;AAEtD,IAAM,uBAAuB,+BAA7B,MAAM,uBAAuB;IAClC,MAAM,CAAC,OAAO,CAAC,KAAqC;QAClD,MAAM,QAAQ,GACZ,OAAO,KAAK,CAAC,QAAQ,KAAK,UAAU;YAClC,CAAC,CAAC,EAAE,OAAO,EAAE,8CAAyB,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE;YAClE,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,8CAAyB,EAAE,CAAC;QAChE,OAAO;YACL,OAAO,EAAE;gBACP,oCAA0B;gBAC1B,8CAAyB;gBACzB,yBAAiB;gBACjB,mDAA8B;gBAC9B,4BAAiB;aAClB;YACD,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,EAAE;YAC5B,MAAM,EAAE,yBAAuB;YAC/B,SAAS,EAAE;gBACT;oBACE,OAAO,EAAE,oCAA0B;oBACnC,QAAQ,EAAE,IAAA,mDAAgC,EAAC,KAAK,CAAC,OAAO,CAAC;iBAC1D;gBACD,QAAQ;gBACR,yBAAiB;gBACjB,mDAA8B;gBAC9B,4BAAiB;aAClB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA5BY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,uBAAuB,CA4BnC"}
|