UNPKG

@auth0/auth0-vue

Version:

Auth0 SDK for Vue Applications using Authorization Code Grant Flow with PKCE

345 lines (335 loc) 13.1 kB
'use strict'; var vue = require('vue'); var auth0SpaJs = require('@auth0/auth0-spa-js'); /** * @ignore */ const AUTH0_TOKEN = '$auth0'; /** * Injection token used to `provide` the `Auth0VueClient` instance. Can be used to pass to `inject()` * * ```js * inject(AUTH0_INJECTION_KEY) * ``` */ const AUTH0_INJECTION_KEY = Symbol(AUTH0_TOKEN); var version = '2.3.1'; /* eslint-disable @typescript-eslint/no-explicit-any */ /** * @ignore * Run watchEffect untill the watcher returns true, then stop the watch. * Once it returns true, the promise will resolve. */ function watchEffectOnceAsync(watcher) { return new Promise(resolve => { watchEffectOnce(watcher, resolve); }); } /** * @ignore * Run watchEffect untill the watcher returns true, then stop the watch. * Once it returns true, it will call the provided function. */ function watchEffectOnce(watcher, fn) { const stopWatch = vue.watchEffect(() => { if (watcher()) { fn(); stopWatch(); } }); } /** * @ignore * Helper function to bind methods to itself, useful when using Vue's `provide` / `inject` API's. */ function bindPluginMethods(plugin, exclude) { Object.getOwnPropertyNames(Object.getPrototypeOf(plugin)) .filter(method => !exclude.includes(method)) // eslint-disable-next-line security/detect-object-injection .forEach(method => (plugin[method] = plugin[method].bind(plugin))); } /** * @ignore * Helper function to map the v1 `redirect_uri` option to the v2 `authorizationParams.redirect_uri` * and log a warning. */ function deprecateRedirectUri(options) { if (options === null || options === void 0 ? void 0 : options.redirect_uri) { console.warn('Using `redirect_uri` has been deprecated, please use `authorizationParams.redirect_uri` instead as `redirectUri` will be no longer supported in a future version'); options.authorizationParams = options.authorizationParams || {}; options.authorizationParams.redirect_uri = options.redirect_uri; delete options.redirect_uri; } } /** * Helper callback that's used by default before the plugin is installed. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any const PLUGIN_NOT_INSTALLED_HANDLER = () => { console.error(`Please ensure Auth0's Vue plugin is correctly installed.`); }; /** * Helper client that's used by default before the plugin is installed. */ const PLUGIN_NOT_INSTALLED_CLIENT = { isLoading: vue.ref(false), isAuthenticated: vue.ref(false), user: vue.ref(undefined), idTokenClaims: vue.ref(undefined), error: vue.ref(null), loginWithPopup: PLUGIN_NOT_INSTALLED_HANDLER, loginWithRedirect: PLUGIN_NOT_INSTALLED_HANDLER, loginWithCustomTokenExchange: PLUGIN_NOT_INSTALLED_HANDLER, getAccessTokenSilently: PLUGIN_NOT_INSTALLED_HANDLER, getAccessTokenWithPopup: PLUGIN_NOT_INSTALLED_HANDLER, logout: PLUGIN_NOT_INSTALLED_HANDLER, checkSession: PLUGIN_NOT_INSTALLED_HANDLER, handleRedirectCallback: PLUGIN_NOT_INSTALLED_HANDLER, getDpopNonce: PLUGIN_NOT_INSTALLED_HANDLER, setDpopNonce: PLUGIN_NOT_INSTALLED_HANDLER, generateDpopProof: PLUGIN_NOT_INSTALLED_HANDLER, createFetcher: PLUGIN_NOT_INSTALLED_HANDLER, mfa: { setMFAAuthDetails: PLUGIN_NOT_INSTALLED_HANDLER, getAuthenticators: PLUGIN_NOT_INSTALLED_HANDLER, enroll: PLUGIN_NOT_INSTALLED_HANDLER, challenge: PLUGIN_NOT_INSTALLED_HANDLER, verify: PLUGIN_NOT_INSTALLED_HANDLER, getEnrollmentFactors: PLUGIN_NOT_INSTALLED_HANDLER }, passkey: { signup: PLUGIN_NOT_INSTALLED_HANDLER, login: PLUGIN_NOT_INSTALLED_HANDLER }, myAccount: { getFactors: PLUGIN_NOT_INSTALLED_HANDLER, getAuthenticationMethods: PLUGIN_NOT_INSTALLED_HANDLER, getAuthenticationMethod: PLUGIN_NOT_INSTALLED_HANDLER, updateAuthenticationMethod: PLUGIN_NOT_INSTALLED_HANDLER, deleteAuthenticationMethod: PLUGIN_NOT_INSTALLED_HANDLER, enrollmentChallenge: PLUGIN_NOT_INSTALLED_HANDLER, enrollmentVerify: PLUGIN_NOT_INSTALLED_HANDLER } }; /** * @ignore */ const client = vue.ref( // eslint-disable-next-line @typescript-eslint/no-explicit-any PLUGIN_NOT_INSTALLED_CLIENT); /** * @ignore */ class Auth0Plugin { constructor(clientOptions, pluginOptions) { this.clientOptions = clientOptions; this.pluginOptions = pluginOptions; this.isLoading = vue.ref(true); this.isAuthenticated = vue.ref(false); this.user = vue.ref({}); this.idTokenClaims = vue.ref(); this.error = vue.ref(null); this.mfa = PLUGIN_NOT_INSTALLED_CLIENT.mfa; this.passkey = PLUGIN_NOT_INSTALLED_CLIENT.passkey; this.myAccount = PLUGIN_NOT_INSTALLED_CLIENT.myAccount; // Vue Plugins can have issues when passing around the instance to `provide` // Therefor we need to bind all methods correctly to `this`. bindPluginMethods(this, ['constructor']); } install(app) { this._client = new auth0SpaJs.Auth0Client(Object.assign(Object.assign({}, this.clientOptions), { auth0Client: { name: 'auth0-vue', version: version } })); this.mfa = this._client.mfa; this.myAccount = this._client.myAccount; const passkeyClient = this._client.passkey; this.passkey = { signup: (options) => this.__proxy(() => passkeyClient.signup(options)), login: (options) => this.__proxy(() => passkeyClient.login(options)) }; this.__checkSession(app.config.globalProperties.$router); // eslint-disable-next-line security/detect-object-injection app.config.globalProperties[AUTH0_TOKEN] = this; app.provide(AUTH0_INJECTION_KEY, this); client.value = this; } async loginWithRedirect(options) { deprecateRedirectUri(options); return this._client.loginWithRedirect(options); } async loginWithPopup(options, config) { deprecateRedirectUri(options); return this.__proxy(() => this._client.loginWithPopup(options, config)); } async logout(options) { if ((options === null || options === void 0 ? void 0 : options.openUrl) || (options === null || options === void 0 ? void 0 : options.openUrl) === false) { return this.__proxy(() => this._client.logout(options)); } return this._client.logout(options); } /* istanbul ignore next */ async getAccessTokenSilently(options = {}) { deprecateRedirectUri(options); return this.__proxy(() => this._client.getTokenSilently(options)); } async getAccessTokenWithPopup(options, config) { deprecateRedirectUri(options); return this.__proxy(() => this._client.getTokenWithPopup(options, config)); } async loginWithCustomTokenExchange(options) { return this.__proxy(() => this._client.loginWithCustomTokenExchange(options)); } async checkSession(options) { return this.__proxy(() => this._client.checkSession(options)); } async handleRedirectCallback(url) { return this.__proxy(() => this._client.handleRedirectCallback(url)); } async getDpopNonce(id) { return this.__proxy(() => this._client.getDpopNonce(id)); } async setDpopNonce(nonce, id) { return this.__proxy(() => this._client.setDpopNonce(nonce, id)); } async generateDpopProof(params) { return this.__proxy(() => this._client.generateDpopProof(params)); } createFetcher(config) { return this._client.createFetcher(config); } async __checkSession(router) { var _a, _b; const search = window.location.search; try { if ((search.includes('code=') || search.includes('error=')) && search.includes('state=') && !((_a = this.pluginOptions) === null || _a === void 0 ? void 0 : _a.skipRedirectCallback)) { const result = await this.handleRedirectCallback(); const appState = result === null || result === void 0 ? void 0 : result.appState; const appStateTarget = appState === null || appState === void 0 ? void 0 : appState.target; const target = appStateTarget !== null && appStateTarget !== void 0 ? appStateTarget : '/'; if (router) { window.history.replaceState({}, '', window.location.pathname); router.push(target); } else { window.history.replaceState({}, '', appStateTarget !== null && appStateTarget !== void 0 ? appStateTarget : window.location.pathname); } return result; } else { await this.checkSession(); } } catch (e) { // __checkSession should never throw an exception as it will fail installing the plugin. // Instead, errors during __checkSession are propagated using the errors property on `useAuth0`. window.history.replaceState({}, '', '/'); if (router) { router.push(((_b = this.pluginOptions) === null || _b === void 0 ? void 0 : _b.errorPath) || '/'); } } } async __refreshState() { this.isAuthenticated.value = await this._client.isAuthenticated(); this.user.value = await this._client.getUser(); this.idTokenClaims.value = await this._client.getIdTokenClaims(); this.isLoading.value = false; } async __proxy(cb, refreshState = true) { let result; try { result = await cb(); this.error.value = null; } catch (e) { this.error.value = e; throw e; } finally { if (refreshState) { await this.__refreshState(); } } return result; } } async function createGuardHandler(client, to, redirectLoginOptions) { const fn = async () => { if (vue.unref(client.isAuthenticated)) { return true; } await client.loginWithRedirect(Object.assign(Object.assign({}, redirectLoginOptions), { appState: Object.assign({ target: to.fullPath }, redirectLoginOptions === null || redirectLoginOptions === void 0 ? void 0 : redirectLoginOptions.appState) })); return false; }; if (!vue.unref(client.isLoading)) { return fn(); } await watchEffectOnceAsync(() => !vue.unref(client.isLoading)); return fn(); } function createAuthGuard(appOrOptions) { const { app, redirectLoginOptions } = !appOrOptions || 'config' in appOrOptions ? { app: appOrOptions, redirectLoginOptions: undefined } : appOrOptions; return async (to) => { // eslint-disable-next-line security/detect-object-injection const auth0 = app ? app.config.globalProperties[AUTH0_TOKEN] : vue.unref(client); return createGuardHandler(auth0, to, redirectLoginOptions); }; } async function authGuard(to) { const auth0 = vue.unref(client); return createGuardHandler(auth0, to); } /** * Creates the Auth0 plugin. * * @param clientOptions The Auth Vue Client Options * @param pluginOptions Additional Plugin Configuration Options * @returns An instance of Auth0Plugin */ function createAuth0(clientOptions, pluginOptions) { deprecateRedirectUri(clientOptions); return new Auth0Plugin(clientOptions, pluginOptions); } /** * Returns the registered Auth0 instance using Vue's `inject`. * @returns An instance of Auth0VueClient */ function useAuth0() { return vue.inject(AUTH0_INJECTION_KEY); } var Auth0Vue = /*#__PURE__*/Object.freeze({ __proto__: null, createAuth0: createAuth0, useAuth0: useAuth0, AUTH0_INJECTION_KEY: AUTH0_INJECTION_KEY, Auth0Plugin: Auth0Plugin, User: auth0SpaJs.User, InMemoryCache: auth0SpaJs.InMemoryCache, LocalStorageCache: auth0SpaJs.LocalStorageCache, UseDpopNonceError: auth0SpaJs.UseDpopNonceError, MfaRequiredError: auth0SpaJs.MfaRequiredError, MfaError: auth0SpaJs.MfaError, MfaListAuthenticatorsError: auth0SpaJs.MfaListAuthenticatorsError, MfaEnrollmentError: auth0SpaJs.MfaEnrollmentError, MfaChallengeError: auth0SpaJs.MfaChallengeError, MfaVerifyError: auth0SpaJs.MfaVerifyError, MfaEnrollmentFactorsError: auth0SpaJs.MfaEnrollmentFactorsError, PasskeyError: auth0SpaJs.PasskeyError, PasskeyRegisterError: auth0SpaJs.PasskeyRegisterError, PasskeyChallengeError: auth0SpaJs.PasskeyChallengeError, PasskeyGetTokenError: auth0SpaJs.PasskeyGetTokenError, MyAccountApiError: auth0SpaJs.MyAccountApiError, MissingScopesError: auth0SpaJs.MissingScopesError, InvalidConfigurationError: auth0SpaJs.InvalidConfigurationError, RefreshTokenMode: auth0SpaJs.RefreshTokenMode, createAuthGuard: createAuthGuard, authGuard: authGuard }); module.exports = Auth0Vue; //# sourceMappingURL=auth0-vue.cjs.map