@auth0/auth0-spa-js 1.21.1 → 1.22.2
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 +5233 -6033
- package/dist/auth0-spa-js.development.js.map +1 -1
- package/dist/auth0-spa-js.production.esm.js +1 -15
- package/dist/auth0-spa-js.production.esm.js.map +1 -1
- package/dist/auth0-spa-js.production.js +1 -15
- package/dist/auth0-spa-js.production.js.map +1 -1
- package/dist/lib/auth0-spa-js.cjs.js +4854 -5186
- package/dist/lib/auth0-spa-js.cjs.js.map +1 -1
- package/dist/typings/Auth0Client.d.ts +1 -0
- package/dist/typings/constants.d.ts +1 -1
- package/dist/typings/errors.d.ts +5 -0
- package/dist/typings/global.d.ts +24 -1
- package/dist/typings/utils.d.ts +7 -0
- package/dist/typings/version.d.ts +1 -1
- package/package.json +4 -5
- package/src/Auth0Client.ts +27 -7
- package/src/constants.ts +1 -2
- package/src/errors.ts +15 -0
- package/src/global.ts +27 -2
- package/src/utils.ts +10 -0
- package/src/version.ts +1 -1
- package/src/worker/token.worker.ts +2 -2
|
@@ -17,6 +17,7 @@ export default class Auth0Client {
|
|
|
17
17
|
private readonly isAuthenticatedCookieName;
|
|
18
18
|
private readonly nowProvider;
|
|
19
19
|
private readonly httpTimeoutMs;
|
|
20
|
+
private readonly useRefreshTokensFallback;
|
|
20
21
|
cacheLocation: CacheLocation;
|
|
21
22
|
private worker;
|
|
22
23
|
constructor(options: Auth0ClientOptions);
|
|
@@ -24,7 +24,7 @@ export declare const CACHE_LOCATION_LOCAL_STORAGE = "localstorage";
|
|
|
24
24
|
/**
|
|
25
25
|
* @ignore
|
|
26
26
|
*/
|
|
27
|
-
export declare const MISSING_REFRESH_TOKEN_ERROR_MESSAGE = "
|
|
27
|
+
export declare const MISSING_REFRESH_TOKEN_ERROR_MESSAGE = "Missing Refresh Token";
|
|
28
28
|
/**
|
|
29
29
|
* @ignore
|
|
30
30
|
*/
|
package/dist/typings/errors.d.ts
CHANGED
|
@@ -48,3 +48,8 @@ export declare class MfaRequiredError extends GenericError {
|
|
|
48
48
|
mfa_token: string;
|
|
49
49
|
constructor(error: string, error_description: string, mfa_token: string);
|
|
50
50
|
}
|
|
51
|
+
export declare class MissingRefreshTokenError extends GenericError {
|
|
52
|
+
audience: string;
|
|
53
|
+
scope: string;
|
|
54
|
+
constructor(audience: string, scope: string);
|
|
55
|
+
}
|
package/dist/typings/global.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export interface BaseLoginOptions {
|
|
|
39
39
|
*
|
|
40
40
|
* This only affects the New Universal Login Experience.
|
|
41
41
|
*/
|
|
42
|
-
screen_hint?: string;
|
|
42
|
+
screen_hint?: 'signup' | 'login' | string;
|
|
43
43
|
/**
|
|
44
44
|
* The user's email address or other identifier. When your app knows
|
|
45
45
|
* which user is trying to authenticate, you can provide this parameter
|
|
@@ -138,6 +138,26 @@ export interface Auth0ClientOptions extends BaseLoginOptions {
|
|
|
138
138
|
* **Note**: Use of refresh tokens must be enabled by an administrator on your Auth0 client application.
|
|
139
139
|
*/
|
|
140
140
|
useRefreshTokens?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* If true, fallback to the technique of using a hidden iframe and the `authorization_code` grant with `prompt=none` when unable to use refresh tokens.
|
|
143
|
+
* The default setting is `true`.
|
|
144
|
+
*
|
|
145
|
+
* **Note**: There might be situations where doing silent auth with a Web Message response from an iframe is not possible,
|
|
146
|
+
* like when you're serving your application from the file system or a custom protocol (like in a Desktop or Native app).
|
|
147
|
+
* In situations like this you can disable the iframe fallback and handle the failed Refresh Grant and prompt the user to login interactively with `loginWithRedirect` or `loginWithPopup`."
|
|
148
|
+
*
|
|
149
|
+
* E.g. Using the `file:` protocol in an Electron application does not support that legacy technique.
|
|
150
|
+
*
|
|
151
|
+
* let token: string;
|
|
152
|
+
* try {
|
|
153
|
+
* token = await auth0.getTokenSilently();
|
|
154
|
+
* } catch (e) {
|
|
155
|
+
* if (e.error === 'missing_refresh_token' || e.error === 'invalid_grant') {
|
|
156
|
+
* auth0.loginWithRedirect();
|
|
157
|
+
* }
|
|
158
|
+
* }
|
|
159
|
+
*/
|
|
160
|
+
useRefreshTokensFallback?: boolean;
|
|
141
161
|
/**
|
|
142
162
|
* A maximum number of seconds to wait before declaring background calls to /authorize as failed for timeout
|
|
143
163
|
* Defaults to 60s.
|
|
@@ -154,6 +174,9 @@ export interface Auth0ClientOptions extends BaseLoginOptions {
|
|
|
154
174
|
auth0Client?: {
|
|
155
175
|
name: string;
|
|
156
176
|
version: string;
|
|
177
|
+
env?: {
|
|
178
|
+
[key: string]: string;
|
|
179
|
+
};
|
|
157
180
|
};
|
|
158
181
|
/**
|
|
159
182
|
* Sets an additional cookie with no SameSite attribute to support legacy browsers
|
package/dist/typings/utils.d.ts
CHANGED
|
@@ -13,3 +13,10 @@ export declare const sha256: (s: string) => Promise<any>;
|
|
|
13
13
|
export declare const urlDecodeB64: (input: string) => string;
|
|
14
14
|
export declare const bufferToBase64UrlEncoded: (input: number[] | Uint8Array) => string;
|
|
15
15
|
export declare const validateCrypto: () => void;
|
|
16
|
+
/**
|
|
17
|
+
* Returns an empty string when value is falsy, or when it's value is included in the exclude argument.
|
|
18
|
+
* @param value The value to check
|
|
19
|
+
* @param exclude An array of values that should result in an empty string.
|
|
20
|
+
* @returns The value, or an empty string when falsy or included in the exclude argument.
|
|
21
|
+
*/
|
|
22
|
+
export declare function valueOrEmptyString(value: string, exclude?: string[]): string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "1.
|
|
1
|
+
declare const _default: "1.22.2";
|
|
2
2
|
export default _default;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "@auth0/auth0-spa-js",
|
|
4
4
|
"description": "Auth0 SDK for Single Page Applications using Authorization Code Grant Flow with PKCE",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"version": "1.
|
|
6
|
+
"version": "1.22.2",
|
|
7
7
|
"main": "dist/lib/auth0-spa-js.cjs.js",
|
|
8
8
|
"types": "dist/typings/index.d.ts",
|
|
9
9
|
"module": "dist/auth0-spa-js.production.esm.js",
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
"@typescript-eslint/parser": "^4.33.0",
|
|
41
41
|
"browserstack-cypress-cli": "1.8.1",
|
|
42
42
|
"cli-table": "^0.3.6",
|
|
43
|
-
"codecov": "^3.8.3",
|
|
44
43
|
"concurrently": "^6.4.0",
|
|
45
44
|
"cypress": "7.2.0",
|
|
46
45
|
"es-check": "^6.1.1",
|
|
@@ -71,7 +70,7 @@
|
|
|
71
70
|
"rollup-plugin-web-worker-loader": "^1.6.1",
|
|
72
71
|
"serve": "^12.0.1",
|
|
73
72
|
"ts-jest": "^27.0.7",
|
|
74
|
-
"tslib": "^2.
|
|
73
|
+
"tslib": "^2.4.0",
|
|
75
74
|
"tslint": "^6.1.3",
|
|
76
75
|
"tslint-config-security": "^1.16.0",
|
|
77
76
|
"typedoc": "0.18.0",
|
|
@@ -81,9 +80,9 @@
|
|
|
81
80
|
"dependencies": {
|
|
82
81
|
"abortcontroller-polyfill": "^1.7.3",
|
|
83
82
|
"browser-tabs-lock": "^1.2.15",
|
|
84
|
-
"core-js": "^3.
|
|
83
|
+
"core-js": "^3.23.2",
|
|
85
84
|
"es-cookie": "^1.3.2",
|
|
86
|
-
"fast-text-encoding": "^1.0.
|
|
85
|
+
"fast-text-encoding": "^1.0.4",
|
|
87
86
|
"promise-polyfill": "^8.2.3",
|
|
88
87
|
"unfetch": "^4.2.0"
|
|
89
88
|
},
|
package/src/Auth0Client.ts
CHANGED
|
@@ -27,7 +27,12 @@ import {
|
|
|
27
27
|
|
|
28
28
|
import TransactionManager from './transaction-manager';
|
|
29
29
|
import { verify as verifyIdToken } from './jwt';
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
AuthenticationError,
|
|
32
|
+
GenericError,
|
|
33
|
+
MissingRefreshTokenError,
|
|
34
|
+
TimeoutError
|
|
35
|
+
} from './errors';
|
|
31
36
|
|
|
32
37
|
import {
|
|
33
38
|
ClientStorage,
|
|
@@ -170,14 +175,17 @@ const getCustomInitialOptions = (
|
|
|
170
175
|
auth0Client,
|
|
171
176
|
authorizeTimeoutInSeconds,
|
|
172
177
|
cacheLocation,
|
|
178
|
+
cache,
|
|
173
179
|
client_id,
|
|
174
180
|
domain,
|
|
175
181
|
issuer,
|
|
176
182
|
leeway,
|
|
177
183
|
max_age,
|
|
184
|
+
nowProvider,
|
|
178
185
|
redirect_uri,
|
|
179
186
|
scope,
|
|
180
187
|
useRefreshTokens,
|
|
188
|
+
useRefreshTokensFallback,
|
|
181
189
|
useCookiesForTransactions,
|
|
182
190
|
useFormData,
|
|
183
191
|
...customParams
|
|
@@ -202,6 +210,7 @@ export default class Auth0Client {
|
|
|
202
210
|
private readonly isAuthenticatedCookieName: string;
|
|
203
211
|
private readonly nowProvider: () => number | Promise<number>;
|
|
204
212
|
private readonly httpTimeoutMs: number;
|
|
213
|
+
private readonly useRefreshTokensFallback: boolean;
|
|
205
214
|
|
|
206
215
|
cacheLocation: CacheLocation;
|
|
207
216
|
private worker: Worker;
|
|
@@ -299,6 +308,9 @@ export default class Auth0Client {
|
|
|
299
308
|
}
|
|
300
309
|
|
|
301
310
|
this.customOptions = getCustomInitialOptions(options);
|
|
311
|
+
|
|
312
|
+
this.useRefreshTokensFallback =
|
|
313
|
+
this.options.useRefreshTokensFallback !== false;
|
|
302
314
|
}
|
|
303
315
|
|
|
304
316
|
private _url(path: string) {
|
|
@@ -1183,7 +1195,14 @@ export default class Auth0Client {
|
|
|
1183
1195
|
// and you don't have a refresh token in web worker memory
|
|
1184
1196
|
// fallback to an iframe.
|
|
1185
1197
|
if ((!cache || !cache.refresh_token) && !this.worker) {
|
|
1186
|
-
|
|
1198
|
+
if (this.useRefreshTokensFallback) {
|
|
1199
|
+
return await this._getTokenFromIFrame(options);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
throw new MissingRefreshTokenError(
|
|
1203
|
+
options.audience || 'default',
|
|
1204
|
+
options.scope
|
|
1205
|
+
);
|
|
1187
1206
|
}
|
|
1188
1207
|
|
|
1189
1208
|
const redirect_uri =
|
|
@@ -1230,11 +1249,12 @@ export default class Auth0Client {
|
|
|
1230
1249
|
if (
|
|
1231
1250
|
// The web worker didn't have a refresh token in memory so
|
|
1232
1251
|
// fallback to an iframe.
|
|
1233
|
-
e.message
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1252
|
+
(e.message.indexOf(MISSING_REFRESH_TOKEN_ERROR_MESSAGE) > -1 ||
|
|
1253
|
+
// A refresh token was found, but is it no longer valid.
|
|
1254
|
+
// Fallback to an iframe.
|
|
1255
|
+
(e.message &&
|
|
1256
|
+
e.message.indexOf(INVALID_REFRESH_TOKEN_ERROR_MESSAGE) > -1)) &&
|
|
1257
|
+
this.useRefreshTokensFallback
|
|
1238
1258
|
) {
|
|
1239
1259
|
return await this._getTokenFromIFrame(options);
|
|
1240
1260
|
}
|
package/src/constants.ts
CHANGED
|
@@ -34,8 +34,7 @@ export const CACHE_LOCATION_LOCAL_STORAGE = 'localstorage';
|
|
|
34
34
|
/**
|
|
35
35
|
* @ignore
|
|
36
36
|
*/
|
|
37
|
-
export const MISSING_REFRESH_TOKEN_ERROR_MESSAGE =
|
|
38
|
-
'The web worker is missing the refresh token';
|
|
37
|
+
export const MISSING_REFRESH_TOKEN_ERROR_MESSAGE = 'Missing Refresh Token';
|
|
39
38
|
|
|
40
39
|
/**
|
|
41
40
|
* @ignore
|
package/src/errors.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* https://github.com/gotwarlost/istanbul/issues/690
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { valueOrEmptyString } from './utils';
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Thrown when network requests to the Auth server fail.
|
|
8
10
|
*/
|
|
@@ -91,3 +93,16 @@ export class MfaRequiredError extends GenericError {
|
|
|
91
93
|
Object.setPrototypeOf(this, MfaRequiredError.prototype);
|
|
92
94
|
}
|
|
93
95
|
}
|
|
96
|
+
|
|
97
|
+
export class MissingRefreshTokenError extends GenericError {
|
|
98
|
+
/* istanbul ignore next */
|
|
99
|
+
constructor(public audience: string, public scope: string) {
|
|
100
|
+
super(
|
|
101
|
+
'missing_refresh_token',
|
|
102
|
+
`Missing Refresh Token (audience: '${valueOrEmptyString(audience, [
|
|
103
|
+
'default'
|
|
104
|
+
])}', scope: '${valueOrEmptyString(scope)}')`
|
|
105
|
+
);
|
|
106
|
+
Object.setPrototypeOf(this, MissingRefreshTokenError.prototype);
|
|
107
|
+
}
|
|
108
|
+
}
|
package/src/global.ts
CHANGED
|
@@ -45,7 +45,7 @@ export interface BaseLoginOptions {
|
|
|
45
45
|
*
|
|
46
46
|
* This only affects the New Universal Login Experience.
|
|
47
47
|
*/
|
|
48
|
-
screen_hint?: string;
|
|
48
|
+
screen_hint?: 'signup' | 'login' | string;
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* The user's email address or other identifier. When your app knows
|
|
@@ -158,6 +158,27 @@ export interface Auth0ClientOptions extends BaseLoginOptions {
|
|
|
158
158
|
*/
|
|
159
159
|
useRefreshTokens?: boolean;
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* If true, fallback to the technique of using a hidden iframe and the `authorization_code` grant with `prompt=none` when unable to use refresh tokens.
|
|
163
|
+
* The default setting is `true`.
|
|
164
|
+
*
|
|
165
|
+
* **Note**: There might be situations where doing silent auth with a Web Message response from an iframe is not possible,
|
|
166
|
+
* like when you're serving your application from the file system or a custom protocol (like in a Desktop or Native app).
|
|
167
|
+
* In situations like this you can disable the iframe fallback and handle the failed Refresh Grant and prompt the user to login interactively with `loginWithRedirect` or `loginWithPopup`."
|
|
168
|
+
*
|
|
169
|
+
* E.g. Using the `file:` protocol in an Electron application does not support that legacy technique.
|
|
170
|
+
*
|
|
171
|
+
* let token: string;
|
|
172
|
+
* try {
|
|
173
|
+
* token = await auth0.getTokenSilently();
|
|
174
|
+
* } catch (e) {
|
|
175
|
+
* if (e.error === 'missing_refresh_token' || e.error === 'invalid_grant') {
|
|
176
|
+
* auth0.loginWithRedirect();
|
|
177
|
+
* }
|
|
178
|
+
* }
|
|
179
|
+
*/
|
|
180
|
+
useRefreshTokensFallback?: boolean;
|
|
181
|
+
|
|
161
182
|
/**
|
|
162
183
|
* A maximum number of seconds to wait before declaring background calls to /authorize as failed for timeout
|
|
163
184
|
* Defaults to 60s.
|
|
@@ -173,7 +194,11 @@ export interface Auth0ClientOptions extends BaseLoginOptions {
|
|
|
173
194
|
* Internal property to send information about the client to the authorization server.
|
|
174
195
|
* @internal
|
|
175
196
|
*/
|
|
176
|
-
auth0Client?: {
|
|
197
|
+
auth0Client?: {
|
|
198
|
+
name: string;
|
|
199
|
+
version: string;
|
|
200
|
+
env?: { [key: string]: string };
|
|
201
|
+
};
|
|
177
202
|
|
|
178
203
|
/**
|
|
179
204
|
* Sets an additional cookie with no SameSite attribute to support legacy browsers
|
package/src/utils.ts
CHANGED
|
@@ -241,3 +241,13 @@ export const validateCrypto = () => {
|
|
|
241
241
|
`);
|
|
242
242
|
}
|
|
243
243
|
};
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Returns an empty string when value is falsy, or when it's value is included in the exclude argument.
|
|
247
|
+
* @param value The value to check
|
|
248
|
+
* @param exclude An array of values that should result in an empty string.
|
|
249
|
+
* @returns The value, or an empty string when falsy or included in the exclude argument.
|
|
250
|
+
*/
|
|
251
|
+
export function valueOrEmptyString(value: string, exclude: string[] = []) {
|
|
252
|
+
return value && !exclude.includes(value) ? value : '';
|
|
253
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.
|
|
1
|
+
export default '1.22.2';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MissingRefreshTokenError } from '../errors';
|
|
2
2
|
import { WorkerRefreshTokenMessage } from './worker.types';
|
|
3
3
|
|
|
4
4
|
let refreshTokens: Record<string, string> = {};
|
|
@@ -50,7 +50,7 @@ const messageHandler = async ({
|
|
|
50
50
|
const refreshToken = getRefreshToken(audience, scope);
|
|
51
51
|
|
|
52
52
|
if (!refreshToken) {
|
|
53
|
-
throw new
|
|
53
|
+
throw new MissingRefreshTokenError(audience, scope);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
fetchOptions.body = useFormData
|