UNPKG

@aws-amplify/auth

Version:
137 lines (135 loc) 6.15 kB
'use strict'; // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 Object.defineProperty(exports, "__esModule", { value: true }); exports.signInWithRedirect = signInWithRedirect; const core_1 = require("@aws-amplify/core"); const utils_1 = require("@aws-amplify/core/internals/utils"); require("../utils/oauth/enableOAuthListener"); const models_1 = require("../types/models"); const utils_2 = require("../../../utils"); const signInHelpers_1 = require("../utils/signInHelpers"); const oauth_1 = require("../utils/oauth"); const createOAuthError_1 = require("../utils/oauth/createOAuthError"); const cancelOAuthFlow_1 = require("../utils/oauth/cancelOAuthFlow"); /** * Signs in a user with OAuth. Redirects the application to an Identity Provider. * * @param input - The SignInWithRedirectInput object, if empty it will redirect to Cognito HostedUI * * @throws AuthTokenConfigException - Thrown when the user pool config is invalid. * @throws OAuthNotConfigureException - Thrown when the oauth config is invalid. */ async function signInWithRedirect(input) { const authConfig = core_1.Amplify.getConfig().Auth?.Cognito; (0, utils_1.assertTokenProviderConfig)(authConfig); (0, utils_1.assertOAuthConfig)(authConfig); oauth_1.oAuthStore.setAuthConfig(authConfig); if (!input?.options?.prompt) { await (0, signInHelpers_1.assertUserNotAuthenticated)(); } let provider = 'COGNITO'; // Default let idpIdentifier; if (typeof input?.provider === 'string') { provider = models_1.cognitoHostedUIIdentityProviderMap[input.provider]; } else if (input?.provider?.custom) { provider = input.provider.custom; } else if (input?.provider?.idpIdentifier) { ({ idpIdentifier } = input.provider); } return oauthSignIn({ oauthConfig: authConfig.loginWith.oauth, clientId: authConfig.userPoolClientId, provider, idpIdentifier, customState: input?.customState, preferPrivateSession: input?.options?.preferPrivateSession, options: { loginHint: input?.options?.loginHint, lang: input?.options?.lang, nonce: input?.options?.nonce, prompt: input?.options?.prompt, }, authSessionOpener: input?.options?.authSessionOpener, }); } const oauthSignIn = async ({ oauthConfig, provider, idpIdentifier, clientId, customState, preferPrivateSession, options, authSessionOpener, }) => { const { domain, redirectSignIn, responseType, scopes } = oauthConfig; const { loginHint, lang, nonce, prompt } = options ?? {}; const randomState = (0, oauth_1.generateState)(); const openAuthSession = authSessionOpener || utils_2.openAuthSession; /* encodeURIComponent is not URL safe, use urlSafeEncode instead. Cognito single-encodes/decodes url on first sign in and double-encodes/decodes url when user already signed in. Using encodeURIComponent, Base32, Base64 add characters % or = which on further encoding becomes unsafe. '=' create issue for parsing query params. Refer: https://github.com/aws-amplify/amplify-js/issues/5218 */ const state = customState ? `${randomState}-${(0, utils_1.urlSafeEncode)(customState)}` : randomState; const { value, method, toCodeChallenge } = (0, oauth_1.generateCodeVerifier)(128); const redirectUri = (0, oauth_1.getRedirectUrl)(oauthConfig.redirectSignIn); if ((0, utils_1.isBrowser)()) oauth_1.oAuthStore.storeOAuthInFlight(true); oauth_1.oAuthStore.storeOAuthState(state); oauth_1.oAuthStore.storePKCE(value); const params = new URLSearchParams([ ['redirect_uri', redirectUri], ['response_type', responseType], ['client_id', clientId], ]); // Add either identity_provider or idp_identifier, but not both if (idpIdentifier) { params.append('idp_identifier', idpIdentifier); } else { params.append('identity_provider', provider); } params.append('scope', scopes.join(' ')); loginHint && params.append('login_hint', loginHint); lang && params.append('lang', lang); nonce && params.append('nonce', nonce); prompt && params.append('prompt', prompt.toLowerCase()); params.append('state', state); if (responseType === 'code') { params.append('code_challenge', toCodeChallenge()); params.append('code_challenge_method', method); } // Using URL object is not supported in React Native as the `search` property is read-only // See: https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Blob/URL.js const oAuthUrl = `https://${domain}/oauth2/authorize?${params.toString()}`; // this will only take effect in the following scenarios: // 1. the user cancels the OAuth flow on web via back button, and // 2. when bfcache is enabled (0, cancelOAuthFlow_1.listenForOAuthFlowCancellation)(oauth_1.oAuthStore); // the following is effective only in react-native as openAuthSession resolves only in react-native const { type, error, url } = (await openAuthSession(oAuthUrl, redirectSignIn, preferPrivateSession)) ?? {}; try { if (type === 'error') { throw (0, createOAuthError_1.createOAuthError)(String(error)); } if (type === 'canceled') { throw (0, createOAuthError_1.createOAuthError)(String(type)); } if (type === 'success' && url) { await (0, oauth_1.completeOAuthFlow)({ currentUrl: url, clientId, domain, redirectUri, responseType, userAgentValue: (0, utils_2.getAuthUserAgentValue)(utils_1.AuthAction.SignInWithRedirect), preferPrivateSession, }); } } catch (err) { await (0, oauth_1.handleFailure)(err); // rethrow the error so it can be caught by `await signInWithRedirect()` in react-native throw err; } }; //# sourceMappingURL=signInWithRedirect.js.map