@auth0/auth0-spa-js 2.5.0 → 2.6.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 +1 -1
- package/dist/auth0-spa-js.development.js +164 -7
- package/dist/auth0-spa-js.development.js.map +1 -1
- package/dist/auth0-spa-js.production.esm.js +1 -1
- package/dist/auth0-spa-js.production.esm.js.map +1 -1
- package/dist/auth0-spa-js.production.js +1 -1
- package/dist/auth0-spa-js.production.js.map +1 -1
- package/dist/auth0-spa-js.worker.development.js.map +1 -1
- package/dist/auth0-spa-js.worker.production.js.map +1 -1
- package/dist/lib/auth0-spa-js.cjs.js +172 -8
- package/dist/lib/auth0-spa-js.cjs.js.map +1 -1
- package/dist/typings/Auth0Client.d.ts +42 -2
- package/dist/typings/MyAccountApiClient.d.ts +92 -0
- package/dist/typings/errors.d.ts +10 -0
- package/dist/typings/fetcher.d.ts +1 -1
- package/dist/typings/global.d.ts +93 -0
- package/dist/typings/index.d.ts +2 -1
- package/dist/typings/transaction-manager.d.ts +15 -4
- package/dist/typings/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Auth0Client.ts +197 -12
- package/src/MyAccountApiClient.ts +158 -0
- package/src/errors.ts +18 -0
- package/src/fetcher.ts +2 -2
- package/src/global.ts +105 -3
- package/src/index.ts +5 -0
- package/src/transaction-manager.ts +17 -4
- package/src/utils.ts +1 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { AuthorizationParams } from './global';
|
|
2
|
+
import { Fetcher } from './fetcher';
|
|
3
|
+
|
|
4
|
+
interface ConnectRequest {
|
|
5
|
+
/** The name of the connection to link the account with (e.g., 'google-oauth2', 'facebook'). */
|
|
6
|
+
connection: string;
|
|
7
|
+
/** The URI to redirect to after the connection process completes. */
|
|
8
|
+
redirect_uri: string;
|
|
9
|
+
/** An opaque value used to maintain state between the request and callback. */
|
|
10
|
+
state?: string;
|
|
11
|
+
/** A string value used to associate a Client session with an ID Token, and to mitigate replay attacks. */
|
|
12
|
+
nonce?: string;
|
|
13
|
+
/** The PKCE code challenge derived from the code verifier. */
|
|
14
|
+
code_challenge?: string;
|
|
15
|
+
/** The method used to derive the code challenge. Required when code_challenge is provided. */
|
|
16
|
+
code_challenge_method?: 'S256';
|
|
17
|
+
authorization_params?: AuthorizationParams;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ConnectResponse {
|
|
21
|
+
/** The base URI to initiate the account connection flow. */
|
|
22
|
+
connect_uri: string;
|
|
23
|
+
/** The authentication session identifier. */
|
|
24
|
+
auth_session: string;
|
|
25
|
+
/** Parameters to be used with the connect URI. */
|
|
26
|
+
connect_params: {
|
|
27
|
+
/** The ticket identifier to be used with the connection URI. */
|
|
28
|
+
ticket: string;
|
|
29
|
+
};
|
|
30
|
+
/** The number of seconds until the ticket expires. */
|
|
31
|
+
expires_in: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface CompleteRequest {
|
|
35
|
+
/** The authentication session identifier */
|
|
36
|
+
auth_session: string;
|
|
37
|
+
/** The authorization code returned from the connect flow */
|
|
38
|
+
connect_code: string;
|
|
39
|
+
/** The redirect URI used in the original request */
|
|
40
|
+
redirect_uri: string;
|
|
41
|
+
/** The PKCE code verifier */
|
|
42
|
+
code_verifier?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface CompleteResponse {
|
|
46
|
+
/** The unique identifier of the connected account */
|
|
47
|
+
id: string;
|
|
48
|
+
/** The connection name */
|
|
49
|
+
connection: string;
|
|
50
|
+
/** The access type, always 'offline' */
|
|
51
|
+
access_type: 'offline';
|
|
52
|
+
/** Array of scopes granted */
|
|
53
|
+
scopes?: string[];
|
|
54
|
+
/** ISO date string of when the connected account was created */
|
|
55
|
+
created_at: string;
|
|
56
|
+
/** ISO date string of when the refresh token expires (optional) */
|
|
57
|
+
expires_at?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Validation error returned from MyAccount API
|
|
61
|
+
export interface ErrorResponse {
|
|
62
|
+
type: string;
|
|
63
|
+
status: number;
|
|
64
|
+
title: string;
|
|
65
|
+
detail: string;
|
|
66
|
+
validation_errors?: {
|
|
67
|
+
detail: string;
|
|
68
|
+
field?: string;
|
|
69
|
+
pointer?: string;
|
|
70
|
+
source?: string;
|
|
71
|
+
}[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Subset of the MyAccount API that handles the connect accounts flow.
|
|
76
|
+
*/
|
|
77
|
+
export class MyAccountApiClient {
|
|
78
|
+
constructor(
|
|
79
|
+
private myAccountFetcher: Fetcher<Response>,
|
|
80
|
+
private apiBase: string
|
|
81
|
+
) {}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get a ticket for the connect account flow.
|
|
85
|
+
*/
|
|
86
|
+
async connectAccount(params: ConnectRequest): Promise<ConnectResponse> {
|
|
87
|
+
const res = await this.myAccountFetcher.fetchWithAuth(
|
|
88
|
+
`${this.apiBase}v1/connected-accounts/connect`,
|
|
89
|
+
{
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: { 'Content-Type': 'application/json' },
|
|
92
|
+
body: JSON.stringify(params)
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
return this._handleResponse(res);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Verify the redirect from the connect account flow and complete the connecting of the account.
|
|
100
|
+
*/
|
|
101
|
+
async completeAccount(params: CompleteRequest): Promise<CompleteResponse> {
|
|
102
|
+
const res = await this.myAccountFetcher.fetchWithAuth(
|
|
103
|
+
`${this.apiBase}v1/connected-accounts/complete`,
|
|
104
|
+
{
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: { 'Content-Type': 'application/json' },
|
|
107
|
+
body: JSON.stringify(params)
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
return this._handleResponse(res);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private async _handleResponse(res: Response) {
|
|
114
|
+
let body: any;
|
|
115
|
+
try {
|
|
116
|
+
body = await res.text();
|
|
117
|
+
body = JSON.parse(body);
|
|
118
|
+
} catch (err) {
|
|
119
|
+
throw new MyAccountApiError({
|
|
120
|
+
type: 'invalid_json',
|
|
121
|
+
status: res.status,
|
|
122
|
+
title: 'Invalid JSON response',
|
|
123
|
+
detail: body || String(err)
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (res.ok) {
|
|
128
|
+
return body;
|
|
129
|
+
} else {
|
|
130
|
+
throw new MyAccountApiError(body);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export class MyAccountApiError extends Error {
|
|
136
|
+
public readonly type: string;
|
|
137
|
+
public readonly status: number;
|
|
138
|
+
public readonly title: string;
|
|
139
|
+
public readonly detail: string;
|
|
140
|
+
public readonly validation_errors?: ErrorResponse['validation_errors'];
|
|
141
|
+
|
|
142
|
+
constructor({
|
|
143
|
+
type,
|
|
144
|
+
status,
|
|
145
|
+
title,
|
|
146
|
+
detail,
|
|
147
|
+
validation_errors
|
|
148
|
+
}: ErrorResponse) {
|
|
149
|
+
super(detail);
|
|
150
|
+
this.name = 'MyAccountApiError';
|
|
151
|
+
this.type = type;
|
|
152
|
+
this.status = status;
|
|
153
|
+
this.title = title;
|
|
154
|
+
this.detail = detail;
|
|
155
|
+
this.validation_errors = validation_errors;
|
|
156
|
+
Object.setPrototypeOf(this, MyAccountApiError.prototype);
|
|
157
|
+
}
|
|
158
|
+
}
|
package/src/errors.ts
CHANGED
|
@@ -35,6 +35,24 @@ export class AuthenticationError extends GenericError {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Thrown when handling the redirect callback for the connect flow fails, will be one of Auth0's
|
|
40
|
+
* Authentication API's Standard Error Responses: https://auth0.com/docs/api/authentication?javascript#standard-error-responses
|
|
41
|
+
*/
|
|
42
|
+
export class ConnectError extends GenericError {
|
|
43
|
+
constructor(
|
|
44
|
+
error: string,
|
|
45
|
+
error_description: string,
|
|
46
|
+
public connection: string,
|
|
47
|
+
public state: string,
|
|
48
|
+
public appState: any = null
|
|
49
|
+
) {
|
|
50
|
+
super(error, error_description);
|
|
51
|
+
//https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
52
|
+
Object.setPrototypeOf(this, ConnectError.prototype);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
38
56
|
/**
|
|
39
57
|
* Thrown when silent auth times out (usually due to a configuration issue) or
|
|
40
58
|
* when network requests to the Auth server timeout.
|
package/src/fetcher.ts
CHANGED
|
@@ -114,10 +114,10 @@ export class Fetcher<TOutput extends CustomFetchMinimalOutput> {
|
|
|
114
114
|
);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
protected
|
|
117
|
+
protected setAuthorizationHeader(
|
|
118
118
|
request: Request,
|
|
119
119
|
accessToken: string
|
|
120
|
-
):
|
|
120
|
+
): void {
|
|
121
121
|
request.headers.set(
|
|
122
122
|
'authorization',
|
|
123
123
|
`${this.config.dpopNonceId ? 'DPoP' : 'Bearer'} ${accessToken}`
|
package/src/global.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ICache } from './cache';
|
|
2
2
|
import type { Dpop } from './dpop/dpop';
|
|
3
|
+
import { CompleteResponse } from './MyAccountApiClient';
|
|
3
4
|
|
|
4
5
|
export interface AuthorizationParams {
|
|
5
6
|
/**
|
|
@@ -265,10 +266,10 @@ export interface Auth0ClientOptions extends BaseLoginOptions {
|
|
|
265
266
|
|
|
266
267
|
/**
|
|
267
268
|
* If provided, the SDK will load the token worker from this URL instead of the integrated `blob`. An example of when this is useful is if you have strict
|
|
268
|
-
* Content-Security-Policy (CSP) and wish to avoid needing to set `worker-src: blob:`. We recommend either serving the worker, which you can find in the module
|
|
269
|
-
* at `<module_path>/dist/auth0-spa-js.worker.production.js`, from the same host as your application or using the Auth0 CDN
|
|
269
|
+
* Content-Security-Policy (CSP) and wish to avoid needing to set `worker-src: blob:`. We recommend either serving the worker, which you can find in the module
|
|
270
|
+
* at `<module_path>/dist/auth0-spa-js.worker.production.js`, from the same host as your application or using the Auth0 CDN
|
|
270
271
|
* `https://cdn.auth0.com/js/auth0-spa-js/<version>/auth0-spa-js.worker.production.js`.
|
|
271
|
-
*
|
|
272
|
+
*
|
|
272
273
|
* **Note**: The worker is only used when `useRefreshTokens: true`, `cacheLocation: 'memory'`, and the `cache` is not custom.
|
|
273
274
|
*/
|
|
274
275
|
workerUrl?: string;
|
|
@@ -353,11 +354,26 @@ export interface RedirectLoginOptions<TAppState = any>
|
|
|
353
354
|
openUrl?: (url: string) => Promise<void> | void;
|
|
354
355
|
}
|
|
355
356
|
|
|
357
|
+
/**
|
|
358
|
+
* The types of responses expected from the authorization server.
|
|
359
|
+
* - `code`: used for the standard login flow.
|
|
360
|
+
* - `connect_code`: used for the connect account flow.
|
|
361
|
+
*/
|
|
362
|
+
export enum ResponseType {
|
|
363
|
+
Code = 'code',
|
|
364
|
+
ConnectCode = 'connect_code'
|
|
365
|
+
}
|
|
366
|
+
|
|
356
367
|
export interface RedirectLoginResult<TAppState = any> {
|
|
357
368
|
/**
|
|
358
369
|
* State stored when the redirect request was made
|
|
359
370
|
*/
|
|
360
371
|
appState?: TAppState;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* The type of response, for login it will be `code`
|
|
375
|
+
*/
|
|
376
|
+
response_type: ResponseType.Code;
|
|
361
377
|
}
|
|
362
378
|
|
|
363
379
|
export interface PopupLoginOptions extends BaseLoginOptions { }
|
|
@@ -523,12 +539,98 @@ export interface LogoutOptions extends LogoutUrlOptions {
|
|
|
523
539
|
openUrl?: false | ((url: string) => Promise<void> | void);
|
|
524
540
|
}
|
|
525
541
|
|
|
542
|
+
export interface RedirectConnectAccountOptions<TAppState = any> {
|
|
543
|
+
/**
|
|
544
|
+
* The name of the connection to link (e.g. 'google-oauth2').
|
|
545
|
+
*/
|
|
546
|
+
connection: string;
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Additional authorization parameters for the request.
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* await auth0.connectAccountWithRedirect({
|
|
553
|
+
* connection: 'google-oauth2',
|
|
554
|
+
* authorization_params: {
|
|
555
|
+
* scope: 'https://www.googleapis.com/auth/calendar'
|
|
556
|
+
* access_type: 'offline'
|
|
557
|
+
* }
|
|
558
|
+
* });
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* await auth0.connectAccountWithRedirect({
|
|
562
|
+
* connection: 'github',
|
|
563
|
+
* authorization_params: {
|
|
564
|
+
* scope: 'repo user',
|
|
565
|
+
* audience: 'https://api.github.com'
|
|
566
|
+
* }
|
|
567
|
+
* });
|
|
568
|
+
*/
|
|
569
|
+
authorization_params?: AuthorizationParams;
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* The URI to redirect back to after connecting the account.
|
|
573
|
+
*/
|
|
574
|
+
redirectUri?: string;
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Optional application state to persist through the transaction.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* await auth0.connectAccountWithRedirect({
|
|
581
|
+
* connection: 'google-oauth2',
|
|
582
|
+
* appState: { returnTo: '/settings' }
|
|
583
|
+
* });
|
|
584
|
+
*/
|
|
585
|
+
appState?: TAppState;
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Optional function to handle the redirect URL.
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* await auth0.connectAccountWithRedirect({
|
|
592
|
+
* connection: 'google-oauth2',
|
|
593
|
+
* openUrl: async (url) => { myBrowserApi.open(url); }
|
|
594
|
+
* });
|
|
595
|
+
*/
|
|
596
|
+
openUrl?: (url: string) => Promise<void>;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* The result returned after a successful account connection redirect.
|
|
601
|
+
*
|
|
602
|
+
* Combines the redirect login result (including any persisted app state)
|
|
603
|
+
* with the complete response from the My Account API.
|
|
604
|
+
*
|
|
605
|
+
* @template TAppState - The type of application state persisted through the transaction.
|
|
606
|
+
* @example
|
|
607
|
+
* const result = await auth0.connectAccountWithRedirect(options);
|
|
608
|
+
* console.log(result.appState); // Access persisted app state
|
|
609
|
+
* console.log(result.connection); // The connection of the account you connected to.
|
|
610
|
+
* console.log(result.response_type === 'connect_code'); // The response type will be 'connect_code'
|
|
611
|
+
*/
|
|
612
|
+
export type ConnectAccountRedirectResult<TAppState = any> = CompleteResponse & {
|
|
613
|
+
/**
|
|
614
|
+
* State stored when the redirect request was made
|
|
615
|
+
*/
|
|
616
|
+
appState?: TAppState;
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* The type of response, for connect account it will be `connect_code`
|
|
620
|
+
*/
|
|
621
|
+
response_type: ResponseType.ConnectCode;
|
|
622
|
+
};
|
|
623
|
+
|
|
526
624
|
/**
|
|
527
625
|
* @ignore
|
|
528
626
|
*/
|
|
529
627
|
export interface AuthenticationResult {
|
|
530
628
|
state: string;
|
|
531
629
|
code?: string;
|
|
630
|
+
/**
|
|
631
|
+
* This is for the redirect from the connect account flow.
|
|
632
|
+
*/
|
|
633
|
+
connect_code?: string;
|
|
532
634
|
error?: string;
|
|
533
635
|
error_description?: string;
|
|
534
636
|
}
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export async function createAuth0Client(options: Auth0ClientOptions) {
|
|
|
23
23
|
export { Auth0Client };
|
|
24
24
|
|
|
25
25
|
export {
|
|
26
|
+
ConnectError,
|
|
26
27
|
GenericError,
|
|
27
28
|
AuthenticationError,
|
|
28
29
|
TimeoutError,
|
|
@@ -48,3 +49,7 @@ export {
|
|
|
48
49
|
} from './cache';
|
|
49
50
|
|
|
50
51
|
export { type FetcherConfig } from './fetcher';
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
MyAccountApiError
|
|
55
|
+
} from './MyAccountApiClient';
|
|
@@ -2,7 +2,7 @@ import { ClientStorage } from './storage';
|
|
|
2
2
|
|
|
3
3
|
const TRANSACTION_STORAGE_KEY_PREFIX = 'a0.spajs.txs';
|
|
4
4
|
|
|
5
|
-
interface
|
|
5
|
+
export interface LoginTransaction {
|
|
6
6
|
nonce: string;
|
|
7
7
|
scope: string;
|
|
8
8
|
audience: string;
|
|
@@ -11,6 +11,19 @@ interface Transaction {
|
|
|
11
11
|
redirect_uri?: string;
|
|
12
12
|
organization?: string;
|
|
13
13
|
state?: string;
|
|
14
|
+
response_type: 'code';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ConnectAccountTransaction {
|
|
18
|
+
appState?: any;
|
|
19
|
+
audience?: string;
|
|
20
|
+
auth_session: string;
|
|
21
|
+
code_verifier: string;
|
|
22
|
+
redirect_uri: string;
|
|
23
|
+
scope?: string;
|
|
24
|
+
state: string;
|
|
25
|
+
connection: string;
|
|
26
|
+
response_type: 'connect_code';
|
|
14
27
|
}
|
|
15
28
|
|
|
16
29
|
export class TransactionManager {
|
|
@@ -24,14 +37,14 @@ export class TransactionManager {
|
|
|
24
37
|
this.storageKey = `${TRANSACTION_STORAGE_KEY_PREFIX}.${this.clientId}`;
|
|
25
38
|
}
|
|
26
39
|
|
|
27
|
-
public create(transaction:
|
|
40
|
+
public create<T extends Object = LoginTransaction>(transaction: T) {
|
|
28
41
|
this.storage.save(this.storageKey, transaction, {
|
|
29
42
|
daysUntilExpire: 1,
|
|
30
43
|
cookieDomain: this.cookieDomain
|
|
31
44
|
});
|
|
32
45
|
}
|
|
33
46
|
|
|
34
|
-
public get():
|
|
47
|
+
public get<T extends Object = LoginTransaction>(): T | undefined {
|
|
35
48
|
return this.storage.get(this.storageKey);
|
|
36
49
|
}
|
|
37
50
|
|
|
@@ -40,4 +53,4 @@ export class TransactionManager {
|
|
|
40
53
|
cookieDomain: this.cookieDomain
|
|
41
54
|
});
|
|
42
55
|
}
|
|
43
|
-
}
|
|
56
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -24,6 +24,7 @@ export const parseAuthenticationResult = (
|
|
|
24
24
|
return {
|
|
25
25
|
state: searchParams.get('state')!,
|
|
26
26
|
code: searchParams.get('code') || undefined,
|
|
27
|
+
connect_code: searchParams.get('connect_code') || undefined,
|
|
27
28
|
error: searchParams.get('error') || undefined,
|
|
28
29
|
error_description: searchParams.get('error_description') || undefined
|
|
29
30
|
};
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '2.
|
|
1
|
+
export default '2.6.0';
|