@hyper.authio/testing 0.9.0 → 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 +5 -1
- package/dist/index.cjs +34 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +35 -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. */
|
|
@@ -212,6 +222,12 @@ interface FakeAuthioTokenOptions {
|
|
|
212
222
|
algorithm?: "RSA-OAEP" | "RSA-OAEP-256";
|
|
213
223
|
encryptionMethod?: string;
|
|
214
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;
|
|
215
231
|
}
|
|
216
232
|
type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "discovery" | "authorize" | "logout";
|
|
217
233
|
/**
|
|
@@ -220,7 +236,8 @@ type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "dis
|
|
|
220
236
|
* `iss`), token (client credentials, authorization code with ID tokens, refresh, token exchange, password, device code,
|
|
221
237
|
* personal access token) with the client's exact authentication method, introspection, revocation, UserInfo, device
|
|
222
238
|
* authorization, end session, back-channel and front-channel logout delivery, tokens signed RS256 or HS* with the
|
|
223
|
-
* 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.
|
|
224
241
|
*/
|
|
225
242
|
declare class FakeAuthio {
|
|
226
243
|
/** Every request received, in order. */
|
|
@@ -418,4 +435,4 @@ declare function createWebhookDelivery(type: string, data: unknown, secret: stri
|
|
|
418
435
|
sendEventIdHeader?: boolean;
|
|
419
436
|
}): Promise<FakeWebhookDelivery>;
|
|
420
437
|
|
|
421
|
-
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. */
|
|
@@ -212,6 +222,12 @@ interface FakeAuthioTokenOptions {
|
|
|
212
222
|
algorithm?: "RSA-OAEP" | "RSA-OAEP-256";
|
|
213
223
|
encryptionMethod?: string;
|
|
214
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;
|
|
215
231
|
}
|
|
216
232
|
type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "discovery" | "authorize" | "logout";
|
|
217
233
|
/**
|
|
@@ -220,7 +236,8 @@ type Endpoint = "token" | "introspect" | "revoke" | "userinfo" | "device" | "dis
|
|
|
220
236
|
* `iss`), token (client credentials, authorization code with ID tokens, refresh, token exchange, password, device code,
|
|
221
237
|
* personal access token) with the client's exact authentication method, introspection, revocation, UserInfo, device
|
|
222
238
|
* authorization, end session, back-channel and front-channel logout delivery, tokens signed RS256 or HS* with the
|
|
223
|
-
* 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.
|
|
224
241
|
*/
|
|
225
242
|
declare class FakeAuthio {
|
|
226
243
|
/** Every request received, in order. */
|
|
@@ -418,4 +435,4 @@ declare function createWebhookDelivery(type: string, data: unknown, secret: stri
|
|
|
418
435
|
sendEventIdHeader?: boolean;
|
|
419
436
|
}): Promise<FakeWebhookDelivery>;
|
|
420
437
|
|
|
421
|
-
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 = [];
|
|
@@ -141,9 +164,17 @@ var FakeAuthio = class _FakeAuthio {
|
|
|
141
164
|
...options.claims
|
|
142
165
|
};
|
|
143
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);
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
|
|
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 });
|
|
147
178
|
return token;
|
|
148
179
|
}
|
|
149
180
|
/**
|