UNPKG

@okta/okta-auth-js

Version:
342 lines (262 loc) 11.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.mixinOAuth = mixinOAuth; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _http = require("../../http"); var _util = require("../../util"); var crypto = _interopRequireWildcard(require("../../crypto")); var _pkce = _interopRequireDefault(require("../util/pkce")); var _factory = require("../factory"); var _TokenManager = require("../TokenManager"); var _util2 = require("../util"); var _node = require("./node"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function mixinOAuth(Base, TransactionManagerConstructor) { var _class; const WithOriginalUri = (0, _node.provideOriginalUri)(Base); return _class = class OktaAuthOAuth extends WithOriginalUri { constructor(...args) { super(...args); this.transactionManager = new TransactionManagerConstructor(Object.assign({ storageManager: this.storageManager }, this.options.transactionManager)); this.pkce = { DEFAULT_CODE_CHALLENGE_METHOD: _pkce.default.DEFAULT_CODE_CHALLENGE_METHOD, generateVerifier: _pkce.default.generateVerifier, computeChallenge: _pkce.default.computeChallenge }; this._pending = { handleLogin: false }; this._tokenQueue = new _util.PromiseQueue(); this.token = (0, _factory.createTokenAPI)(this, this._tokenQueue); // TokenManager this.tokenManager = new _TokenManager.TokenManager(this, this.options.tokenManager); } // inherited from subclass clearStorage() { super.clearStorage(); // Clear all local tokens this.tokenManager.clear(); } // Returns true if both accessToken and idToken are not expired // If `autoRenew` option is set, will attempt to renew expired tokens before returning. // eslint-disable-next-line complexity async isAuthenticated(options = {}) { // TODO: remove dependency on tokenManager options in next major version - OKTA-473815 const { autoRenew, autoRemove } = this.tokenManager.getOptions(); const shouldRenew = options.onExpiredToken ? options.onExpiredToken === 'renew' : autoRenew; const shouldRemove = options.onExpiredToken ? options.onExpiredToken === 'remove' : autoRemove; let { accessToken } = this.tokenManager.getTokensSync(); if (accessToken && this.tokenManager.hasExpired(accessToken)) { accessToken = undefined; if (shouldRenew) { try { accessToken = await this.tokenManager.renew('accessToken'); } catch {// Renew errors will emit an "error" event } } else if (shouldRemove) { this.tokenManager.remove('accessToken'); } } let { idToken } = this.tokenManager.getTokensSync(); if (idToken && this.tokenManager.hasExpired(idToken)) { idToken = undefined; if (shouldRenew) { try { idToken = await this.tokenManager.renew('idToken'); } catch {// Renew errors will emit an "error" event } } else if (shouldRemove) { this.tokenManager.remove('idToken'); } } return !!(accessToken && idToken); } async signInWithRedirect(opts = {}) { const { originalUri, ...additionalParams } = opts; if (this._pending.handleLogin) { // Don't trigger second round return; } this._pending.handleLogin = true; try { // Trigger default signIn redirect flow if (originalUri) { this.setOriginalUri(originalUri); } const params = Object.assign({ // TODO: remove this line when default scopes are changed OKTA-343294 scopes: this.options.scopes || ['openid', 'email', 'profile'] }, additionalParams); await this.token.getWithRedirect(params); } finally { this._pending.handleLogin = false; } } async getUser() { const { idToken, accessToken } = this.tokenManager.getTokensSync(); return this.token.getUserInfo(accessToken, idToken); } getIdToken() { const { idToken } = this.tokenManager.getTokensSync(); return idToken ? idToken.idToken : undefined; } getAccessToken() { const { accessToken } = this.tokenManager.getTokensSync(); return accessToken ? accessToken.accessToken : undefined; } getRefreshToken() { const { refreshToken } = this.tokenManager.getTokensSync(); return refreshToken ? refreshToken.refreshToken : undefined; } /** * Store parsed tokens from redirect url */ async storeTokensFromRedirect() { const { tokens } = await this.token.parseFromUrl(); this.tokenManager.setTokens(tokens); } isLoginRedirect() { return (0, _util2.isLoginRedirect)(this); } isPKCE() { return !!this.options.pkce; } hasResponseType(responseType) { let hasResponseType = false; if (Array.isArray(this.options.responseType) && this.options.responseType.length) { hasResponseType = this.options.responseType.indexOf(responseType) >= 0; } else { hasResponseType = this.options.responseType === responseType; } return hasResponseType; } isAuthorizationCodeFlow() { return this.hasResponseType('code'); } // Escape hatch method to make arbitrary OKTA API call async invokeApiMethod(options) { if (!options.accessToken) { const accessToken = (await this.tokenManager.getTokens()).accessToken; options.accessToken = accessToken === null || accessToken === void 0 ? void 0 : accessToken.accessToken; } return (0, _http.httpRequest)(this, options); } // Revokes the access token for the application session async revokeAccessToken(accessToken) { if (!accessToken) { accessToken = (await this.tokenManager.getTokens()).accessToken; const accessTokenKey = this.tokenManager.getStorageKeyByType('accessToken'); this.tokenManager.remove(accessTokenKey); } // Access token may have been removed. In this case, we will silently succeed. if (!accessToken) { return Promise.resolve(null); } return this.token.revoke(accessToken); } // Revokes the refresh token for the application session async revokeRefreshToken(refreshToken) { if (!refreshToken) { refreshToken = (await this.tokenManager.getTokens()).refreshToken; const refreshTokenKey = this.tokenManager.getStorageKeyByType('refreshToken'); this.tokenManager.remove(refreshTokenKey); } // Refresh token may have been removed. In this case, we will silently succeed. if (!refreshToken) { return Promise.resolve(null); } return this.token.revoke(refreshToken); } getSignOutRedirectUrl(options = {}) { let { idToken, postLogoutRedirectUri, state } = options; if (!idToken) { idToken = this.tokenManager.getTokensSync().idToken; } if (!idToken) { return ''; } if (!postLogoutRedirectUri) { postLogoutRedirectUri = this.options.postLogoutRedirectUri; } const logoutUrl = (0, _util2.getOAuthUrls)(this).logoutUrl; const idTokenHint = idToken.idToken; // a string let logoutUri = logoutUrl + '?id_token_hint=' + encodeURIComponent(idTokenHint); if (postLogoutRedirectUri) { logoutUri += '&post_logout_redirect_uri=' + encodeURIComponent(postLogoutRedirectUri); } // State allows option parameters to be passed to logout redirect uri if (state) { logoutUri += '&state=' + encodeURIComponent(state); } return logoutUri; } // Revokes refreshToken or accessToken, clears all local tokens, then redirects to Okta to end the SSO session. // eslint-disable-next-line complexity async signOut(options) { options = Object.assign({}, options); // postLogoutRedirectUri must be whitelisted in Okta Admin UI var defaultUri = window.location.origin; var currentUri = window.location.href; var postLogoutRedirectUri = options.postLogoutRedirectUri || this.options.postLogoutRedirectUri || defaultUri; var accessToken = options.accessToken; var refreshToken = options.refreshToken; var revokeAccessToken = options.revokeAccessToken !== false; var revokeRefreshToken = options.revokeRefreshToken !== false; if (revokeRefreshToken && typeof refreshToken === 'undefined') { refreshToken = this.tokenManager.getTokensSync().refreshToken; } if (revokeAccessToken && typeof accessToken === 'undefined') { accessToken = this.tokenManager.getTokensSync().accessToken; } if (!options.idToken) { options.idToken = this.tokenManager.getTokensSync().idToken; } if (revokeRefreshToken && refreshToken) { await this.revokeRefreshToken(refreshToken); } if (revokeAccessToken && accessToken) { await this.revokeAccessToken(accessToken); } const logoutUri = this.getSignOutRedirectUrl({ ...options, postLogoutRedirectUri }); // No logoutUri? This can happen if the storage was cleared. // Fallback to XHR signOut, then simulate a redirect to the post logout uri if (!logoutUri) { // local tokens are cleared once session is closed return this.closeSession() // can throw if the user cannot be signed out .then(function () { if (postLogoutRedirectUri === currentUri) { window.location.reload(); // force a hard reload if URI is not changing } else { window.location.assign(postLogoutRedirectUri); } }); } else { if (options.clearTokensBeforeRedirect) { // Clear all local tokens this.tokenManager.clear(); } else { this.tokenManager.addPendingRemoveFlags(); } // Flow ends with logout redirect window.location.assign(logoutUri); } } }, (0, _defineProperty2.default)(_class, "crypto", crypto), _class; } //# sourceMappingURL=index.js.map