@auth0/auth0-spa-js
Advanced tools
Comparing version 1.10.0 to 1.11.0
# Change Log | ||
## [v1.11.0](https://github.com/auth0/auth0-spa-js/tree/v1.11.0) (2020-07-21) | ||
[Full Changelog](https://github.com/auth0/auth0-spa-js/compare/v1.10.0...v1.11.0) | ||
**Added** | ||
- [SDK-1560] Allow issuer as url [\#523](https://github.com/auth0/auth0-spa-js/pull/523) ([adamjmcgrath](https://github.com/adamjmcgrath)) | ||
- [SDK-1790] use refresh_tokens with multiple audiences [\#521](https://github.com/auth0/auth0-spa-js/pull/521) ([adamjmcgrath](https://github.com/adamjmcgrath)) | ||
- [SDK-1650] Add `message` to errors that don't have one [\#520](https://github.com/auth0/auth0-spa-js/pull/520) ([adamjmcgrath](https://github.com/adamjmcgrath)) | ||
**Fixed** | ||
- [SDK-1798] prevent unnecessary token requests [\#525](https://github.com/auth0/auth0-spa-js/pull/525) ([adamjmcgrath](https://github.com/adamjmcgrath)) | ||
- [SDK-1789] Add custom initial options to the 2 getToken methods [\#524](https://github.com/auth0/auth0-spa-js/pull/524) ([adamjmcgrath](https://github.com/adamjmcgrath)) | ||
## [v1.10.0](https://github.com/auth0/auth0-spa-js/tree/v1.10.0) (2020-06-17) | ||
@@ -4,0 +19,0 @@ |
@@ -9,2 +9,3 @@ import { Auth0ClientOptions, RedirectLoginOptions, PopupLoginOptions, PopupConfigOptions, GetUserOptions, GetIdTokenClaimsOptions, RedirectLoginResult, GetTokenSilentlyOptions, GetTokenWithPopupOptions, LogoutOptions, CacheLocation } from './global'; | ||
private transactionManager; | ||
private customOptions; | ||
private domainUrl; | ||
@@ -11,0 +12,0 @@ private tokenIssuer; |
@@ -5,2 +5,6 @@ export declare class GenericError extends Error { | ||
constructor(error: string, error_description: string); | ||
static fromPayload({ error, error_description }: { | ||
error: any; | ||
error_description: any; | ||
}): GenericError; | ||
} | ||
@@ -12,1 +16,8 @@ export declare class AuthenticationError extends GenericError { | ||
} | ||
export declare class TimeoutError extends GenericError { | ||
constructor(); | ||
} | ||
export declare class PopupTimeoutError extends TimeoutError { | ||
popup: Window; | ||
constructor(popup: Window); | ||
} |
@@ -310,2 +310,4 @@ /** | ||
redirect_uri: string; | ||
audience: string; | ||
scope: string; | ||
} | ||
@@ -312,0 +314,0 @@ /** |
@@ -13,6 +13,6 @@ import { AuthenticationResult, PopupConfigOptions, TokenEndpointOptions } from './global'; | ||
export declare const bufferToBase64UrlEncoded: (input: any) => string; | ||
export declare const fetchWithTimeout: (url: any, options: any, worker: any, timeout?: number) => Promise<unknown>; | ||
export declare const oauthToken: ({ baseUrl, timeout, ...options }: TokenEndpointOptions, worker: any) => Promise<any>; | ||
export declare const fetchWithTimeout: (url: any, audience: any, scope: any, options: any, worker: any, timeout?: number) => Promise<unknown>; | ||
export declare const oauthToken: ({ baseUrl, timeout, audience, scope, ...options }: TokenEndpointOptions, worker: any) => Promise<any>; | ||
export declare const getCrypto: () => Crypto; | ||
export declare const getCryptoSubtle: () => any; | ||
export declare const validateCrypto: () => void; |
@@ -1,2 +0,2 @@ | ||
declare const _default: "1.10.0"; | ||
declare const _default: "1.11.0"; | ||
export default _default; |
@@ -6,3 +6,3 @@ { | ||
"license": "MIT", | ||
"version": "1.10.0", | ||
"version": "1.11.0", | ||
"main": "dist/lib/auth0-spa-js.cjs.js", | ||
@@ -42,3 +42,3 @@ "types": "dist/typings/index.d.ts", | ||
"concurrently": "^5.1.0", | ||
"cypress": "^4.3.0", | ||
"cypress": "^4.10.0", | ||
"es-check": "^5.1.0", | ||
@@ -50,2 +50,3 @@ "eslint": "^6.8.0", | ||
"jest": "^24.9.0", | ||
"jest-junit": "^11.0.1", | ||
"jest-localstorage-mock": "^2.4.0", | ||
@@ -68,3 +69,3 @@ "jsonwebtoken": "^8.5.1", | ||
"rollup-plugin-web-worker-loader": "^1.1.3", | ||
"serve": "^11.3.0", | ||
"serve": "^11.3.2", | ||
"ts-jest": "^24.3.0", | ||
@@ -71,0 +72,0 @@ "tslint": "^6.1.1", |
@@ -86,2 +86,37 @@ import Lock from 'browser-tabs-lock'; | ||
/** | ||
* @ignore | ||
*/ | ||
const getTokenIssuer = (issuer, domainUrl) => { | ||
if (issuer) { | ||
return issuer.startsWith('https://') ? issuer : `https://${issuer}/`; | ||
} | ||
return `${domainUrl}/`; | ||
}; | ||
/** | ||
* @ignore | ||
*/ | ||
const getCustomInitialOptions = ( | ||
options: Auth0ClientOptions | ||
): BaseLoginOptions => { | ||
const { | ||
advancedOptions, | ||
audience, | ||
auth0Client, | ||
authorizeTimeoutInSeconds, | ||
cacheLocation, | ||
client_id, | ||
domain, | ||
issuer, | ||
leeway, | ||
max_age, | ||
redirect_uri, | ||
scope, | ||
useRefreshTokens, | ||
...customParams | ||
} = options; | ||
return customParams; | ||
}; | ||
/** | ||
* Auth0 SDK for Single Page Applications using [Authorization Code Grant Flow with PKCE](https://auth0.com/docs/api-auth/tutorials/authorization-code-grant-pkce). | ||
@@ -92,2 +127,3 @@ */ | ||
private transactionManager: TransactionManager; | ||
private customOptions: BaseLoginOptions; | ||
private domainUrl: string; | ||
@@ -113,7 +149,4 @@ private tokenIssuer: string; | ||
this.domainUrl = `https://${this.options.domain}`; | ||
this.tokenIssuer = getTokenIssuer(this.options.issuer, this.domainUrl); | ||
this.tokenIssuer = this.options.issuer | ||
? `https://${this.options.issuer}/` | ||
: `${this.domainUrl}/`; | ||
this.defaultScope = getUniqueScopes( | ||
@@ -143,2 +176,4 @@ 'openid', | ||
} | ||
this.customOptions = getCustomInitialOptions(options); | ||
} | ||
@@ -314,2 +349,4 @@ | ||
{ | ||
audience: params.audience, | ||
scope: params.scope, | ||
baseUrl: this.domainUrl, | ||
@@ -448,2 +485,4 @@ client_id: this.options.client_id, | ||
const tokenOptions = { | ||
audience: transaction.audience, | ||
scope: transaction.scope, | ||
baseUrl: this.domainUrl, | ||
@@ -553,2 +592,4 @@ client_id: this.options.client_id, | ||
try { | ||
await lock.acquireLock(GET_TOKEN_SILENTLY_LOCK_KEY, 5000); | ||
if (!ignoreCache) { | ||
@@ -565,2 +606,3 @@ const cache = this.cache.get( | ||
if (cache && cache.access_token) { | ||
await lock.releaseLock(GET_TOKEN_SILENTLY_LOCK_KEY); | ||
return cache.access_token; | ||
@@ -570,12 +612,6 @@ } | ||
await lock.acquireLock(GET_TOKEN_SILENTLY_LOCK_KEY, 5000); | ||
const authResult = this.options.useRefreshTokens | ||
? await this._getTokenUsingRefreshToken(getTokenOptions) | ||
: await this._getTokenFromIFrame(getTokenOptions); | ||
// Only get an access token using a refresh token if: | ||
// * refresh tokens are enabled | ||
// * no audience has been specified to getTokenSilently (we can only get a token for a new audience when using an iframe) | ||
const authResult = | ||
this.options.useRefreshTokens && !options.audience | ||
? await this._getTokenUsingRefreshToken(getTokenOptions) | ||
: await this._getTokenFromIFrame(getTokenOptions); | ||
this.cache.save({ client_id: this.options.client_id, ...authResult }); | ||
@@ -731,3 +767,6 @@ | ||
{ | ||
...this.customOptions, | ||
...customOptions, | ||
scope, | ||
audience, | ||
baseUrl: this.domainUrl, | ||
@@ -793,3 +832,6 @@ client_id: this.options.client_id, | ||
{ | ||
...this.customOptions, | ||
...customOptions, | ||
audience, | ||
scope, | ||
baseUrl: this.domainUrl, | ||
@@ -796,0 +838,0 @@ client_id: this.options.client_id, |
@@ -7,3 +7,8 @@ export class GenericError extends Error { | ||
} | ||
static fromPayload({ error, error_description }) { | ||
return new GenericError(error, error_description); | ||
} | ||
} | ||
export class AuthenticationError extends GenericError { | ||
@@ -21,1 +26,17 @@ constructor( | ||
} | ||
export class TimeoutError extends GenericError { | ||
constructor() { | ||
super('timeout', 'Timeout'); | ||
//https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, TimeoutError.prototype); | ||
} | ||
} | ||
export class PopupTimeoutError extends TimeoutError { | ||
constructor(public popup: Window) { | ||
super(); | ||
//https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work | ||
Object.setPrototypeOf(this, PopupTimeoutError.prototype); | ||
} | ||
} |
@@ -340,2 +340,4 @@ /** | ||
redirect_uri: string; | ||
audience: string; | ||
scope: string; | ||
} | ||
@@ -342,0 +344,0 @@ |
import { MISSING_REFRESH_TOKEN_ERROR_MESSAGE } from './constants'; | ||
/** | ||
* @ignore | ||
*/ | ||
let refreshToken; | ||
let refreshTokens = {}; | ||
/** | ||
* @ignore | ||
*/ | ||
const cacheKey = (audience, scope) => `${audience}|${scope}`; | ||
const getRefreshToken = (audience, scope) => | ||
refreshTokens[cacheKey(audience, scope)]; | ||
const setRefreshToken = (refreshToken, audience, scope) => | ||
(refreshTokens[cacheKey(audience, scope)] = refreshToken); | ||
const deleteRefreshToken = (audience, scope) => | ||
delete refreshTokens[cacheKey(audience, scope)]; | ||
const wait: any = time => new Promise(resolve => setTimeout(resolve, time)); | ||
/** | ||
* @ignore | ||
*/ | ||
const messageHandler = async ({ | ||
data: { url, timeout, ...opts }, | ||
data: { url, timeout, audience, scope, ...opts }, | ||
ports: [port] | ||
@@ -24,2 +26,3 @@ }) => { | ||
if (!body.refresh_token && body.grant_type === 'refresh_token') { | ||
const refreshToken = getRefreshToken(audience, scope); | ||
if (!refreshToken) { | ||
@@ -57,6 +60,6 @@ throw new Error(MISSING_REFRESH_TOKEN_ERROR_MESSAGE); | ||
if (json.refresh_token) { | ||
refreshToken = json.refresh_token; | ||
setRefreshToken(json.refresh_token, audience, scope); | ||
delete json.refresh_token; | ||
} else { | ||
refreshToken = null; | ||
deleteRefreshToken(audience, scope); | ||
} | ||
@@ -63,0 +66,0 @@ |
@@ -16,3 +16,3 @@ import fetch from 'unfetch'; | ||
const TIMEOUT_ERROR = { error: 'timeout', error_description: 'Timeout' }; | ||
import { PopupTimeoutError, TimeoutError, GenericError } from './errors'; | ||
@@ -58,3 +58,3 @@ export const createAbortController = () => new AbortController(); | ||
const timeoutSetTimeoutId = setTimeout(() => { | ||
rej(TIMEOUT_ERROR); | ||
rej(new TimeoutError()); | ||
removeIframe(); | ||
@@ -70,3 +70,5 @@ }, timeoutInSeconds * 1000); | ||
} | ||
e.data.response.error ? rej(e.data.response) : res(e.data.response); | ||
e.data.response.error | ||
? rej(GenericError.fromPayload(e.data.response)) | ||
: res(e.data.response); | ||
clearTimeout(timeoutSetTimeoutId); | ||
@@ -112,3 +114,3 @@ window.removeEventListener('message', iframeEventHandler, false); | ||
const timeoutId = setTimeout(() => { | ||
reject({ ...TIMEOUT_ERROR, popup }); | ||
reject(new PopupTimeoutError(popup)); | ||
}, (config.timeoutInSeconds || DEFAULT_AUTHORIZE_TIMEOUT_IN_SECONDS) * 1000); | ||
@@ -122,3 +124,3 @@ window.addEventListener('message', e => { | ||
if (e.data.response.error) { | ||
return reject(e.data.response); | ||
return reject(GenericError.fromPayload(e.data.response)); | ||
} | ||
@@ -223,7 +225,7 @@ resolve(e.data.response); | ||
const switchFetch = async (url, opts, timeout, worker) => { | ||
const switchFetch = async (url, audience, scope, opts, timeout, worker) => { | ||
if (worker) { | ||
// AbortSignal is not serializable, need to implement in the Web Worker | ||
delete opts.signal; | ||
return sendMessage({ url, timeout, ...opts }, worker); | ||
return sendMessage({ url, audience, scope, timeout, ...opts }, worker); | ||
} else { | ||
@@ -240,2 +242,4 @@ const response = await fetch(url, opts); | ||
url, | ||
audience, | ||
scope, | ||
options, | ||
@@ -256,3 +260,3 @@ worker, | ||
return Promise.race([ | ||
switchFetch(url, fetchOptions, timeout, worker), | ||
switchFetch(url, audience, scope, fetchOptions, timeout, worker), | ||
new Promise((_, reject) => { | ||
@@ -269,3 +273,3 @@ timeoutId = setTimeout(() => { | ||
const getJSON = async (url, timeout, options, worker) => { | ||
const getJSON = async (url, timeout, audience, scope, options, worker) => { | ||
let fetchError, response; | ||
@@ -275,3 +279,10 @@ | ||
try { | ||
response = await fetchWithTimeout(url, options, worker, timeout); | ||
response = await fetchWithTimeout( | ||
url, | ||
audience, | ||
scope, | ||
options, | ||
worker, | ||
timeout | ||
); | ||
fetchError = null; | ||
@@ -289,2 +300,5 @@ break; | ||
if (fetchError) { | ||
// unfetch uses XMLHttpRequest under the hood which throws | ||
// ProgressEvents on error, which don't have message properties | ||
fetchError.message = fetchError.message || 'Failed to fetch'; | ||
throw fetchError; | ||
@@ -313,3 +327,3 @@ } | ||
export const oauthToken = async ( | ||
{ baseUrl, timeout, ...options }: TokenEndpointOptions, | ||
{ baseUrl, timeout, audience, scope, ...options }: TokenEndpointOptions, | ||
worker | ||
@@ -320,2 +334,4 @@ ) => | ||
timeout, | ||
audience || 'default', | ||
scope, | ||
{ | ||
@@ -322,0 +338,0 @@ method: 'POST', |
@@ -1,1 +0,1 @@ | ||
export default '1.10.0'; | ||
export default '1.11.0'; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
1801695
11215
40