huia-auth-core 1.0.0-alpha.5

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.
@@ -0,0 +1,15 @@
1
+ export declare function splitIntoChunks(value: string, limit: number): string[];
2
+ export declare function sealValue(password: string, value: unknown, ttlSeconds?: number): Promise<string>;
3
+ export declare function unsealValue<T>(password: string, sealed: string | undefined, ttlSeconds?: number): Promise<T | null>;
4
+ /**
5
+ * Normalizes the cookie name:
6
+ * If secure=true, preserves `__Host-` or `__Secure-` prefixes.
7
+ * If secure=false (e.g. dev over plain http), strips `__Host-` and `__Secure-` prefixes
8
+ * because browsers strictly reject prefixed cookies over insecure HTTP.
9
+ */
10
+ export declare function resolveCookieName(name: string, secure: boolean): string;
11
+ /**
12
+ * Reassembles a chunked cookie if present, or reads single cookie.
13
+ */
14
+ export declare function assembleChunks(getCookie: (name: string) => string | undefined, name: string, maxChunks?: number): string | null;
15
+ //# sourceMappingURL=cookie.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.d.ts","sourceRoot":"","sources":["../src/cookie.ts"],"names":[],"mappings":"AAMA,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAOtE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAKhG;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,UAAU,SAAS,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAWzH;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAGvE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAC/C,IAAI,EAAE,MAAM,EACZ,SAAS,SAAI,GACZ,MAAM,GAAG,IAAI,CAYf"}
package/dist/cookie.js ADDED
@@ -0,0 +1,60 @@
1
+ import uncrypto from 'uncrypto';
2
+ import { seal, unseal, defaults as ironDefaults } from 'iron-webcrypto';
3
+ // iron-webcrypto's internal _Crypto shape; uncrypto satisfies it at runtime in node/browser/edge.
4
+ const ironCrypto = uncrypto;
5
+ export function splitIntoChunks(value, limit) {
6
+ if (limit <= 0)
7
+ return [value];
8
+ const parts = [];
9
+ for (let i = 0; i < value.length; i += limit) {
10
+ parts.push(value.slice(i, i + limit));
11
+ }
12
+ return parts;
13
+ }
14
+ export function sealValue(password, value, ttlSeconds = 604800) {
15
+ return seal(ironCrypto, value, password, {
16
+ ...ironDefaults,
17
+ ttl: ttlSeconds * 1000,
18
+ });
19
+ }
20
+ export async function unsealValue(password, sealed, ttlSeconds = 604800) {
21
+ if (!sealed)
22
+ return null;
23
+ try {
24
+ return (await unseal(ironCrypto, sealed, password, {
25
+ ...ironDefaults,
26
+ ttl: ttlSeconds * 1000,
27
+ }));
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ /**
34
+ * Normalizes the cookie name:
35
+ * If secure=true, preserves `__Host-` or `__Secure-` prefixes.
36
+ * If secure=false (e.g. dev over plain http), strips `__Host-` and `__Secure-` prefixes
37
+ * because browsers strictly reject prefixed cookies over insecure HTTP.
38
+ */
39
+ export function resolveCookieName(name, secure) {
40
+ if (secure)
41
+ return name;
42
+ return name.replace(/^__Host-/, '').replace(/^__Secure-/, '');
43
+ }
44
+ /**
45
+ * Reassembles a chunked cookie if present, or reads single cookie.
46
+ */
47
+ export function assembleChunks(getCookie, name, maxChunks = 4) {
48
+ const direct = getCookie(name);
49
+ if (direct !== undefined && direct !== '')
50
+ return direct;
51
+ const parts = [];
52
+ for (let i = 0; i < maxChunks; i++) {
53
+ const part = getCookie(`${name}.${i}`);
54
+ if (part === undefined || part === '')
55
+ break;
56
+ parts.push(part);
57
+ }
58
+ return parts.length > 0 ? parts.join('') : null;
59
+ }
60
+ //# sourceMappingURL=cookie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookie.js","sourceRoot":"","sources":["../src/cookie.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAEvE,kGAAkG;AAClG,MAAM,UAAU,GAAG,QAAiD,CAAA;AAEpE,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,KAAa;IAC1D,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IAC9B,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;QAC7C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAA;IACvC,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,KAAc,EAAE,UAAU,GAAG,MAAM;IAC7E,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE;QACvC,GAAG,YAAY;QACf,GAAG,EAAE,UAAU,GAAG,IAAI;KACvB,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAI,QAAgB,EAAE,MAA0B,EAAE,UAAU,GAAG,MAAM;IACpG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IACxB,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE;YACjD,GAAG,YAAY;YACf,GAAG,EAAE,UAAU,GAAG,IAAI;SACvB,CAAC,CAAM,CAAA;IACV,CAAC;IACD,MAAM,CAAC;QACL,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,MAAe;IAC7D,IAAI,MAAM;QAAE,OAAO,IAAI,CAAA;IACvB,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;AAC/D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,SAA+C,EAC/C,IAAY,EACZ,SAAS,GAAG,CAAC;IAEb,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC9B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,MAAM,CAAA;IAExD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAA;QACtC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE;YAAE,MAAK;QAC5C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACjD,CAAC"}
@@ -0,0 +1,81 @@
1
+ import type { BackendTokenResponse, BackendMeResponse, BackendPhoneStartResponse, BackendPhoneVerifyResponse, BackendExternalExchangeResponse, HeadlessAdminUser, HeadlessAdminRole, HeadlessAdminUsersPage, CreateHeadlessAdminUserRequest, UpdateHeadlessAdminUserRequest } from './types.js';
2
+ export declare class BackendError extends Error {
3
+ status: number;
4
+ problem: unknown;
5
+ constructor(status: number, problem: unknown);
6
+ }
7
+ export interface HuiaHeadlessClientOptions {
8
+ baseUrl: string;
9
+ allowInsecureTls?: boolean;
10
+ }
11
+ export declare class HuiaHeadlessClient {
12
+ readonly baseUrl: string;
13
+ readonly allowInsecureTls: boolean;
14
+ constructor(options: HuiaHeadlessClientOptions);
15
+ private call;
16
+ register(body: {
17
+ email: string;
18
+ password: string;
19
+ firstName?: string;
20
+ lastName?: string;
21
+ }): Promise<void>;
22
+ login(body: {
23
+ email: string;
24
+ password: string;
25
+ twoFactorCode?: string;
26
+ twoFactorRecoveryCode?: string;
27
+ }): Promise<BackendTokenResponse>;
28
+ refresh(refreshToken: string): Promise<BackendTokenResponse>;
29
+ me(accessToken: string): Promise<BackendMeResponse>;
30
+ confirmEmail(userId: string, code: string, changedEmail?: string): Promise<void>;
31
+ resendConfirmationEmail(email: string): Promise<void>;
32
+ forgotPassword(email: string): Promise<void>;
33
+ resetPassword(body: {
34
+ email: string;
35
+ resetCode: string;
36
+ newPassword: string;
37
+ }): Promise<void>;
38
+ phoneStart(body: {
39
+ phoneNumber: string;
40
+ country?: string;
41
+ captchaResponse?: string;
42
+ }): Promise<BackendPhoneStartResponse>;
43
+ phoneVerify(body: {
44
+ flowId: string;
45
+ code: string;
46
+ }): Promise<BackendPhoneVerifyResponse>;
47
+ phoneCompleteProfile(body: {
48
+ flowId: string;
49
+ firstName: string;
50
+ lastName: string;
51
+ }): Promise<BackendTokenResponse>;
52
+ externalLoginUrl(provider: string, returnUrl: string): string;
53
+ externalExchange(code: string): Promise<BackendExternalExchangeResponse>;
54
+ externalCompleteProfile(body: {
55
+ code: string;
56
+ firstName: string;
57
+ lastName: string;
58
+ }): Promise<BackendTokenResponse>;
59
+ adminListUsers(accessToken: string, params?: {
60
+ page?: number;
61
+ pageSize?: number;
62
+ search?: string;
63
+ }): Promise<HeadlessAdminUsersPage>;
64
+ adminGetUser(accessToken: string, id: string): Promise<HeadlessAdminUser>;
65
+ adminCreateUser(accessToken: string, body: CreateHeadlessAdminUserRequest): Promise<HeadlessAdminUser>;
66
+ adminUpdateUser(accessToken: string, id: string, body: UpdateHeadlessAdminUserRequest): Promise<HeadlessAdminUser>;
67
+ adminDeleteUser(accessToken: string, id: string): Promise<void>;
68
+ adminGetUserRoles(accessToken: string, id: string): Promise<string[]>;
69
+ adminAddUserRole(accessToken: string, id: string, role: string): Promise<void>;
70
+ adminRemoveUserRole(accessToken: string, id: string, role: string): Promise<void>;
71
+ adminLockUser(accessToken: string, id: string): Promise<void>;
72
+ adminUnlockUser(accessToken: string, id: string): Promise<void>;
73
+ adminListRoles(accessToken: string): Promise<{
74
+ data: HeadlessAdminRole[];
75
+ }>;
76
+ adminGetRole(accessToken: string, id: string): Promise<HeadlessAdminRole>;
77
+ adminCreateRole(accessToken: string, name: string): Promise<HeadlessAdminRole>;
78
+ adminUpdateRole(accessToken: string, id: string, name: string): Promise<HeadlessAdminRole>;
79
+ adminDeleteRole(accessToken: string, id: string): Promise<void>;
80
+ }
81
+ //# sourceMappingURL=headless-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headless-client.d.ts","sourceRoot":"","sources":["../src/headless-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,231 @@
1
+ export class BackendError extends Error {
2
+ status;
3
+ problem;
4
+ constructor(status, problem) {
5
+ super(`huia_headless_error: ${status}`);
6
+ this.status = status;
7
+ this.problem = problem;
8
+ this.name = 'BackendError';
9
+ }
10
+ }
11
+ export class HuiaHeadlessClient {
12
+ baseUrl;
13
+ allowInsecureTls;
14
+ constructor(options) {
15
+ this.baseUrl = options.baseUrl.replace(/\/+$/, '');
16
+ this.allowInsecureTls = options.allowInsecureTls ?? false;
17
+ if (this.allowInsecureTls && typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {
18
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
19
+ }
20
+ }
21
+ async call(path, init) {
22
+ const res = await fetch(`${this.baseUrl}${path}`, {
23
+ ...init,
24
+ headers: {
25
+ 'content-type': 'application/json',
26
+ ...init.headers,
27
+ },
28
+ });
29
+ const text = await res.text();
30
+ if (!res.ok) {
31
+ let problem = null;
32
+ if (text) {
33
+ try {
34
+ problem = JSON.parse(text);
35
+ }
36
+ catch {
37
+ problem = text;
38
+ }
39
+ }
40
+ throw new BackendError(res.status, problem);
41
+ }
42
+ if (!text) {
43
+ return undefined;
44
+ }
45
+ return JSON.parse(text);
46
+ }
47
+ register(body) {
48
+ return this.call('/identity/register', {
49
+ method: 'POST',
50
+ body: JSON.stringify(body),
51
+ });
52
+ }
53
+ login(body) {
54
+ return this.call('/identity/login', {
55
+ method: 'POST',
56
+ body: JSON.stringify(body),
57
+ });
58
+ }
59
+ refresh(refreshToken) {
60
+ return this.call('/identity/refresh', {
61
+ method: 'POST',
62
+ body: JSON.stringify({ refreshToken }),
63
+ });
64
+ }
65
+ me(accessToken) {
66
+ return this.call('/identity/me', {
67
+ method: 'GET',
68
+ headers: { authorization: `Bearer ${accessToken}` },
69
+ });
70
+ }
71
+ confirmEmail(userId, code, changedEmail) {
72
+ const query = new URLSearchParams({ userId, code, ...(changedEmail ? { changedEmail } : {}) });
73
+ return this.call(`/identity/confirmEmail?${query}`, { method: 'GET' });
74
+ }
75
+ resendConfirmationEmail(email) {
76
+ return this.call('/identity/resendConfirmationEmail', {
77
+ method: 'POST',
78
+ body: JSON.stringify({ email }),
79
+ });
80
+ }
81
+ forgotPassword(email) {
82
+ return this.call('/identity/forgotPassword', {
83
+ method: 'POST',
84
+ body: JSON.stringify({ email }),
85
+ });
86
+ }
87
+ resetPassword(body) {
88
+ return this.call('/identity/resetPassword', {
89
+ method: 'POST',
90
+ body: JSON.stringify(body),
91
+ });
92
+ }
93
+ phoneStart(body) {
94
+ return this.call('/identity/phone/start', {
95
+ method: 'POST',
96
+ body: JSON.stringify(body),
97
+ });
98
+ }
99
+ phoneVerify(body) {
100
+ return this.call('/identity/phone/verify', {
101
+ method: 'POST',
102
+ body: JSON.stringify(body),
103
+ });
104
+ }
105
+ phoneCompleteProfile(body) {
106
+ return this.call('/identity/phone/complete-profile', {
107
+ method: 'POST',
108
+ body: JSON.stringify(body),
109
+ });
110
+ }
111
+ externalLoginUrl(provider, returnUrl) {
112
+ const q = new URLSearchParams({ returnUrl });
113
+ return `${this.baseUrl}/identity/account/external/${encodeURIComponent(provider)}?${q}`;
114
+ }
115
+ externalExchange(code) {
116
+ return this.call('/identity/account/external/exchange', {
117
+ method: 'POST',
118
+ body: JSON.stringify({ code }),
119
+ });
120
+ }
121
+ externalCompleteProfile(body) {
122
+ return this.call('/identity/account/external/complete-profile', {
123
+ method: 'POST',
124
+ body: JSON.stringify(body),
125
+ });
126
+ }
127
+ adminListUsers(accessToken, params) {
128
+ const q = new URLSearchParams();
129
+ if (params?.page)
130
+ q.set('page', String(params.page));
131
+ if (params?.pageSize)
132
+ q.set('pageSize', String(params.pageSize));
133
+ if (params?.search)
134
+ q.set('search', params.search);
135
+ const qs = q.toString() ? `?${q}` : '';
136
+ return this.call(`/admin/users${qs}`, {
137
+ method: 'GET',
138
+ headers: { authorization: `Bearer ${accessToken}` },
139
+ });
140
+ }
141
+ adminGetUser(accessToken, id) {
142
+ return this.call(`/admin/users/${encodeURIComponent(id)}`, {
143
+ method: 'GET',
144
+ headers: { authorization: `Bearer ${accessToken}` },
145
+ });
146
+ }
147
+ adminCreateUser(accessToken, body) {
148
+ return this.call('/admin/users', {
149
+ method: 'POST',
150
+ headers: { authorization: `Bearer ${accessToken}` },
151
+ body: JSON.stringify(body),
152
+ });
153
+ }
154
+ adminUpdateUser(accessToken, id, body) {
155
+ return this.call(`/admin/users/${encodeURIComponent(id)}`, {
156
+ method: 'PUT',
157
+ headers: { authorization: `Bearer ${accessToken}` },
158
+ body: JSON.stringify(body),
159
+ });
160
+ }
161
+ adminDeleteUser(accessToken, id) {
162
+ return this.call(`/admin/users/${encodeURIComponent(id)}`, {
163
+ method: 'DELETE',
164
+ headers: { authorization: `Bearer ${accessToken}` },
165
+ });
166
+ }
167
+ adminGetUserRoles(accessToken, id) {
168
+ return this.call(`/admin/users/${encodeURIComponent(id)}/roles`, {
169
+ method: 'GET',
170
+ headers: { authorization: `Bearer ${accessToken}` },
171
+ });
172
+ }
173
+ adminAddUserRole(accessToken, id, role) {
174
+ return this.call(`/admin/users/${encodeURIComponent(id)}/roles`, {
175
+ method: 'POST',
176
+ headers: { authorization: `Bearer ${accessToken}` },
177
+ body: JSON.stringify({ role }),
178
+ });
179
+ }
180
+ adminRemoveUserRole(accessToken, id, role) {
181
+ return this.call(`/admin/users/${encodeURIComponent(id)}/roles/${encodeURIComponent(role)}`, {
182
+ method: 'DELETE',
183
+ headers: { authorization: `Bearer ${accessToken}` },
184
+ });
185
+ }
186
+ adminLockUser(accessToken, id) {
187
+ return this.call(`/admin/users/${encodeURIComponent(id)}/lock`, {
188
+ method: 'POST',
189
+ headers: { authorization: `Bearer ${accessToken}` },
190
+ });
191
+ }
192
+ adminUnlockUser(accessToken, id) {
193
+ return this.call(`/admin/users/${encodeURIComponent(id)}/unlock`, {
194
+ method: 'POST',
195
+ headers: { authorization: `Bearer ${accessToken}` },
196
+ });
197
+ }
198
+ adminListRoles(accessToken) {
199
+ return this.call('/admin/roles', {
200
+ method: 'GET',
201
+ headers: { authorization: `Bearer ${accessToken}` },
202
+ });
203
+ }
204
+ adminGetRole(accessToken, id) {
205
+ return this.call(`/admin/roles/${encodeURIComponent(id)}`, {
206
+ method: 'GET',
207
+ headers: { authorization: `Bearer ${accessToken}` },
208
+ });
209
+ }
210
+ adminCreateRole(accessToken, name) {
211
+ return this.call('/admin/roles', {
212
+ method: 'POST',
213
+ headers: { authorization: `Bearer ${accessToken}` },
214
+ body: JSON.stringify({ name }),
215
+ });
216
+ }
217
+ adminUpdateRole(accessToken, id, name) {
218
+ return this.call(`/admin/roles/${encodeURIComponent(id)}`, {
219
+ method: 'PUT',
220
+ headers: { authorization: `Bearer ${accessToken}` },
221
+ body: JSON.stringify({ name }),
222
+ });
223
+ }
224
+ adminDeleteRole(accessToken, id) {
225
+ return this.call(`/admin/roles/${encodeURIComponent(id)}`, {
226
+ method: 'DELETE',
227
+ headers: { authorization: `Bearer ${accessToken}` },
228
+ });
229
+ }
230
+ }
231
+ //# sourceMappingURL=headless-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headless-client.js","sourceRoot":"","sources":["../src/headless-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export * from './types.js';
2
+ export * from './cookie.js';
3
+ export * from './tokens.js';
4
+ export * from './storage.js';
5
+ export * from './refresh.js';
6
+ export * from './headless-client.js';
7
+ export * from './oidc-client.js';
8
+ export { randomUUID } from 'uncrypto';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ export * from './types.js';
2
+ export * from './cookie.js';
3
+ export * from './tokens.js';
4
+ export * from './storage.js';
5
+ export * from './refresh.js';
6
+ export * from './headless-client.js';
7
+ export * from './oidc-client.js';
8
+ export { randomUUID } from 'uncrypto';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,46 @@
1
+ import * as oidc from 'openid-client';
2
+ import type { AuthStateRecord } from './types.js';
3
+ export interface HuiaOidcClientOptions {
4
+ issuer: string;
5
+ clientId: string;
6
+ clientSecret?: string;
7
+ scopes?: string[];
8
+ par?: {
9
+ enabled?: boolean;
10
+ required?: boolean;
11
+ };
12
+ allowInsecureTls?: boolean;
13
+ }
14
+ export interface AuthorizationResult {
15
+ redirectTo: string;
16
+ stateRecord: AuthStateRecord;
17
+ }
18
+ export interface CompletedAuthResult {
19
+ tokens: oidc.TokenEndpointResponse & oidc.TokenEndpointResponseHelpers;
20
+ claims: Record<string, unknown>;
21
+ returnTo?: string;
22
+ }
23
+ export declare class HuiaOidcHelper {
24
+ private configCache;
25
+ private inflightDiscovery;
26
+ getConfiguration(options: HuiaOidcClientOptions): Promise<oidc.Configuration>;
27
+ private discover;
28
+ beginAuthorization(config: oidc.Configuration, options: {
29
+ clientId: string;
30
+ redirectUri: string;
31
+ scopes?: string[];
32
+ returnTo?: string;
33
+ extraParams?: Record<string, string>;
34
+ parEnabled?: boolean;
35
+ parRequired?: boolean;
36
+ }): Promise<AuthorizationResult>;
37
+ completeAuthorization(config: oidc.Configuration, currentUrl: URL, stateRecord: AuthStateRecord, expectedIssuer: string): Promise<CompletedAuthResult>;
38
+ refreshTokens(config: oidc.Configuration, refreshToken: string, scope?: string): Promise<oidc.TokenEndpointResponse & oidc.TokenEndpointResponseHelpers>;
39
+ buildLogoutUrl(config: oidc.Configuration, issuer: string, params: {
40
+ clientId: string;
41
+ postLogoutRedirectUri: string;
42
+ idTokenHint?: string;
43
+ }): string;
44
+ }
45
+ export declare const defaultOidcHelper: HuiaOidcHelper;
46
+ //# sourceMappingURL=oidc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-client.d.ts","sourceRoot":"","sources":["../src/oidc-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,eAAe,CAAA;AAErC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;KACnB,CAAA;IACD,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,eAAe,CAAA;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,4BAA4B,CAAA;IACtE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,WAAW,CAAwC;IAC3D,OAAO,CAAC,iBAAiB,CAAiD;IAEpE,gBAAgB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC;YAoBrE,QAAQ;IAoBhB,kBAAkB,CACtB,MAAM,EAAE,IAAI,CAAC,aAAa,EAC1B,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAA;QAChB,WAAW,EAAE,MAAM,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QACpC,UAAU,CAAC,EAAE,OAAO,CAAA;QACpB,WAAW,CAAC,EAAE,OAAO,CAAA;KACtB,GACA,OAAO,CAAC,mBAAmB,CAAC;IAqDzB,qBAAqB,CACzB,MAAM,EAAE,IAAI,CAAC,aAAa,EAC1B,UAAU,EAAE,GAAG,EACf,WAAW,EAAE,eAAe,EAC5B,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,mBAAmB,CAAC;IAmBzB,aAAa,CACjB,MAAM,EAAE,IAAI,CAAC,aAAa,EAC1B,YAAY,EAAE,MAAM,EACpB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,4BAA4B,CAAC;IAI1E,cAAc,CACZ,MAAM,EAAE,IAAI,CAAC,aAAa,EAC1B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,qBAAqB,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAChF,MAAM;CAkBV;AAED,eAAO,MAAM,iBAAiB,gBAAuB,CAAA"}
@@ -0,0 +1,122 @@
1
+ import * as oidc from 'openid-client';
2
+ import { assertHuiaIssuer } from './tokens.js';
3
+ export class HuiaOidcHelper {
4
+ configCache = new Map();
5
+ inflightDiscovery = new Map();
6
+ async getConfiguration(options) {
7
+ const key = `${options.issuer}:${options.clientId}`;
8
+ const cached = this.configCache.get(key);
9
+ if (cached)
10
+ return cached;
11
+ const pending = this.inflightDiscovery.get(key);
12
+ if (pending)
13
+ return pending;
14
+ const p = this.discover(options);
15
+ this.inflightDiscovery.set(key, p);
16
+ try {
17
+ const cfg = await p;
18
+ this.configCache.set(key, cfg);
19
+ return cfg;
20
+ }
21
+ finally {
22
+ this.inflightDiscovery.delete(key);
23
+ }
24
+ }
25
+ async discover(options) {
26
+ const server = new URL(`${options.issuer.replace(/\/+$/, '')}/.well-known/openid-configuration`);
27
+ const insecure = process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0' || (options.allowInsecureTls && process.env.NODE_ENV !== 'production');
28
+ const clientAuth = options.clientSecret
29
+ ? oidc.ClientSecretPost(options.clientSecret)
30
+ : undefined;
31
+ return oidc.discovery(server, options.clientId, undefined, clientAuth, {
32
+ timeout: 10,
33
+ ...(insecure ? { execute: [oidc.allowInsecureRequests] } : {}),
34
+ });
35
+ }
36
+ async beginAuthorization(config, options) {
37
+ const codeVerifier = oidc.randomPKCECodeVerifier();
38
+ const codeChallenge = await oidc.calculatePKCECodeChallenge(codeVerifier);
39
+ const state = oidc.randomState();
40
+ const nonce = oidc.randomNonce();
41
+ const params = {
42
+ client_id: options.clientId,
43
+ redirect_uri: options.redirectUri,
44
+ response_type: 'code',
45
+ scope: (options.scopes && options.scopes.length > 0)
46
+ ? options.scopes.join(' ')
47
+ : 'openid profile email offline_access',
48
+ state,
49
+ nonce,
50
+ code_challenge: codeChallenge,
51
+ code_challenge_method: 'S256',
52
+ ...options.extraParams,
53
+ };
54
+ const meta = config.serverMetadata();
55
+ const parSupported = !!meta.pushed_authorization_request_endpoint;
56
+ let redirectTo;
57
+ if (options.parEnabled && parSupported) {
58
+ try {
59
+ redirectTo = (await oidc.buildAuthorizationUrlWithPAR(config, params)).href;
60
+ }
61
+ catch (err) {
62
+ if (options.parRequired) {
63
+ throw new Error('par_required: PAR push failed', { cause: err });
64
+ }
65
+ redirectTo = oidc.buildAuthorizationUrl(config, params).href;
66
+ }
67
+ }
68
+ else if (options.parRequired) {
69
+ throw new Error('par_required: server does not advertise pushed_authorization_request_endpoint');
70
+ }
71
+ else {
72
+ redirectTo = oidc.buildAuthorizationUrl(config, params).href;
73
+ }
74
+ const stateRecord = {
75
+ state,
76
+ codeVerifier,
77
+ nonce,
78
+ returnTo: options.returnTo,
79
+ createdAt: Date.now(),
80
+ };
81
+ return { redirectTo, stateRecord };
82
+ }
83
+ async completeAuthorization(config, currentUrl, stateRecord, expectedIssuer) {
84
+ const tokens = await oidc.authorizationCodeGrant(config, currentUrl, {
85
+ pkceCodeVerifier: stateRecord.codeVerifier,
86
+ expectedState: stateRecord.state,
87
+ expectedNonce: stateRecord.nonce,
88
+ idTokenExpected: true,
89
+ });
90
+ const claims = tokens.claims();
91
+ if (!claims)
92
+ throw new Error('missing_id_token');
93
+ assertHuiaIssuer(claims.iss, expectedIssuer);
94
+ return {
95
+ tokens,
96
+ claims,
97
+ returnTo: stateRecord.returnTo,
98
+ };
99
+ }
100
+ async refreshTokens(config, refreshToken, scope) {
101
+ return oidc.refreshTokenGrant(config, refreshToken, scope ? { scope } : undefined);
102
+ }
103
+ buildLogoutUrl(config, issuer, params) {
104
+ const meta = config.serverMetadata();
105
+ const queryParams = {
106
+ client_id: params.clientId,
107
+ post_logout_redirect_uri: params.postLogoutRedirectUri,
108
+ };
109
+ if (params.idTokenHint)
110
+ queryParams.id_token_hint = params.idTokenHint;
111
+ if (meta.end_session_endpoint) {
112
+ return oidc.buildEndSessionUrl(config, queryParams).href;
113
+ }
114
+ const url = new URL(`${issuer.replace(/\/+$/, '')}/connect/logout`);
115
+ for (const [k, v] of Object.entries(queryParams)) {
116
+ url.searchParams.set(k, v);
117
+ }
118
+ return url.href;
119
+ }
120
+ }
121
+ export const defaultOidcHelper = new HuiaOidcHelper();
122
+ //# sourceMappingURL=oidc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-client.js","sourceRoot":"","sources":["../src/oidc-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { HuiaStorageAdapter, TokenRecord } from './types.js';
2
+ export declare class RefreshTokenExpiredError extends Error {
3
+ constructor(message?: string);
4
+ }
5
+ export interface RefreshLockOptions {
6
+ ttlMs?: number;
7
+ earlyRefreshSeconds?: number;
8
+ retryIntervalMs?: number;
9
+ maxWaitMs?: number;
10
+ }
11
+ /**
12
+ * Ensures token record is fresh, using deduplicated in-memory promises and storage locking.
13
+ */
14
+ export declare function ensureFreshTokenRecord(storage: HuiaStorageAdapter, record: TokenRecord, refreshFn: (record: TokenRecord) => Promise<TokenRecord>, options?: RefreshLockOptions): Promise<TokenRecord>;
15
+ //# sourceMappingURL=refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../src/refresh.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGjE,qBAAa,wBAAyB,SAAQ,KAAK;gBACrC,OAAO,SAA0B;CAI9C;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAKD;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,EACxD,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,WAAW,CAAC,CAkBtB"}