@hyper.authio/testing 0.8.1 → 0.10.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/README.md +6 -1
- package/dist/index.cjs +35 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +36 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -28,6 +28,14 @@ type FakeAuthioTokenEndpointAuthMethod = "client_secret_basic" | "client_secret_
|
|
|
28
28
|
* The algorithm Authio signs every token of a client with: the realm's RSA key, or the client secret (HS*).
|
|
29
29
|
*/
|
|
30
30
|
type FakeAuthioSigningAlgorithm = "RS256" | "HS256" | "HS384" | "HS512";
|
|
31
|
+
/**
|
|
32
|
+
* The form a client's access tokens are handed out in, as Authio's access token format setting: `Jwt`, the
|
|
33
|
+
* self-contained JWT; `Reference`, an opaque handle of 43 characters that only introspection resolves; `Lightweight`, a
|
|
34
|
+
* JWT that carries only the identity and session claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`, `typ`,
|
|
35
|
+
* `client_id`, `azp`, `scope`, `sid`, `auth_time`, `acr`, `amr`, `idp`, `act`, `delegation_id`, `session_client`,
|
|
36
|
+
* `org_id`, `org_alias`). Introspection answers with every claim of the full token, whatever the form.
|
|
37
|
+
*/
|
|
38
|
+
type FakeAuthioAccessTokenFormat = "Jwt" | "Reference" | "Lightweight";
|
|
31
39
|
/**
|
|
32
40
|
* A client registered in the fake, configured as a client is in Authio's console. What the client requires is
|
|
33
41
|
* enforced as Authio enforces it: a request that does not match is refused with an error naming the setting, and
|
|
@@ -62,6 +70,8 @@ interface FakeAuthioClient {
|
|
|
62
70
|
signingAlgorithm?: FakeAuthioSigningAlgorithm;
|
|
63
71
|
/** The algorithm the client's access tokens are signed with, Authio's second setting. Defaults to `RS256`. */
|
|
64
72
|
accessTokenSigningAlgorithm?: FakeAuthioSigningAlgorithm;
|
|
73
|
+
/** The form the client's access tokens are handed out in. Defaults to `Jwt`. */
|
|
74
|
+
accessTokenFormat?: FakeAuthioAccessTokenFormat;
|
|
65
75
|
/** Issues a new ID token with every refresh. Defaults to `false`. */
|
|
66
76
|
issueIdTokenOnRefresh?: boolean;
|
|
67
77
|
/** Scopes granted when a request names none. */
|
|
@@ -198,6 +208,8 @@ interface FakeAuthioTokenOptions {
|
|
|
198
208
|
expiresIn?: number;
|
|
199
209
|
/** The `typ` claim. Defaults to `Bearer`. */
|
|
200
210
|
type?: string;
|
|
211
|
+
/** The header `typ`. Defaults to `at+jwt` (RFC 9068 §2.1); `null` leaves it out. */
|
|
212
|
+
headerType?: string | null;
|
|
201
213
|
/** Claims added to the payload. */
|
|
202
214
|
claims?: Record<string, unknown>;
|
|
203
215
|
/** Signs with another issuer. */
|
|
@@ -210,6 +222,12 @@ interface FakeAuthioTokenOptions {
|
|
|
210
222
|
algorithm?: "RSA-OAEP" | "RSA-OAEP-256";
|
|
211
223
|
encryptionMethod?: string;
|
|
212
224
|
};
|
|
225
|
+
/**
|
|
226
|
+
* The form of the token: `Reference` mints an opaque handle (never encrypted) and `Lightweight` a JWT with only the
|
|
227
|
+
* identity and session claims; introspection answers with every claim either way. Defaults to the client's
|
|
228
|
+
* `accessTokenFormat`, else `Jwt`.
|
|
229
|
+
*/
|
|
230
|
+
format?: FakeAuthioAccessTokenFormat;
|
|
213
231
|
}
|
|
214
232
|
type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "discovery" | "authorize" | "logout";
|
|
215
233
|
/**
|
|
@@ -218,7 +236,8 @@ type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "dis
|
|
|
218
236
|
* `iss`), token (client credentials, authorization code with ID tokens, refresh, token exchange, password, device code,
|
|
219
237
|
* personal access token) with the client's exact authentication method, introspection, revocation, UserInfo, device
|
|
220
238
|
* authorization, end session, back-channel and front-channel logout delivery, tokens signed RS256 or HS* with the
|
|
221
|
-
* client secret,
|
|
239
|
+
* client secret, access tokens as a JWT, an opaque reference or a lightweight JWT (`accessTokenFormat`), and JWE
|
|
240
|
+
* (RSA-OAEP, RSA-OAEP-256) for clients that registered an encryption key.
|
|
222
241
|
*/
|
|
223
242
|
declare class FakeAuthio {
|
|
224
243
|
/** Every request received, in order. */
|
|
@@ -416,4 +435,4 @@ declare function createWebhookDelivery(type: string, data: unknown, secret: stri
|
|
|
416
435
|
sendEventIdHeader?: boolean;
|
|
417
436
|
}): Promise<FakeWebhookDelivery>;
|
|
418
437
|
|
|
419
|
-
export { FakeAuthio, type FakeAuthioAuthorizationOutcome, type FakeAuthioBackchannelDelivery, type FakeAuthioClient, type FakeAuthioClientEncryption, type FakeAuthioDeviceOutcome, type FakeAuthioError, type FakeAuthioFrontchannelDelivery, type FakeAuthioOptions, type FakeAuthioPersonalAccessToken, type FakeAuthioRecordedRequest, type FakeAuthioSigningAlgorithm, type FakeAuthioTokenEndpointAuthMethod, type FakeAuthioTokenOptions, type FakeAuthioUser, type FakeWebhookDelivery, ManualClock, createWebhookDelivery };
|
|
438
|
+
export { FakeAuthio, type FakeAuthioAccessTokenFormat, type FakeAuthioAuthorizationOutcome, type FakeAuthioBackchannelDelivery, type FakeAuthioClient, type FakeAuthioClientEncryption, type FakeAuthioDeviceOutcome, type FakeAuthioError, type FakeAuthioFrontchannelDelivery, type FakeAuthioOptions, type FakeAuthioPersonalAccessToken, type FakeAuthioRecordedRequest, type FakeAuthioSigningAlgorithm, type FakeAuthioTokenEndpointAuthMethod, type FakeAuthioTokenOptions, type FakeAuthioUser, type FakeWebhookDelivery, ManualClock, createWebhookDelivery };
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,14 @@ type FakeAuthioTokenEndpointAuthMethod = "client_secret_basic" | "client_secret_
|
|
|
28
28
|
* The algorithm Authio signs every token of a client with: the realm's RSA key, or the client secret (HS*).
|
|
29
29
|
*/
|
|
30
30
|
type FakeAuthioSigningAlgorithm = "RS256" | "HS256" | "HS384" | "HS512";
|
|
31
|
+
/**
|
|
32
|
+
* The form a client's access tokens are handed out in, as Authio's access token format setting: `Jwt`, the
|
|
33
|
+
* self-contained JWT; `Reference`, an opaque handle of 43 characters that only introspection resolves; `Lightweight`, a
|
|
34
|
+
* JWT that carries only the identity and session claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`, `typ`,
|
|
35
|
+
* `client_id`, `azp`, `scope`, `sid`, `auth_time`, `acr`, `amr`, `idp`, `act`, `delegation_id`, `session_client`,
|
|
36
|
+
* `org_id`, `org_alias`). Introspection answers with every claim of the full token, whatever the form.
|
|
37
|
+
*/
|
|
38
|
+
type FakeAuthioAccessTokenFormat = "Jwt" | "Reference" | "Lightweight";
|
|
31
39
|
/**
|
|
32
40
|
* A client registered in the fake, configured as a client is in Authio's console. What the client requires is
|
|
33
41
|
* enforced as Authio enforces it: a request that does not match is refused with an error naming the setting, and
|
|
@@ -62,6 +70,8 @@ interface FakeAuthioClient {
|
|
|
62
70
|
signingAlgorithm?: FakeAuthioSigningAlgorithm;
|
|
63
71
|
/** The algorithm the client's access tokens are signed with, Authio's second setting. Defaults to `RS256`. */
|
|
64
72
|
accessTokenSigningAlgorithm?: FakeAuthioSigningAlgorithm;
|
|
73
|
+
/** The form the client's access tokens are handed out in. Defaults to `Jwt`. */
|
|
74
|
+
accessTokenFormat?: FakeAuthioAccessTokenFormat;
|
|
65
75
|
/** Issues a new ID token with every refresh. Defaults to `false`. */
|
|
66
76
|
issueIdTokenOnRefresh?: boolean;
|
|
67
77
|
/** Scopes granted when a request names none. */
|
|
@@ -198,6 +208,8 @@ interface FakeAuthioTokenOptions {
|
|
|
198
208
|
expiresIn?: number;
|
|
199
209
|
/** The `typ` claim. Defaults to `Bearer`. */
|
|
200
210
|
type?: string;
|
|
211
|
+
/** The header `typ`. Defaults to `at+jwt` (RFC 9068 §2.1); `null` leaves it out. */
|
|
212
|
+
headerType?: string | null;
|
|
201
213
|
/** Claims added to the payload. */
|
|
202
214
|
claims?: Record<string, unknown>;
|
|
203
215
|
/** Signs with another issuer. */
|
|
@@ -210,6 +222,12 @@ interface FakeAuthioTokenOptions {
|
|
|
210
222
|
algorithm?: "RSA-OAEP" | "RSA-OAEP-256";
|
|
211
223
|
encryptionMethod?: string;
|
|
212
224
|
};
|
|
225
|
+
/**
|
|
226
|
+
* The form of the token: `Reference` mints an opaque handle (never encrypted) and `Lightweight` a JWT with only the
|
|
227
|
+
* identity and session claims; introspection answers with every claim either way. Defaults to the client's
|
|
228
|
+
* `accessTokenFormat`, else `Jwt`.
|
|
229
|
+
*/
|
|
230
|
+
format?: FakeAuthioAccessTokenFormat;
|
|
213
231
|
}
|
|
214
232
|
type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "discovery" | "authorize" | "logout";
|
|
215
233
|
/**
|
|
@@ -218,7 +236,8 @@ type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "dis
|
|
|
218
236
|
* `iss`), token (client credentials, authorization code with ID tokens, refresh, token exchange, password, device code,
|
|
219
237
|
* personal access token) with the client's exact authentication method, introspection, revocation, UserInfo, device
|
|
220
238
|
* authorization, end session, back-channel and front-channel logout delivery, tokens signed RS256 or HS* with the
|
|
221
|
-
* client secret,
|
|
239
|
+
* client secret, access tokens as a JWT, an opaque reference or a lightweight JWT (`accessTokenFormat`), and JWE
|
|
240
|
+
* (RSA-OAEP, RSA-OAEP-256) for clients that registered an encryption key.
|
|
222
241
|
*/
|
|
223
242
|
declare class FakeAuthio {
|
|
224
243
|
/** Every request received, in order. */
|
|
@@ -416,4 +435,4 @@ declare function createWebhookDelivery(type: string, data: unknown, secret: stri
|
|
|
416
435
|
sendEventIdHeader?: boolean;
|
|
417
436
|
}): Promise<FakeWebhookDelivery>;
|
|
418
437
|
|
|
419
|
-
export { FakeAuthio, type FakeAuthioAuthorizationOutcome, type FakeAuthioBackchannelDelivery, type FakeAuthioClient, type FakeAuthioClientEncryption, type FakeAuthioDeviceOutcome, type FakeAuthioError, type FakeAuthioFrontchannelDelivery, type FakeAuthioOptions, type FakeAuthioPersonalAccessToken, type FakeAuthioRecordedRequest, type FakeAuthioSigningAlgorithm, type FakeAuthioTokenEndpointAuthMethod, type FakeAuthioTokenOptions, type FakeAuthioUser, type FakeWebhookDelivery, ManualClock, createWebhookDelivery };
|
|
438
|
+
export { FakeAuthio, type FakeAuthioAccessTokenFormat, type FakeAuthioAuthorizationOutcome, type FakeAuthioBackchannelDelivery, type FakeAuthioClient, type FakeAuthioClientEncryption, type FakeAuthioDeviceOutcome, type FakeAuthioError, type FakeAuthioFrontchannelDelivery, type FakeAuthioOptions, type FakeAuthioPersonalAccessToken, type FakeAuthioRecordedRequest, type FakeAuthioSigningAlgorithm, type FakeAuthioTokenEndpointAuthMethod, type FakeAuthioTokenOptions, type FakeAuthioUser, type FakeWebhookDelivery, ManualClock, createWebhookDelivery };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
import { createServer } from 'http';
|
|
2
|
-
import { randomUUID, createHash } from 'crypto';
|
|
2
|
+
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
3
3
|
import { SignJWT, decodeJwt, generateKeyPair, exportJWK, jwtVerify, importJWK, decodeProtectedHeader, CompactEncrypt } from 'jose';
|
|
4
4
|
import { AuthioWebhookHeaders, computeWebhookSignatureHeader } from '@hyper.authio/client';
|
|
5
5
|
|
|
6
6
|
// src/fake-authio.ts
|
|
7
|
+
var lightweightAccessTokenClaims = /* @__PURE__ */ new Set([
|
|
8
|
+
"iss",
|
|
9
|
+
"sub",
|
|
10
|
+
"aud",
|
|
11
|
+
"exp",
|
|
12
|
+
"nbf",
|
|
13
|
+
"iat",
|
|
14
|
+
"jti",
|
|
15
|
+
"typ",
|
|
16
|
+
"client_id",
|
|
17
|
+
"azp",
|
|
18
|
+
"scope",
|
|
19
|
+
"sid",
|
|
20
|
+
"auth_time",
|
|
21
|
+
"acr",
|
|
22
|
+
"amr",
|
|
23
|
+
"idp",
|
|
24
|
+
"act",
|
|
25
|
+
"delegation_id",
|
|
26
|
+
"session_client",
|
|
27
|
+
"org_id",
|
|
28
|
+
"org_alias"
|
|
29
|
+
]);
|
|
7
30
|
var FakeAuthio = class _FakeAuthio {
|
|
8
31
|
/** Every request received, in order. */
|
|
9
32
|
requests = [];
|
|
@@ -130,6 +153,7 @@ var FakeAuthio = class _FakeAuthio {
|
|
|
130
153
|
async issueAccessToken(options = {}) {
|
|
131
154
|
const now = this.nowSeconds();
|
|
132
155
|
const clientId = options.clientId ?? "fake-client";
|
|
156
|
+
const headerType = options.headerType === null ? void 0 : options.headerType ?? "at+jwt";
|
|
133
157
|
const jti = randomUUID();
|
|
134
158
|
const payload = {
|
|
135
159
|
typ: options.type ?? "Bearer",
|
|
@@ -140,9 +164,17 @@ var FakeAuthio = class _FakeAuthio {
|
|
|
140
164
|
...options.claims
|
|
141
165
|
};
|
|
142
166
|
const builder = new SignJWT(payload).setIssuer(options.issuer ?? this.issuer).setAudience(options.audience ?? clientId).setIssuedAt(now).setNotBefore(now).setExpirationTime(now + (options.expiresIn ?? this.lifetime)).setJti(jti);
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
|
|
167
|
+
const sign = (jwt) => options.untrusted ? jwt.setProtectedHeader({ alg: "RS256", kid: this.keyId, typ: headerType }).sign(this.untrustedKey) : this.sign(jwt, this.clients.get(clientId), headerType, this.clients.get(clientId)?.accessTokenSigningAlgorithm ?? "RS256");
|
|
168
|
+
const format = options.format ?? this.clients.get(clientId)?.accessTokenFormat ?? "Jwt";
|
|
169
|
+
const full = await sign(builder);
|
|
170
|
+
const claims = decodeJwt(full);
|
|
171
|
+
let token;
|
|
172
|
+
if (format === "Reference") token = randomBytes(32).toString("base64url");
|
|
173
|
+
else {
|
|
174
|
+
const signed = format === "Lightweight" ? await sign(new SignJWT(Object.fromEntries(Object.entries(claims).filter(([name]) => lightweightAccessTokenClaims.has(name))))) : full;
|
|
175
|
+
token = options.encryptTo ? await encryptTo(signed, options.encryptTo) : signed;
|
|
176
|
+
}
|
|
177
|
+
this.issued.set(token, { claims, clientId, revoked: false });
|
|
146
178
|
return token;
|
|
147
179
|
}
|
|
148
180
|
/**
|