@udibo/oauth2 0.6.0 → 0.8.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/esm/_dnt.polyfills.d.ts +14 -0
- package/esm/_dnt.polyfills.js +11 -0
- package/esm/adapters/hono/bff/bff.d.ts +66 -3
- package/esm/adapters/hono/bff/bff.js +95 -12
- package/esm/client/_http.d.ts +5 -2
- package/esm/client/_http.js +6 -3
- package/esm/client/check.js +11 -32
- package/esm/client/direct-client.d.ts +41 -2
- package/esm/client/direct-client.js +41 -2
- package/esm/client/storage.d.ts +8 -1
- package/esm/server/authorization-server.d.ts +27 -2
- package/esm/server/authorization-server.js +29 -5
- package/esm/testing/contract/auth-request-storage.d.ts +26 -0
- package/esm/testing/contract/auth-request-storage.js +44 -7
- package/esm/testing/contract/mod.d.ts +1 -1
- package/esm/testing/contract/tenant.d.ts +49 -9
- package/esm/testing/contract/tenant.js +631 -5
- package/esm/testing/mod.d.ts +6 -5
- package/esm/testing/mod.js +5 -4
- package/esm/testing/tenant.d.ts +88 -16
- package/esm/testing/tenant.js +971 -57
- package/esm/utils/_body.d.ts +29 -0
- package/esm/utils/_body.js +66 -0
- package/package.json +1 -1
package/esm/testing/mod.d.ts
CHANGED
|
@@ -27,10 +27,11 @@
|
|
|
27
27
|
* prototypes — never for production.
|
|
28
28
|
*
|
|
29
29
|
* - **A fake Udibo Identity tenant.** {@link createFakeTenant} answers a tenant's
|
|
30
|
-
* protocol surface
|
|
31
|
-
* claims a real tenant issues —
|
|
32
|
-
* sign-in, and resource grants — so
|
|
33
|
-
* its own routes without
|
|
30
|
+
* protocol surface, its `/api/check` questions, and its organization and
|
|
31
|
+
* account APIs over `fetch`, with the claims a real tenant issues —
|
|
32
|
+
* permissions, the organization picked at sign-in, and resource grants — so
|
|
33
|
+
* an app built on a Udibo Identity tenant can test its own routes without
|
|
34
|
+
* running the identity service.
|
|
34
35
|
*
|
|
35
36
|
* Nothing in this module is an OAuth2 primitive — only testing support.
|
|
36
37
|
* Production code should never import from here.
|
|
@@ -40,4 +41,4 @@
|
|
|
40
41
|
import "../_dnt.polyfills.js";
|
|
41
42
|
export { MemoryAuthorizationCodeService, type MemoryAuthorizationCodeServiceOptions, MemoryClientService, MemoryDeviceAuthorizationService, type MemoryDeviceAuthorizationServiceOptions, MemoryTokenService, type MemoryTokenServiceOptions, MemoryUserService, type MemoryUserServiceOptions, type MemoryUserShape, } from "./services.js";
|
|
42
43
|
export { createMemoryAuthorizationServer, type CreateMemoryAuthorizationServerOptions, type MemoryAuthorizationServerClientSeed, type MemoryAuthorizationServerGrants, type MemoryAuthorizationServerHarness, type MemoryAuthorizationServerUserSeed, } from "./server.js";
|
|
43
|
-
export { createFakeTenant, type FakeTenant, type FakeTenantClient, type FakeTenantGrant, type FakeTenantMembership, type FakeTenantOptions, type FakeTenantOrganization, type FakeTenantSignIn, type FakeTenantSubject, type FakeTenantTokenRequest, type FakeTenantUser, } from "./tenant.js";
|
|
44
|
+
export { createFakeTenant, type FakeTenant, type FakeTenantClient, type FakeTenantGrant, type FakeTenantLinkedAccount, type FakeTenantMembership, type FakeTenantOptions, type FakeTenantOrganization, type FakeTenantOrganizationRole, type FakeTenantSignIn, type FakeTenantSubject, type FakeTenantTokenRequest, type FakeTenantUser, } from "./tenant.js";
|
package/esm/testing/mod.js
CHANGED
|
@@ -27,10 +27,11 @@
|
|
|
27
27
|
* prototypes — never for production.
|
|
28
28
|
*
|
|
29
29
|
* - **A fake Udibo Identity tenant.** {@link createFakeTenant} answers a tenant's
|
|
30
|
-
* protocol surface
|
|
31
|
-
* claims a real tenant issues —
|
|
32
|
-
* sign-in, and resource grants — so
|
|
33
|
-
* its own routes without
|
|
30
|
+
* protocol surface, its `/api/check` questions, and its organization and
|
|
31
|
+
* account APIs over `fetch`, with the claims a real tenant issues —
|
|
32
|
+
* permissions, the organization picked at sign-in, and resource grants — so
|
|
33
|
+
* an app built on a Udibo Identity tenant can test its own routes without
|
|
34
|
+
* running the identity service.
|
|
34
35
|
*
|
|
35
36
|
* Nothing in this module is an OAuth2 primitive — only testing support.
|
|
36
37
|
* Production code should never import from here.
|
package/esm/testing/tenant.d.ts
CHANGED
|
@@ -5,14 +5,35 @@ export interface FakeTenantUser {
|
|
|
5
5
|
id: string;
|
|
6
6
|
/** The `username` introspection reports. */
|
|
7
7
|
username: string;
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* The `name` claim UserInfo reports, and the name the organization API's
|
|
10
|
+
* member listing gives the person. The listing falls back to `username`.
|
|
11
|
+
*/
|
|
9
12
|
name?: string;
|
|
10
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The `email` claim UserInfo reports. An invitation to this address offers
|
|
15
|
+
* the person a pending membership rather than an invitation.
|
|
16
|
+
*/
|
|
11
17
|
email?: string;
|
|
12
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The `email_verified` claim UserInfo reports. Defaults to `true`. While it
|
|
20
|
+
* is `false`, invitations to the address stay hidden from the person's
|
|
21
|
+
* offers and cannot be accepted.
|
|
22
|
+
*/
|
|
13
23
|
emailVerified?: boolean;
|
|
14
24
|
/** Permissions held tenant-wide, in every organization and on every resource. */
|
|
15
25
|
permissions?: string[];
|
|
26
|
+
/**
|
|
27
|
+
* The person's own metadata bucket, as `GET /api/account` first reports
|
|
28
|
+
* it. Defaults to `{}`.
|
|
29
|
+
*/
|
|
30
|
+
userMetadata?: Record<string, unknown>;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the person has a password. Defaults to `true`. Without one, a
|
|
33
|
+
* linked account is their only way in, and the account API refuses to
|
|
34
|
+
* disconnect the last of them.
|
|
35
|
+
*/
|
|
36
|
+
hasPassword?: boolean;
|
|
16
37
|
}
|
|
17
38
|
/** An OAuth2 application registered in a {@linkcode FakeTenant}. */
|
|
18
39
|
export interface FakeTenantClient extends ClientInterface {
|
|
@@ -25,6 +46,14 @@ export interface FakeTenantClient extends ClientInterface {
|
|
|
25
46
|
accessTokenFormat?: "opaque" | "jwt";
|
|
26
47
|
/** A JWT access token's `aud`. Defaults to the client id. */
|
|
27
48
|
audience?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Whose application this is. Defaults to `"first-party"`: its credentials
|
|
51
|
+
* belong to the login session they were issued from, so a later sign-in in
|
|
52
|
+
* that browser revokes them, revoking one ends the session, and ending the
|
|
53
|
+
* session revokes them. A `"third-party"` application's credentials only
|
|
54
|
+
* name that session as the one they came from, and outlive it.
|
|
55
|
+
*/
|
|
56
|
+
type?: "first-party" | "third-party";
|
|
28
57
|
}
|
|
29
58
|
/** An organization in a {@linkcode FakeTenant}. */
|
|
30
59
|
export interface FakeTenantOrganization {
|
|
@@ -38,8 +67,12 @@ export interface FakeTenantOrganization {
|
|
|
38
67
|
/** A person's place in one organization. */
|
|
39
68
|
export interface FakeTenantMembership {
|
|
40
69
|
/**
|
|
41
|
-
* The membership
|
|
42
|
-
* them
|
|
70
|
+
* The roles the membership holds, as `org_roles`, `/api/memberships` and the
|
|
71
|
+
* organization API report them. `owner`, `admin` and `member` are the
|
|
72
|
+
* built-in tiers. `owner` and `admin` may manage the organization through
|
|
73
|
+
* its API, and only `owner` may delete it or deal in the `owner` tier.
|
|
74
|
+
* Defaults to `["member"]`, because a membership on a real tenant always
|
|
75
|
+
* holds a role. An empty list is also read as `["member"]`.
|
|
43
76
|
*/
|
|
44
77
|
roles?: string[];
|
|
45
78
|
/** Permissions held inside this organization only. */
|
|
@@ -65,6 +98,22 @@ export interface FakeTenantGrant {
|
|
|
65
98
|
/** What the subject may do on that one resource. */
|
|
66
99
|
permissions: string[];
|
|
67
100
|
}
|
|
101
|
+
/** An organization role your tenant defines beside the built-in tiers. */
|
|
102
|
+
export interface FakeTenantOrganizationRole {
|
|
103
|
+
/** The role a membership, an invitation or `org_roles` names. */
|
|
104
|
+
slug: string;
|
|
105
|
+
/** How the role is named to people. Defaults to the slug. */
|
|
106
|
+
name?: string;
|
|
107
|
+
}
|
|
108
|
+
/** An external account a person can sign in with. */
|
|
109
|
+
export interface FakeTenantLinkedAccount {
|
|
110
|
+
/** The provider's key, such as `google` or `github`. */
|
|
111
|
+
provider: string;
|
|
112
|
+
/** How the provider is named to the person. Defaults to the key. */
|
|
113
|
+
displayName?: string;
|
|
114
|
+
/** The address the provider reported, if any. */
|
|
115
|
+
email?: string | null;
|
|
116
|
+
}
|
|
68
117
|
/** How the next sign-in resolves. */
|
|
69
118
|
export interface FakeTenantSignIn {
|
|
70
119
|
/**
|
|
@@ -77,6 +126,10 @@ export interface FakeTenantSignIn {
|
|
|
77
126
|
* `invalid_request` when the person is not a member.
|
|
78
127
|
*/
|
|
79
128
|
organizationId?: string;
|
|
129
|
+
/** The browser `GET /api/account/sessions` reports for this sign-in. */
|
|
130
|
+
userAgent?: string;
|
|
131
|
+
/** The address `GET /api/account/sessions` reports for this sign-in. */
|
|
132
|
+
ipAddress?: string;
|
|
80
133
|
}
|
|
81
134
|
/** What {@linkcode FakeTenant.issueAccessToken} mints a token for. */
|
|
82
135
|
export interface FakeTenantTokenRequest {
|
|
@@ -105,9 +158,10 @@ export interface FakeTenantOptions {
|
|
|
105
158
|
* A stand-in for a Udibo Identity tenant, for testing an app that signs in against one
|
|
106
159
|
* without running the identity service. It answers the tenant's protocol
|
|
107
160
|
* surface — discovery, authorize, token, introspection, UserInfo, JWKS — the
|
|
108
|
-
* caller's own `GET /api/memberships`,
|
|
109
|
-
* `POST /api/check` and `POST /api/check/batch`,
|
|
110
|
-
*
|
|
161
|
+
* caller's own `GET /api/memberships`, the two authorization questions,
|
|
162
|
+
* `POST /api/check` and `POST /api/check/batch`, the organization API under
|
|
163
|
+
* `/api/organizations`, and the account API under `/api/account`, with the
|
|
164
|
+
* same shapes and refusals a real tenant uses.
|
|
111
165
|
*
|
|
112
166
|
* Nothing here is interactive: {@linkcode signInAs} decides who the next
|
|
113
167
|
* authorization request authenticates, and there is no consent step. Serve
|
|
@@ -125,30 +179,48 @@ export interface FakeTenant {
|
|
|
125
179
|
/** Adds an organization. Throws on a duplicate id. */
|
|
126
180
|
addOrganization(organization: FakeTenantOrganization): void;
|
|
127
181
|
/**
|
|
128
|
-
* Makes a person a member of an organization, replacing
|
|
129
|
-
*
|
|
182
|
+
* Makes a person a member of an organization, replacing earlier membership
|
|
183
|
+
* grants, including pending grants. Email-address invitations remain.
|
|
184
|
+
* Throws when the organization does not exist.
|
|
130
185
|
*/
|
|
131
186
|
addMember(organizationId: string, userId: string, membership?: FakeTenantMembership): void;
|
|
132
187
|
/**
|
|
133
|
-
* Ends a membership
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
188
|
+
* Ends a membership and removes the person's pending membership grants.
|
|
189
|
+
* Email-address invitations remain. From then on introspection and
|
|
190
|
+
* `/api/check` stop answering for that
|
|
191
|
+
* organization on credentials issued in it, and UserInfo drops its `org_*`
|
|
192
|
+
* claims; a JWT access token or id_token already minted keeps its claims
|
|
193
|
+
* until it expires.
|
|
137
194
|
*/
|
|
138
195
|
removeMember(organizationId: string, userId: string): void;
|
|
196
|
+
/**
|
|
197
|
+
* Defines an organization role beside the built-in tiers, so invitations
|
|
198
|
+
* may offer it and `member-roles` lists it. Throws on a built-in slug.
|
|
199
|
+
*/
|
|
200
|
+
defineOrganizationRole(role: FakeTenantOrganizationRole): void;
|
|
139
201
|
/** Registers a resource type, so `/api/check` accepts it. */
|
|
140
202
|
registerResourceType(type: string): void;
|
|
141
203
|
/** Adds a resource grant. */
|
|
142
204
|
grant(grant: FakeTenantGrant): void;
|
|
205
|
+
/**
|
|
206
|
+
* Links an external account to a person, as the account API lists it, and
|
|
207
|
+
* returns its id. Throws when the person does not exist.
|
|
208
|
+
*/
|
|
209
|
+
linkAccount(userId: string, account: FakeTenantLinkedAccount): string;
|
|
143
210
|
/**
|
|
144
211
|
* Chooses who the next authorization requests authenticate as, until
|
|
145
212
|
* called again. With nobody chosen, authorize answers `access_denied`.
|
|
213
|
+
*
|
|
214
|
+
* Each call is a new browser: the first authorization after it starts a
|
|
215
|
+
* login session, which the account API lists, and later ones reuse it until
|
|
216
|
+
* that session is ended. When a first-party application signs in again in
|
|
217
|
+
* that browser, the credentials the session issued before are revoked.
|
|
146
218
|
*/
|
|
147
219
|
signInAs(userId: string | null, signIn?: FakeTenantSignIn): void;
|
|
148
220
|
/**
|
|
149
221
|
* Mints an access token without the browser flow, for testing an API
|
|
150
|
-
* directly. JWT or opaque as the client is registered.
|
|
151
|
-
* client or user does not exist.
|
|
222
|
+
* directly. JWT or opaque as the client is registered. It belongs to no
|
|
223
|
+
* login session. Throws when the client or user does not exist.
|
|
152
224
|
*/
|
|
153
225
|
issueAccessToken(request: FakeTenantTokenRequest): Promise<string>;
|
|
154
226
|
}
|