@atlasauth/backend 0.4.0 → 0.5.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/dist/discovery.d.ts +49 -0
- package/dist/discovery.js +143 -0
- package/dist/discovery.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/jwks-cache.d.ts +8 -0
- package/dist/jwks-cache.js +20 -3
- package/dist/jwks-cache.js.map +1 -1
- package/dist/verify.d.ts +19 -3
- package/dist/verify.js +27 -5
- package/dist/verify.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OIDC discovery of an instance's JWKS URL, so `new AtlasBackend({ issuer })`
|
|
3
|
+
* works without a `jwksUrl`.
|
|
4
|
+
*
|
|
5
|
+
* Where the document lives:
|
|
6
|
+
* - an instance with its own frontend API host (every instance created from
|
|
7
|
+
* the dashboard): `${issuer}/.well-known/openid-configuration`;
|
|
8
|
+
* - an instance on the SHARED host: its tokens carry the shared issuer, and the
|
|
9
|
+
* shared host's root discovery document describes a different instance's key
|
|
10
|
+
* set. Such an instance must name itself (`instanceId`, or a `publishableKey`
|
|
11
|
+
* it is derived from) so discovery uses the per-instance document at
|
|
12
|
+
* `${issuer}/instances/${instanceId}/.well-known/openid-configuration`.
|
|
13
|
+
*
|
|
14
|
+
* Caching mirrors the JWKS cache: the discovered URL is reused for the JWKS TTL
|
|
15
|
+
* (an hour), a failed refresh keeps serving the last good URL, and a failing
|
|
16
|
+
* endpoint is retried at most once a minute — so a broken or hostile discovery
|
|
17
|
+
* endpoint cannot turn verification traffic into outbound request floods.
|
|
18
|
+
*/
|
|
19
|
+
export declare class DiscoveryError extends Error {
|
|
20
|
+
constructor(message: string);
|
|
21
|
+
}
|
|
22
|
+
export interface JwksDiscoveryDeps {
|
|
23
|
+
/** The `iss` tokens carry. The discovery document's `issuer` must equal it. */
|
|
24
|
+
issuer: string;
|
|
25
|
+
/** Per-instance discovery for shared-host instances. */
|
|
26
|
+
instanceId?: string;
|
|
27
|
+
fetchImpl?: typeof fetch;
|
|
28
|
+
now?: () => number;
|
|
29
|
+
ttlMs?: number;
|
|
30
|
+
refetchIntervalMs?: number;
|
|
31
|
+
}
|
|
32
|
+
/** The instance id inside a publishable key (`pk_live_ins_…` / `pk_test_ins_…`), if it has one. */
|
|
33
|
+
export declare function instanceIdFromPublishableKey(publishableKey: string): string | undefined;
|
|
34
|
+
/** The discovery document URL for an issuer (and optional instance id). */
|
|
35
|
+
export declare function discoveryUrlFor(issuer: string, instanceId?: string): string;
|
|
36
|
+
export declare class JwksDiscovery {
|
|
37
|
+
private readonly deps;
|
|
38
|
+
readonly url: string;
|
|
39
|
+
private cachedUri;
|
|
40
|
+
private fetchedAt;
|
|
41
|
+
private lastAttemptAt;
|
|
42
|
+
private lastError;
|
|
43
|
+
private inflight;
|
|
44
|
+
constructor(deps: JwksDiscoveryDeps);
|
|
45
|
+
private get now();
|
|
46
|
+
/** The JWKS URL, from cache when fresh. Throws {@link DiscoveryError} when none can be had. */
|
|
47
|
+
jwksUri(): Promise<string>;
|
|
48
|
+
private fetchUri;
|
|
49
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JwksDiscovery = exports.DiscoveryError = void 0;
|
|
4
|
+
exports.instanceIdFromPublishableKey = instanceIdFromPublishableKey;
|
|
5
|
+
exports.discoveryUrlFor = discoveryUrlFor;
|
|
6
|
+
const jwks_cache_1 = require("./jwks-cache");
|
|
7
|
+
/**
|
|
8
|
+
* OIDC discovery of an instance's JWKS URL, so `new AtlasBackend({ issuer })`
|
|
9
|
+
* works without a `jwksUrl`.
|
|
10
|
+
*
|
|
11
|
+
* Where the document lives:
|
|
12
|
+
* - an instance with its own frontend API host (every instance created from
|
|
13
|
+
* the dashboard): `${issuer}/.well-known/openid-configuration`;
|
|
14
|
+
* - an instance on the SHARED host: its tokens carry the shared issuer, and the
|
|
15
|
+
* shared host's root discovery document describes a different instance's key
|
|
16
|
+
* set. Such an instance must name itself (`instanceId`, or a `publishableKey`
|
|
17
|
+
* it is derived from) so discovery uses the per-instance document at
|
|
18
|
+
* `${issuer}/instances/${instanceId}/.well-known/openid-configuration`.
|
|
19
|
+
*
|
|
20
|
+
* Caching mirrors the JWKS cache: the discovered URL is reused for the JWKS TTL
|
|
21
|
+
* (an hour), a failed refresh keeps serving the last good URL, and a failing
|
|
22
|
+
* endpoint is retried at most once a minute — so a broken or hostile discovery
|
|
23
|
+
* endpoint cannot turn verification traffic into outbound request floods.
|
|
24
|
+
*/
|
|
25
|
+
class DiscoveryError extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = 'DiscoveryError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.DiscoveryError = DiscoveryError;
|
|
32
|
+
const stripSlash = (value) => value.replace(/\/+$/, '');
|
|
33
|
+
/** The instance id inside a publishable key (`pk_live_ins_…` / `pk_test_ins_…`), if it has one. */
|
|
34
|
+
function instanceIdFromPublishableKey(publishableKey) {
|
|
35
|
+
const match = /^pk_(?:live|test)_(ins_[A-Za-z0-9]+)$/.exec(publishableKey.trim());
|
|
36
|
+
return match?.[1];
|
|
37
|
+
}
|
|
38
|
+
/** The discovery document URL for an issuer (and optional instance id). */
|
|
39
|
+
function discoveryUrlFor(issuer, instanceId) {
|
|
40
|
+
const base = stripSlash(issuer);
|
|
41
|
+
return instanceId
|
|
42
|
+
? `${base}/instances/${encodeURIComponent(instanceId)}/.well-known/openid-configuration`
|
|
43
|
+
: `${base}/.well-known/openid-configuration`;
|
|
44
|
+
}
|
|
45
|
+
function isLoopback(hostname) {
|
|
46
|
+
return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '[::1]';
|
|
47
|
+
}
|
|
48
|
+
class JwksDiscovery {
|
|
49
|
+
deps;
|
|
50
|
+
url;
|
|
51
|
+
cachedUri = null;
|
|
52
|
+
fetchedAt = 0;
|
|
53
|
+
lastAttemptAt = 0;
|
|
54
|
+
lastError = null;
|
|
55
|
+
inflight = null;
|
|
56
|
+
constructor(deps) {
|
|
57
|
+
this.deps = deps;
|
|
58
|
+
this.url = discoveryUrlFor(deps.issuer, deps.instanceId);
|
|
59
|
+
}
|
|
60
|
+
get now() {
|
|
61
|
+
return (this.deps.now ?? Date.now)();
|
|
62
|
+
}
|
|
63
|
+
/** The JWKS URL, from cache when fresh. Throws {@link DiscoveryError} when none can be had. */
|
|
64
|
+
async jwksUri() {
|
|
65
|
+
const now = this.now;
|
|
66
|
+
const ttl = this.deps.ttlMs ?? jwks_cache_1.DEFAULT_TTL_MS;
|
|
67
|
+
const interval = this.deps.refetchIntervalMs ?? jwks_cache_1.REFETCH_INTERVAL_MS;
|
|
68
|
+
if (this.cachedUri && now - this.fetchedAt < ttl)
|
|
69
|
+
return this.cachedUri;
|
|
70
|
+
// Throttle: inside the retry window, answer from what we have (or the last error).
|
|
71
|
+
if (this.lastAttemptAt && now - this.lastAttemptAt < interval) {
|
|
72
|
+
if (this.cachedUri)
|
|
73
|
+
return this.cachedUri;
|
|
74
|
+
if (this.lastError)
|
|
75
|
+
throw this.lastError;
|
|
76
|
+
}
|
|
77
|
+
if (this.inflight)
|
|
78
|
+
return this.inflight;
|
|
79
|
+
this.lastAttemptAt = now;
|
|
80
|
+
this.inflight = this.fetchUri()
|
|
81
|
+
.then((uri) => {
|
|
82
|
+
this.cachedUri = uri;
|
|
83
|
+
this.fetchedAt = now;
|
|
84
|
+
this.lastError = null;
|
|
85
|
+
return uri;
|
|
86
|
+
})
|
|
87
|
+
.catch((error) => {
|
|
88
|
+
this.lastError =
|
|
89
|
+
error instanceof DiscoveryError
|
|
90
|
+
? error
|
|
91
|
+
: new DiscoveryError(`OIDC discovery at ${this.url} failed: ${error?.message ?? String(error)}`);
|
|
92
|
+
// Keep serving the last good URL through a discovery outage.
|
|
93
|
+
if (this.cachedUri)
|
|
94
|
+
return this.cachedUri;
|
|
95
|
+
throw this.lastError;
|
|
96
|
+
})
|
|
97
|
+
.finally(() => {
|
|
98
|
+
this.inflight = null;
|
|
99
|
+
});
|
|
100
|
+
return this.inflight;
|
|
101
|
+
}
|
|
102
|
+
async fetchUri() {
|
|
103
|
+
const fail = (why) => new DiscoveryError(`OIDC discovery at ${this.url} failed: ${why}. Pass \`jwksUrl\` explicitly` +
|
|
104
|
+
(this.deps.instanceId
|
|
105
|
+
? '.'
|
|
106
|
+
: ', or — for an instance without its own frontend API domain — pass `instanceId` (or `publishableKey`).'));
|
|
107
|
+
const response = await (this.deps.fetchImpl ?? fetch)(this.url, {
|
|
108
|
+
headers: { accept: 'application/json' },
|
|
109
|
+
});
|
|
110
|
+
if (!response.ok)
|
|
111
|
+
throw fail(`HTTP ${response.status}`);
|
|
112
|
+
let body;
|
|
113
|
+
try {
|
|
114
|
+
body = await response.json();
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
throw fail('the response is not JSON');
|
|
118
|
+
}
|
|
119
|
+
const doc = body;
|
|
120
|
+
if (!doc || typeof doc !== 'object')
|
|
121
|
+
throw fail('the response is not a discovery document');
|
|
122
|
+
// OIDC Discovery §4.3: the document's issuer MUST match the issuer it was
|
|
123
|
+
// fetched for — otherwise its keys belong to someone else.
|
|
124
|
+
if (typeof doc.issuer !== 'string' || stripSlash(doc.issuer) !== stripSlash(this.deps.issuer)) {
|
|
125
|
+
throw fail(`its issuer (${String(doc.issuer)}) does not match the configured issuer (${this.deps.issuer})`);
|
|
126
|
+
}
|
|
127
|
+
if (typeof doc.jwks_uri !== 'string')
|
|
128
|
+
throw fail('it has no jwks_uri');
|
|
129
|
+
let jwks;
|
|
130
|
+
try {
|
|
131
|
+
jwks = new URL(doc.jwks_uri);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
throw fail('its jwks_uri is not an absolute URL');
|
|
135
|
+
}
|
|
136
|
+
if (jwks.protocol !== 'https:' && !(jwks.protocol === 'http:' && isLoopback(jwks.hostname))) {
|
|
137
|
+
throw fail('its jwks_uri is not https');
|
|
138
|
+
}
|
|
139
|
+
return jwks.toString();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.JwksDiscovery = JwksDiscovery;
|
|
143
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":";;;AA0CA,oEAGC;AAGD,0CAKC;AArDD,6CAAmE;AAEnE;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AALD,wCAKC;AAaD,MAAM,UAAU,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAEhE,mGAAmG;AACnG,SAAgB,4BAA4B,CAAC,cAAsB;IACjE,MAAM,KAAK,GAAG,uCAAuC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC;IAClF,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,2EAA2E;AAC3E,SAAgB,eAAe,CAAC,MAAc,EAAE,UAAmB;IACjE,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,OAAO,UAAU;QACf,CAAC,CAAC,GAAG,IAAI,cAAc,kBAAkB,CAAC,UAAU,CAAC,mCAAmC;QACxF,CAAC,CAAC,GAAG,IAAI,mCAAmC,CAAC;AACjD,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,OAAO,CAAC;AACtF,CAAC;AAED,MAAa,aAAa;IAQK;IAPpB,GAAG,CAAS;IACb,SAAS,GAAkB,IAAI,CAAC;IAChC,SAAS,GAAG,CAAC,CAAC;IACd,aAAa,GAAG,CAAC,CAAC;IAClB,SAAS,GAA0B,IAAI,CAAC;IACxC,QAAQ,GAA2B,IAAI,CAAC;IAEhD,YAA6B,IAAuB;QAAvB,SAAI,GAAJ,IAAI,CAAmB;QAClD,IAAI,CAAC,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3D,CAAC;IAED,IAAY,GAAG;QACb,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACvC,CAAC;IAED,+FAA+F;IAC/F,KAAK,CAAC,OAAO;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,2BAAc,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,gCAAmB,CAAC;QAEpE,IAAI,IAAI,CAAC,SAAS,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,GAAG;YAAE,OAAO,IAAI,CAAC,SAAS,CAAC;QACxE,mFAAmF;QACnF,IAAI,IAAI,CAAC,aAAa,IAAI,GAAG,GAAG,IAAI,CAAC,aAAa,GAAG,QAAQ,EAAE,CAAC;YAC9D,IAAI,IAAI,CAAC,SAAS;gBAAE,OAAO,IAAI,CAAC,SAAS,CAAC;YAC1C,IAAI,IAAI,CAAC,SAAS;gBAAE,MAAM,IAAI,CAAC,SAAS,CAAC;QAC3C,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;QAExC,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;aAC5B,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YACZ,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;YACrB,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;YACrB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,OAAO,GAAG,CAAC;QACb,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YACxB,IAAI,CAAC,SAAS;gBACZ,KAAK,YAAY,cAAc;oBAC7B,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,IAAI,cAAc,CAAC,qBAAqB,IAAI,CAAC,GAAG,YAAa,KAAe,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAChH,6DAA6D;YAC7D,IAAI,IAAI,CAAC,SAAS;gBAAE,OAAO,IAAI,CAAC,SAAS,CAAC;YAC1C,MAAM,IAAI,CAAC,SAAS,CAAC;QACvB,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC,CAAC,CAAC;QACL,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,QAAQ;QACpB,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,EAAE,CAC3B,IAAI,cAAc,CAChB,qBAAqB,IAAI,CAAC,GAAG,YAAY,GAAG,+BAA+B;YACzE,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;gBACnB,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,uGAAuG,CAAC,CAC/G,CAAC;QAEJ,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YAC9D,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;SACxC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,IAAI,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACxD,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzC,CAAC;QACD,MAAM,GAAG,GAAG,IAAuD,CAAC;QACpE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,MAAM,IAAI,CAAC,0CAA0C,CAAC,CAAC;QAE5F,0EAA0E;QAC1E,2DAA2D;QAC3D,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9F,MAAM,IAAI,CAAC,eAAe,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,2CAA2C,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9G,CAAC;QACD,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ;YAAE,MAAM,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACvE,IAAI,IAAS,CAAC;QACd,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,CAAC,qCAAqC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YAC5F,MAAM,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;CACF;AA5FD,sCA4FC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,9 +14,15 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.memoryPcaStore = exports.defaultExtract = exports.requirePCA = exports.verifyPCActn = exports.createTestIssuer = exports.createAtlasClient = void 0;
|
|
17
|
+
exports.memoryPcaStore = exports.defaultExtract = exports.requirePCA = exports.verifyPCActn = exports.createTestIssuer = exports.createAtlasClient = exports.instanceIdFromPublishableKey = exports.discoveryUrlFor = exports.JwksDiscovery = exports.DiscoveryError = void 0;
|
|
18
18
|
// §7.3 token verification — the original surface, unchanged.
|
|
19
19
|
__exportStar(require("./jwks-cache"), exports);
|
|
20
|
+
// OIDC discovery of the JWKS URL when only `issuer` is configured.
|
|
21
|
+
var discovery_1 = require("./discovery");
|
|
22
|
+
Object.defineProperty(exports, "DiscoveryError", { enumerable: true, get: function () { return discovery_1.DiscoveryError; } });
|
|
23
|
+
Object.defineProperty(exports, "JwksDiscovery", { enumerable: true, get: function () { return discovery_1.JwksDiscovery; } });
|
|
24
|
+
Object.defineProperty(exports, "discoveryUrlFor", { enumerable: true, get: function () { return discovery_1.discoveryUrlFor; } });
|
|
25
|
+
Object.defineProperty(exports, "instanceIdFromPublishableKey", { enumerable: true, get: function () { return discovery_1.instanceIdFromPublishableKey; } });
|
|
20
26
|
__exportStar(require("./verify"), exports);
|
|
21
27
|
__exportStar(require("./handshake"), exports);
|
|
22
28
|
// §12.2 inbound webhook verification for consumers.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,+CAA6B;AAC7B,2CAAyB;AACzB,8CAA4B;AAE5B,oDAAoD;AACpD,6CAA2B;AAE3B,8DAA8D;AAC9D,mCAA6C;AAApC,2GAAA,iBAAiB,OAAA;AAE1B,2CAAyB;AAEzB,yEAAyE;AACzE,2EAA2E;AAC3E,iEAAiE;AACjE,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA;AAGzB,wFAAwF;AACxF,2CAA2C;AAC3C,uCAA4C;AAAnC,sGAAA,YAAY,OAAA;AAErB,iDAA+E;AAAtE,yGAAA,UAAU,OAAA;AAAE,6GAAA,cAAc,OAAA;AAAE,6GAAA,cAAc,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,+CAA6B;AAC7B,mEAAmE;AACnE,yCAA2G;AAAlG,2GAAA,cAAc,OAAA;AAAE,0GAAA,aAAa,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,yHAAA,4BAA4B,OAAA;AACrF,2CAAyB;AACzB,8CAA4B;AAE5B,oDAAoD;AACpD,6CAA2B;AAE3B,8DAA8D;AAC9D,mCAA6C;AAApC,2GAAA,iBAAiB,OAAA;AAE1B,2CAAyB;AAEzB,yEAAyE;AACzE,2EAA2E;AAC3E,iEAAiE;AACjE,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA;AAGzB,wFAAwF;AACxF,2CAA2C;AAC3C,uCAA4C;AAAnC,sGAAA,YAAY,OAAA;AAErB,iDAA+E;AAAtE,yGAAA,UAAU,OAAA;AAAE,6GAAA,cAAc,OAAA;AAAE,6GAAA,cAAc,OAAA"}
|
package/dist/jwks-cache.d.ts
CHANGED
|
@@ -34,6 +34,12 @@ export interface JwksCacheDeps {
|
|
|
34
34
|
* when both are given the static set wins and no network call is ever made.
|
|
35
35
|
*/
|
|
36
36
|
staticJwks?: Jwks;
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the JWKS URL lazily (OIDC discovery) when no fixed `url` is given.
|
|
39
|
+
* Called on each fetch attempt; it does its own caching. A rejection is
|
|
40
|
+
* recorded as {@link JwksCache.lastError} and treated like a failed fetch.
|
|
41
|
+
*/
|
|
42
|
+
resolveUrl?: () => Promise<string>;
|
|
37
43
|
fetchImpl?: typeof fetch;
|
|
38
44
|
now?: () => number;
|
|
39
45
|
ttlMs?: number;
|
|
@@ -47,6 +53,8 @@ export declare class JwksCache {
|
|
|
47
53
|
private lastAttemptAt;
|
|
48
54
|
/** Exposed so a caller can assert the rate limit actually bit. */
|
|
49
55
|
lastOutcome: FetchOutcome;
|
|
56
|
+
/** Why the last attempt produced no keys (e.g. a discovery failure), for diagnostics. */
|
|
57
|
+
lastError: string | null;
|
|
50
58
|
constructor(deps: JwksCacheDeps);
|
|
51
59
|
private get now();
|
|
52
60
|
private has;
|
package/dist/jwks-cache.js
CHANGED
|
@@ -29,6 +29,8 @@ class JwksCache {
|
|
|
29
29
|
lastAttemptAt = 0;
|
|
30
30
|
/** Exposed so a caller can assert the rate limit actually bit. */
|
|
31
31
|
lastOutcome = 'fresh';
|
|
32
|
+
/** Why the last attempt produced no keys (e.g. a discovery failure), for diagnostics. */
|
|
33
|
+
lastError = null;
|
|
32
34
|
constructor(deps) {
|
|
33
35
|
this.deps = deps;
|
|
34
36
|
}
|
|
@@ -62,13 +64,12 @@ class JwksCache {
|
|
|
62
64
|
this.lastOutcome = 'cached';
|
|
63
65
|
return this.deps.staticJwks;
|
|
64
66
|
}
|
|
65
|
-
if (this.deps.url === undefined) {
|
|
67
|
+
if (this.deps.url === undefined && this.deps.resolveUrl === undefined) {
|
|
66
68
|
// Neither a URL nor a static set: nothing to verify against. Report
|
|
67
69
|
// "no keys" rather than attempting `fetch(undefined)`.
|
|
68
70
|
this.lastOutcome = 'failed';
|
|
69
71
|
return null;
|
|
70
72
|
}
|
|
71
|
-
const url = this.deps.url;
|
|
72
73
|
const now = this.now;
|
|
73
74
|
const ttl = this.deps.ttlMs ?? exports.DEFAULT_TTL_MS;
|
|
74
75
|
const interval = this.deps.refetchIntervalMs ?? exports.REFETCH_INTERVAL_MS;
|
|
@@ -88,6 +89,20 @@ class JwksCache {
|
|
|
88
89
|
return this.cached;
|
|
89
90
|
}
|
|
90
91
|
this.lastAttemptAt = now;
|
|
92
|
+
let url;
|
|
93
|
+
if (this.deps.url !== undefined) {
|
|
94
|
+
url = this.deps.url;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
try {
|
|
98
|
+
url = await this.deps.resolveUrl();
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
this.lastOutcome = 'failed';
|
|
102
|
+
this.lastError = error instanceof Error ? error.message : String(error);
|
|
103
|
+
return this.cached;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
91
106
|
try {
|
|
92
107
|
const response = await (this.deps.fetchImpl ?? fetch)(url, {
|
|
93
108
|
headers: { accept: 'application/json' },
|
|
@@ -99,13 +114,15 @@ class JwksCache {
|
|
|
99
114
|
throw new Error('JWKS is malformed');
|
|
100
115
|
this.cached = body;
|
|
101
116
|
this.fetchedAt = now;
|
|
117
|
+
this.lastError = null;
|
|
102
118
|
this.lastOutcome = kidMiss ? 'refetched' : 'fresh';
|
|
103
119
|
return this.cached;
|
|
104
120
|
}
|
|
105
|
-
catch {
|
|
121
|
+
catch (error) {
|
|
106
122
|
// Keep serving what we have. A JWKS outage should degrade to "new keys
|
|
107
123
|
// do not work yet", not "nobody can authenticate".
|
|
108
124
|
this.lastOutcome = 'failed';
|
|
125
|
+
this.lastError = `JWKS fetch from ${url} failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
109
126
|
return this.cached;
|
|
110
127
|
}
|
|
111
128
|
}
|
package/dist/jwks-cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jwks-cache.js","sourceRoot":"","sources":["../src/jwks-cache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;
|
|
1
|
+
{"version":3,"file":"jwks-cache.js","sourceRoot":"","sources":["../src/jwks-cache.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAwJH,0BAWC;AAjKD,wEAAwE;AAC3D,QAAA,mBAAmB,GAAG,MAAM,CAAC;AAE1C,+EAA+E;AAClE,QAAA,cAAc,GAAG,SAAS,CAAC;AA8BxC,MAAa,SAAS;IASS;IARrB,MAAM,GAAgB,IAAI,CAAC;IAC3B,SAAS,GAAG,CAAC,CAAC;IACd,aAAa,GAAG,CAAC,CAAC;IAC1B,kEAAkE;IAClE,WAAW,GAAiB,OAAO,CAAC;IACpC,yFAAyF;IACzF,SAAS,GAAkB,IAAI,CAAC;IAEhC,YAA6B,IAAmB;QAAnB,SAAI,GAAJ,IAAI,CAAe;IAAG,CAAC;IAEpD,IAAY,GAAG;QACb,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACvC,CAAC;IAEO,GAAG,CAAC,GAAuB;QACjC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC/B,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,GAAG,CAAC,GAAY;QACpB;;;;;WAKG;QACH,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC;YAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QAC9B,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACtE,oEAAoE;YACpE,uDAAuD;YACvD,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,sBAAc,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,2BAAmB,CAAC;QAEpE,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC;QAC5D,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEvD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC;YAC5B,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAED;;;;WAIG;QACH,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,GAAG,GAAG,IAAI,CAAC,aAAa,GAAG,QAAQ,EAAE,CAAC;YAC/D,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;YAC/B,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;QAEzB,IAAI,GAAW,CAAC;QAChB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAChC,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC;gBACH,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,UAAW,EAAE,CAAC;YACtC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC;gBAC5B,IAAI,CAAC,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACxE,OAAO,IAAI,CAAC,MAAM,CAAC;YACrB,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC,GAAG,EAAE;gBACzD,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;aACxC,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YAE5E,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAS,CAAC;YAC7C,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAE7E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC;YACrB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC;YACnD,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,uEAAuE;YACvE,mDAAmD;YACnD,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC;YAC5B,IAAI,CAAC,SAAS,GAAG,mBAAmB,GAAG,YAAY,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5G,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;IACH,CAAC;IAED,wEAAwE;IACxE,QAAQ;QACN,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IAC5E,CAAC;CACF;AAjHD,8BAiHC;AAED,mEAAmE;AACnE,SAAgB,OAAO,CAAC,GAAW;IACjC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CACjE,CAAC;QACtB,OAAO,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
package/dist/verify.d.ts
CHANGED
|
@@ -98,14 +98,30 @@ export interface AuthorizedSession {
|
|
|
98
98
|
export type VerifyResult = AuthorizedSession | {
|
|
99
99
|
ok: false;
|
|
100
100
|
reason: 'malformed' | 'invalid' | 'no_keys' | 'unauthorized_party';
|
|
101
|
+
/**
|
|
102
|
+
* Set with `no_keys` when the key set could not be obtained — e.g. OIDC
|
|
103
|
+
* discovery failed — saying why. A configuration diagnostic, never a
|
|
104
|
+
* statement about the token.
|
|
105
|
+
*/
|
|
106
|
+
detail?: string;
|
|
101
107
|
};
|
|
102
108
|
export interface AtlasBackendOptions {
|
|
103
109
|
/**
|
|
104
|
-
* The instance's JWKS URL.
|
|
105
|
-
*
|
|
106
|
-
* `jwks`, verification is fully
|
|
110
|
+
* The instance's JWKS URL. Optional: when neither `jwksUrl` nor `jwks` is
|
|
111
|
+
* given, the URL is discovered from `${issuer}/.well-known/openid-configuration`
|
|
112
|
+
* (cached like the JWKS itself). With a static `jwks`, verification is fully
|
|
113
|
+
* offline. `jwksUrl` and `jwks` are mutually exclusive.
|
|
107
114
|
*/
|
|
108
115
|
jwksUrl?: string;
|
|
116
|
+
/**
|
|
117
|
+
* Only for discovery on an instance WITHOUT its own frontend API domain (the
|
|
118
|
+
* shared host): its tokens carry the shared issuer, so discovery must use the
|
|
119
|
+
* per-instance document. Pass the instance id (`ins_…`), or `publishableKey`.
|
|
120
|
+
* Ignored when `jwksUrl` or `jwks` is set.
|
|
121
|
+
*/
|
|
122
|
+
instanceId?: string;
|
|
123
|
+
/** Alternative to `instanceId`: the instance id is read from the publishable key. */
|
|
124
|
+
publishableKey?: string;
|
|
109
125
|
/**
|
|
110
126
|
* A static JSON Web Key Set to verify against, INSTEAD of fetching from a URL.
|
|
111
127
|
* When set, verification makes NO network call — the hermetic path a
|
package/dist/verify.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.protect = protect;
|
|
|
8
8
|
const jose_1 = require("jose");
|
|
9
9
|
const authz_1 = require("@atlasauth/authz");
|
|
10
10
|
const jwks_cache_1 = require("./jwks-cache");
|
|
11
|
+
const discovery_1 = require("./discovery");
|
|
11
12
|
// Re-export the shared authorization primitive so a backend customer imports
|
|
12
13
|
// `has`, `protect`, `ProtectCondition`, etc. from `@atlasauth/backend` directly —
|
|
13
14
|
// the same contract `@atlasauth/react` and `@atlasauth/nextjs` evaluate.
|
|
@@ -65,12 +66,30 @@ class AtlasBackend {
|
|
|
65
66
|
// failing loudly on rather than silently accepting or rejecting every token.
|
|
66
67
|
const hasUrl = typeof options.jwksUrl === 'string' && options.jwksUrl.length > 0;
|
|
67
68
|
const hasStatic = options.jwks !== undefined;
|
|
68
|
-
if (hasUrl
|
|
69
|
-
throw new Error('AtlasBackend
|
|
69
|
+
if (hasUrl && hasStatic) {
|
|
70
|
+
throw new Error('AtlasBackend takes one key source: `jwksUrl` (fetch from the instance) OR `jwks` (a static key set for offline verification), not both. Omit both to discover the JWKS URL from the issuer.');
|
|
71
|
+
}
|
|
72
|
+
if (typeof options.issuer !== 'string' || !options.issuer) {
|
|
73
|
+
throw new Error('AtlasBackend needs `issuer` (your instance\'s frontend API origin, the `iss` of its tokens).');
|
|
74
|
+
}
|
|
75
|
+
let discovery;
|
|
76
|
+
if (!hasUrl && !hasStatic) {
|
|
77
|
+
const instanceId = options.instanceId ??
|
|
78
|
+
(options.publishableKey ? (0, discovery_1.instanceIdFromPublishableKey)(options.publishableKey) : undefined);
|
|
79
|
+
if (options.publishableKey && !options.instanceId && !instanceId) {
|
|
80
|
+
throw new Error('AtlasBackend: `publishableKey` does not carry an instance id; pass `instanceId` or `jwksUrl` instead.');
|
|
81
|
+
}
|
|
82
|
+
discovery = new discovery_1.JwksDiscovery({
|
|
83
|
+
issuer: options.issuer,
|
|
84
|
+
instanceId,
|
|
85
|
+
fetchImpl: options.fetchImpl,
|
|
86
|
+
now: options.now,
|
|
87
|
+
});
|
|
70
88
|
}
|
|
71
89
|
this.jwks = new jwks_cache_1.JwksCache({
|
|
72
|
-
url: options.jwksUrl,
|
|
90
|
+
url: hasUrl ? options.jwksUrl : undefined,
|
|
73
91
|
staticJwks: options.jwks,
|
|
92
|
+
resolveUrl: discovery ? () => discovery.jwksUri() : undefined,
|
|
74
93
|
fetchImpl: options.fetchImpl,
|
|
75
94
|
now: options.now,
|
|
76
95
|
});
|
|
@@ -83,8 +102,11 @@ class AtlasBackend {
|
|
|
83
102
|
if (!token || token.split('.').length !== 3)
|
|
84
103
|
return { ok: false, reason: 'malformed' };
|
|
85
104
|
const keys = await this.jwks.get((0, jwks_cache_1.readKid)(token));
|
|
86
|
-
if (!keys || keys.keys.length === 0)
|
|
87
|
-
return
|
|
105
|
+
if (!keys || keys.keys.length === 0) {
|
|
106
|
+
return this.jwks.lastError
|
|
107
|
+
? { ok: false, reason: 'no_keys', detail: this.jwks.lastError }
|
|
108
|
+
: { ok: false, reason: 'no_keys' };
|
|
109
|
+
}
|
|
88
110
|
let claims;
|
|
89
111
|
try {
|
|
90
112
|
const { payload } = await (0, jose_1.jwtVerify)(token, (0, jose_1.createLocalJWKSet)(keys), {
|
package/dist/verify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../src/verify.ts"],"names":[],"mappings":"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"}
|