@icp-sdk/auth 10.0.2 → 11.1.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.
@@ -0,0 +1,207 @@
1
+ import { Actor, AnonymousIdentity, HttpAgent } from '@icp-sdk/core/agent';
2
+ /**
3
+ * Written out for the same reason as the session methods in `session-minter.ts`:
4
+ * this package carries no Internet Identity declarations.
5
+ */
6
+ const idlFactory = ({ IDL }) => {
7
+ const Timestamp = IDL.Nat64;
8
+ const Status = IDL.Variant({
9
+ Available: IDL.Record({ name: IDL.Opt(IDL.Text) }),
10
+ Pending: IDL.Null,
11
+ Unavailable: IDL.Record({ retry_after: IDL.Opt(Timestamp), reason: IDL.Opt(IDL.Text) }),
12
+ });
13
+ return IDL.Service({
14
+ app_sso_domain_check: IDL.Func([IDL.Text], [], []),
15
+ app_sso_domain_status: IDL.Func([IDL.Text], [Status], ['query']),
16
+ });
17
+ };
18
+ /**
19
+ * Builds the service an SSO domain check calls, as the anonymous caller: the
20
+ * check runs before anyone has signed in.
21
+ */
22
+ export async function createSsoDomainService(options) {
23
+ const agent = await HttpAgent.create({
24
+ ...options.agentOptions,
25
+ // Last, so no agent option can make the check call as someone.
26
+ identity: new AnonymousIdentity(),
27
+ });
28
+ return Actor.createActor(idlFactory, {
29
+ agent,
30
+ canisterId: options.canisterId,
31
+ });
32
+ }
33
+ /** The first and the longest wait between two status reads. */
34
+ export const SSO_POLL_MIN_MS = 500;
35
+ export const SSO_POLL_MAX_MS = 2_000;
36
+ /**
37
+ * How long a check may read `Pending` before it is started again. Matches the
38
+ * age at which Internet Identity treats a fetch as abandoned.
39
+ */
40
+ export const SSO_RECHECK_AFTER_MS = 120_000;
41
+ const CHECKING = Object.freeze({ state: 'checking' });
42
+ const NANOS_PER_MILLI = 1000000n;
43
+ function fromCandid(status) {
44
+ if ('Available' in status) {
45
+ const name = status.Available.name[0];
46
+ return name === undefined ? { state: 'available' } : { state: 'available', name };
47
+ }
48
+ if ('Unavailable' in status) {
49
+ const retryAfterNs = status.Unavailable.retry_after[0];
50
+ const reason = status.Unavailable.reason[0];
51
+ return {
52
+ state: 'unavailable',
53
+ ...(retryAfterNs !== undefined && {
54
+ retryAfter: new Date(Number(retryAfterNs / NANOS_PER_MILLI)),
55
+ }),
56
+ ...(reason !== undefined && { reason }),
57
+ };
58
+ }
59
+ // Pending: the fetch is still running, which is what `checking` already says.
60
+ return undefined;
61
+ }
62
+ function sameStatus(a, b) {
63
+ switch (a.state) {
64
+ case 'checking':
65
+ return b.state === 'checking';
66
+ case 'available':
67
+ return b.state === 'available' && a.name === b.name;
68
+ case 'invalid':
69
+ return b.state === 'invalid' && a.reason === b.reason;
70
+ case 'unavailable':
71
+ return (b.state === 'unavailable' &&
72
+ a.retryAfter?.getTime() === b.retryAfter?.getTime() &&
73
+ a.reason === b.reason);
74
+ }
75
+ }
76
+ /**
77
+ * Asks Internet Identity whether one SSO domain can be signed in with, and holds
78
+ * the answer.
79
+ *
80
+ * One update starts the fetch, then the status is read with a query until it is
81
+ * final: a query needs no consensus, so polling it is cheap where polling an
82
+ * update is not. A read that fails is retried at the next interval, so a check
83
+ * ends only on an answer from Internet Identity, or on {@link dispose}.
84
+ */
85
+ export class SsoStatusChecker {
86
+ #domain;
87
+ #createService;
88
+ #onChange;
89
+ #service;
90
+ #status;
91
+ #timer;
92
+ // Bumped by every start and by dispose, so a run that was replaced drops its
93
+ // late answers instead of overwriting a newer one.
94
+ #run = 0;
95
+ #disposed = false;
96
+ /**
97
+ * @param domain - The normalized domain, or, for a value that is not one, why
98
+ * not: `invalid` from the start and never checked.
99
+ * @param createService - Builds the service on the first call.
100
+ * @param onChange - Called after the status changes.
101
+ */
102
+ constructor(domain, createService, onChange) {
103
+ this.#domain = typeof domain === 'string' ? domain : undefined;
104
+ this.#createService = createService;
105
+ this.#onChange = onChange;
106
+ this.#status =
107
+ typeof domain === 'string'
108
+ ? CHECKING
109
+ : Object.freeze({ state: 'invalid', reason: domain.invalid });
110
+ if (typeof domain === 'string')
111
+ this.#start(0);
112
+ }
113
+ /** The current answer. The same object until it changes. */
114
+ get status() {
115
+ return this.#status;
116
+ }
117
+ /** Checks again. Does nothing for an `invalid` domain, or once disposed. */
118
+ refresh() {
119
+ if (this.#domain === undefined || this.#disposed)
120
+ return;
121
+ this.#set(CHECKING);
122
+ this.#start(0);
123
+ }
124
+ /** Stops checking. A call already sent is not recalled; its answer is dropped. */
125
+ dispose() {
126
+ this.#disposed = true;
127
+ this.#run += 1;
128
+ clearTimeout(this.#timer);
129
+ this.#timer = undefined;
130
+ }
131
+ #start(delayMs) {
132
+ this.#run += 1;
133
+ const run = this.#run;
134
+ clearTimeout(this.#timer);
135
+ this.#timer = setTimeout(() => {
136
+ void this.#check(run);
137
+ }, delayMs);
138
+ }
139
+ #isCurrent(run) {
140
+ return run === this.#run && !this.#disposed;
141
+ }
142
+ async #check(run) {
143
+ const domain = this.#domain;
144
+ if (domain === undefined || !this.#isCurrent(run))
145
+ return;
146
+ const checkedAt = Date.now();
147
+ try {
148
+ const service = await this.#serviceFor();
149
+ if (!this.#isCurrent(run))
150
+ return;
151
+ await service.app_sso_domain_check(domain);
152
+ }
153
+ catch {
154
+ // The reads below still see whatever Internet Identity has, and a check
155
+ // that never started is started again after `SSO_RECHECK_AFTER_MS`.
156
+ }
157
+ await this.#poll(run, domain, checkedAt, SSO_POLL_MIN_MS);
158
+ }
159
+ async #poll(run, domain, checkedAt, nextDelayMs) {
160
+ if (!this.#isCurrent(run))
161
+ return;
162
+ let answer;
163
+ try {
164
+ const service = await this.#serviceFor();
165
+ if (!this.#isCurrent(run))
166
+ return;
167
+ answer = fromCandid(await service.app_sso_domain_status(domain));
168
+ }
169
+ catch {
170
+ answer = undefined;
171
+ }
172
+ if (!this.#isCurrent(run))
173
+ return;
174
+ if (answer !== undefined) {
175
+ this.#set(answer);
176
+ return;
177
+ }
178
+ if (Date.now() - checkedAt >= SSO_RECHECK_AFTER_MS) {
179
+ this.#timer = setTimeout(() => {
180
+ void this.#check(run);
181
+ }, nextDelayMs);
182
+ return;
183
+ }
184
+ this.#timer = setTimeout(() => {
185
+ void this.#poll(run, domain, checkedAt, Math.min(nextDelayMs * 2, SSO_POLL_MAX_MS));
186
+ }, nextDelayMs);
187
+ }
188
+ #serviceFor() {
189
+ if (this.#service === undefined) {
190
+ const created = this.#createService();
191
+ this.#service = created;
192
+ // A service that could not be built is built again on the next call.
193
+ created.catch(() => {
194
+ if (this.#service === created)
195
+ this.#service = undefined;
196
+ });
197
+ }
198
+ return this.#service;
199
+ }
200
+ #set(next) {
201
+ if (sameStatus(this.#status, next))
202
+ return;
203
+ this.#status = next;
204
+ this.#onChange();
205
+ }
206
+ }
207
+ //# sourceMappingURL=sso-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sso-status.js","sourceRoot":"","sources":["../../../src/client/sso-status.ts"],"names":[],"mappings":"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"}
@@ -1,33 +1,10 @@
1
1
  /**
2
2
  * Normalizes an SSO domain to the authority the identity provider fetches the
3
- * discovery document from: lowercased, IDNA-encoded, host and optional port.
3
+ * discovery document from: lowercased and IDNA-encoded. A loopback host may
4
+ * carry a port, for a local mock provider; any other host may not.
4
5
  *
5
6
  * @param domain - The organization domain.
6
7
  * @returns The normalized authority.
7
- * @throws When `domain` is not a domain with an optional port.
8
+ * @throws When `domain` is not a domain, naming every problem with it.
8
9
  */
9
10
  export declare function normalizeSsoDomain(domain: string): string;
10
- /**
11
- * Checks whether an organization domain can be used for SSO sign-in: it is a
12
- * domain name, and it publishes `/.well-known/ii-openid-configuration` with a
13
- * `client_id` and an `openid_configuration` URL.
14
- *
15
- * The document must be served with `Access-Control-Allow-Origin: *`.
16
- *
17
- * The check waits on a third-party server and has no deadline of its own, so
18
- * `signal` sets one. Pass `AbortSignal.timeout(...)` for a one-shot check, or a
19
- * controller you abort per keystroke when checking as the user types.
20
- *
21
- * @param domain - The organization domain.
22
- * @param signal - Bounds the check.
23
- * @returns Whether the domain is usable for SSO sign-in.
24
- * @throws When `signal` aborts — an abandoned check is not a verdict on the
25
- * domain, so it must not be read as `false`.
26
- *
27
- * @example
28
- * if (await isValidSsoDomain(input.value, AbortSignal.timeout(5_000))) {
29
- * const authClient = new AuthClient({ ssoDomain: input.value });
30
- * await authClient.signIn();
31
- * }
32
- */
33
- export declare function isValidSsoDomain(domain: string, signal: AbortSignal): Promise<boolean>;
@@ -1,120 +1,106 @@
1
1
  // The identity provider's cap on the domain it will fetch.
2
2
  const MAX_AUTHORITY_LENGTH = 255;
3
- const WELL_KNOWN_PATH = '/.well-known/ii-openid-configuration';
3
+ // The identity provider's own limits on a DNS name (idna's strict mode).
4
+ const MAX_DNS_NAME_LENGTH = 253;
5
+ const MAX_DNS_LABEL_LENGTH = 63;
6
+ const MAX_QUOTED_LENGTH = 100;
7
+ /** `value` for an error message: cut short, and quoted so control characters show escaped. */
8
+ function quote(value) {
9
+ return JSON.stringify(value.length > MAX_QUOTED_LENGTH ? `${value.slice(0, MAX_QUOTED_LENGTH)}…` : value);
10
+ }
4
11
  /**
5
- * `localhost` / `127.0.0.1`, optionally followed by `:<port>`. IPv6 loopback
6
- * (`[::1]`, etc.) is intentionally not handled — the identity provider doesn't
7
- * recognise it either, and its e2e setup uses the hostname form.
12
+ * `localhost`, `127.0.0.1`, or a name under `.localhost` (RFC 6761 reserves the
13
+ * whole domain for loopback), like the identity provider's own check. IPv6
14
+ * loopback is not one, there either.
8
15
  */
9
- function isLoopbackHost(host) {
10
- let url;
11
- try {
12
- // Parse as a URL authority so the optional `:<port>` is split off for us
13
- // rather than by hand. Invalid input throws and is treated as non-loopback.
14
- url = new URL(`http://${host}`);
16
+ function isLoopbackHost(hostname) {
17
+ return hostname === 'localhost' || hostname === '127.0.0.1' || hostname.endsWith('.localhost');
18
+ }
19
+ /** What keeps `hostname` from being a DNS name, by the identity provider's rules. */
20
+ function dnsNameProblems(hostname) {
21
+ const labels = hostname.split('.');
22
+ const problems = [];
23
+ if (labels.length < 2)
24
+ problems.push('a single label');
25
+ if (labels.some((label) => label.length === 0))
26
+ problems.push('an empty label');
27
+ if (labels.some((label) => label.length > MAX_DNS_LABEL_LENGTH)) {
28
+ problems.push(`a label longer than ${MAX_DNS_LABEL_LENGTH} characters`);
15
29
  }
16
- catch {
17
- return false;
30
+ if (labels.some((label) => /[^a-z0-9-]/.test(label))) {
31
+ problems.push('a character other than a letter, digit, or hyphen');
32
+ }
33
+ if (labels.some((label) => label.startsWith('-') || label.endsWith('-'))) {
34
+ problems.push('a label starting or ending with a hyphen');
18
35
  }
19
- // A bare `host[:port]` has no path/query/fragment; reject e.g. `localhost/x`.
20
- if (url.pathname !== '/' || url.search !== '' || url.hash !== '') {
21
- return false;
36
+ // `--` in the third and fourth places is reserved, except for punycode.
37
+ if (labels.some((label) => label.slice(2, 4) === '--' && !label.startsWith('xn--'))) {
38
+ problems.push('a label with "--" in its third and fourth places');
22
39
  }
23
- return url.hostname === 'localhost' || url.hostname === '127.0.0.1';
40
+ if (hostname.length > MAX_DNS_NAME_LENGTH) {
41
+ problems.push(`a name longer than ${MAX_DNS_NAME_LENGTH} characters`);
42
+ }
43
+ return problems;
44
+ }
45
+ function listed(items) {
46
+ return items.length < 2 ? items.join('') : `${items.slice(0, -1).join(', ')} and ${items.at(-1)}`;
24
47
  }
25
48
  /**
26
49
  * Normalizes an SSO domain to the authority the identity provider fetches the
27
- * discovery document from: lowercased, IDNA-encoded, host and optional port.
50
+ * discovery document from: lowercased and IDNA-encoded. A loopback host may
51
+ * carry a port, for a local mock provider; any other host may not.
28
52
  *
29
53
  * @param domain - The organization domain.
30
54
  * @returns The normalized authority.
31
- * @throws When `domain` is not a domain with an optional port.
55
+ * @throws When `domain` is not a domain, naming every problem with it.
32
56
  */
33
57
  export function normalizeSsoDomain(domain) {
34
58
  const trimmed = domain.trim();
35
59
  if (trimmed.length === 0) {
36
60
  throw new Error('ssoDomain cannot be empty');
37
61
  }
62
+ const scheme = /^[a-z][a-z0-9+.-]*:\/\//i.exec(trimmed)?.[0];
63
+ const rest = scheme === undefined ? trimmed : trimmed.slice(scheme.length);
38
64
  let url;
39
65
  try {
40
- url = new URL(`https://${trimmed}`);
66
+ url = new URL(`https://${rest}`);
41
67
  }
42
68
  catch {
43
- throw new Error(`ssoDomain is not a domain: ${trimmed}`);
44
- }
45
- const authority = url.host;
46
- // Rebuilding from the host and port alone has to reproduce what was parsed,
47
- // so anything else the domain carried shows up as a difference.
48
- if (new URL(`https://${authority}`).href !== url.href) {
49
- throw new Error(`ssoDomain must be a domain and optional port, nothing else: ${trimmed}`);
69
+ throw new Error(`ssoDomain ${quote(trimmed)} is not a domain`);
50
70
  }
51
- if (authority.length > MAX_AUTHORITY_LENGTH) {
52
- throw new Error(`ssoDomain exceeds ${MAX_AUTHORITY_LENGTH} characters`);
71
+ const { username, password, pathname, hostname, port, host, href } = url;
72
+ // `URL` drops an empty or default port such as `:443`, so the typed one is read
73
+ // from the input itself.
74
+ const typedAuthority = rest.split(/[/?#]/)[0] ?? '';
75
+ const typedPort = /:([0-9]*)$/.exec(typedAuthority.slice(typedAuthority.lastIndexOf('@') + 1))?.[1];
76
+ const [beforeFragment = ''] = href.split('#');
77
+ const problems = [];
78
+ if (scheme !== undefined)
79
+ problems.push('a scheme');
80
+ if (username !== '' || password !== '')
81
+ problems.push('userinfo');
82
+ if (pathname !== '/')
83
+ problems.push('a path');
84
+ if (beforeFragment.includes('?'))
85
+ problems.push('a query');
86
+ if (href.includes('#'))
87
+ problems.push('a fragment');
88
+ const loopback = isLoopbackHost(hostname);
89
+ if (typedPort !== undefined && !loopback) {
90
+ problems.push('a port, which only loopback hosts may carry');
53
91
  }
54
- // A bare hostname is a half-typed domain, not something worth a request.
55
- if (!authority.includes('.') && !isLoopbackHost(authority)) {
56
- throw new Error(`ssoDomain is not a domain name: ${trimmed}`);
92
+ else if (typedPort !== undefined && (typedPort === '' || typedPort !== port)) {
93
+ problems.push('an empty or default port');
57
94
  }
58
- return authority;
59
- }
60
- function publishesSsoConfiguration(value) {
61
- if (typeof value !== 'object' || value === null) {
62
- return false;
95
+ if (trimmed.length > MAX_AUTHORITY_LENGTH) {
96
+ problems.push(`more than ${MAX_AUTHORITY_LENGTH} characters`);
63
97
  }
64
- const { client_id, openid_configuration } = value;
65
- return typeof client_id === 'string' && typeof openid_configuration === 'string';
66
- }
67
- /**
68
- * Checks whether an organization domain can be used for SSO sign-in: it is a
69
- * domain name, and it publishes `/.well-known/ii-openid-configuration` with a
70
- * `client_id` and an `openid_configuration` URL.
71
- *
72
- * The document must be served with `Access-Control-Allow-Origin: *`.
73
- *
74
- * The check waits on a third-party server and has no deadline of its own, so
75
- * `signal` sets one. Pass `AbortSignal.timeout(...)` for a one-shot check, or a
76
- * controller you abort per keystroke when checking as the user types.
77
- *
78
- * @param domain - The organization domain.
79
- * @param signal - Bounds the check.
80
- * @returns Whether the domain is usable for SSO sign-in.
81
- * @throws When `signal` aborts — an abandoned check is not a verdict on the
82
- * domain, so it must not be read as `false`.
83
- *
84
- * @example
85
- * if (await isValidSsoDomain(input.value, AbortSignal.timeout(5_000))) {
86
- * const authClient = new AuthClient({ ssoDomain: input.value });
87
- * await authClient.signIn();
88
- * }
89
- */
90
- export async function isValidSsoDomain(domain, signal) {
91
- signal.throwIfAborted();
92
- let normalized;
93
- try {
94
- normalized = normalizeSsoDomain(domain);
95
- }
96
- catch {
97
- return false;
98
- }
99
- const scheme = isLoopbackHost(normalized) ? 'http' : 'https';
100
- try {
101
- const response = await fetch(`${scheme}://${normalized}${WELL_KNOWN_PATH}`, {
102
- headers: { Accept: 'application/json' },
103
- signal,
104
- });
105
- if (!response.ok) {
106
- return false;
107
- }
108
- const valid = publishesSsoConfiguration(await response.json());
109
- signal.throwIfAborted();
110
- return valid;
98
+ else if (!loopback) {
99
+ problems.push(...dnsNameProblems(hostname));
111
100
  }
112
- catch (error) {
113
- if (signal.aborted) {
114
- throw error;
115
- }
116
- // A DNS, TLS, CORS, or parse failure all leave the domain unusable.
117
- return false;
101
+ if (problems.length > 0) {
102
+ throw new Error(`ssoDomain ${quote(trimmed)} has ${listed(problems)}`);
118
103
  }
104
+ return host;
119
105
  }
120
106
  //# sourceMappingURL=sso.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sso.js","sourceRoot":"","sources":["../../../src/client/sso.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sso.js","sourceRoot":"","sources":["../../../src/client/sso.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC,yEAAyE;AACzE,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAChC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,8FAA8F;AAC9F,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,IAAI,CAAC,SAAS,CACnB,KAAK,CAAC,MAAM,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CACnF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,QAAgB;IACtC,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AACjG,CAAC;AAED,qFAAqF;AACrF,SAAS,eAAe,CAAC,QAAgB;IACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACvD,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,oBAAoB,CAAC,EAAE,CAAC;QAChE,QAAQ,CAAC,IAAI,CAAC,uBAAuB,oBAAoB,aAAa,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACrD,QAAQ,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QACzE,QAAQ,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAC5D,CAAC;IACD,wEAAwE;IACxE,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACpF,QAAQ,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,mBAAmB,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,sBAAsB,mBAAmB,aAAa,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,MAAM,CAAC,KAAe;IAC7B,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACpG,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,MAAM,GAAG,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3E,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC;IACzE,gFAAgF;IAChF,yBAAyB;IACzB,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CACjC,cAAc,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAC1D,EAAE,CAAC,CAAC,CAAC,CAAC;IACP,MAAM,CAAC,cAAc,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE9C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,MAAM,KAAK,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACpD,IAAI,QAAQ,KAAK,EAAE,IAAI,QAAQ,KAAK,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAClE,IAAI,QAAQ,KAAK,GAAG;QAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3D,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC/D,CAAC;SAAM,IAAI,SAAS,KAAK,SAAS,IAAI,CAAC,SAAS,KAAK,EAAE,IAAI,SAAS,KAAK,IAAI,CAAC,EAAE,CAAC;QAC/E,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,aAAa,oBAAoB,aAAa,CAAC,CAAC;IAChE,CAAC;SAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,CAAC,OAAO,CAAC,QAAQ,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@icp-sdk/auth",
3
- "version": "10.0.2",
3
+ "version": "11.1.0",
4
4
  "author": "DFINITY Stiftung <sdk@dfinity.org>",
5
5
  "license": "Apache-2.0",
6
6
  "description": "Authentication library for Internet Computer web apps",