// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import { OAuthConfig } from 'aws-amplify/adapter-core/internals'; import { OAUTH_GRANT_TYPE } from '../constant'; import { OAuthTokenExchangeResult, OAuthTokenRevocationResult } from '../types'; import { createUrlSearchParamsForTokenExchange, createUrlSearchParamsForTokenRevocation, } from './createUrlSearchParams'; import { createRevokeEndpoint, createTokenEndpoint, } from './cognitoHostedUIEndpoints'; export const exchangeAuthNTokens = async ({ redirectUri, userPoolClientId, oAuthConfig, code, codeVerifier, }: { redirectUri: string; userPoolClientId: string; oAuthConfig: OAuthConfig; code: string; codeVerifier: string; }): Promise => { const searchParams = createUrlSearchParamsForTokenExchange({ client_id: userPoolClientId, code, redirect_uri: redirectUri, code_verifier: codeVerifier, grant_type: OAUTH_GRANT_TYPE, }); const oAuthTokenEndpoint = createTokenEndpoint(oAuthConfig.domain); const tokenExchangeResponse = await fetch(oAuthTokenEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Cache-Control': 'no-cache', }, body: searchParams.toString(), }); // Exchanging an authorization code grant with PKCE for tokens with // `grant_type=authorization_code` produces a stable shape of payload. // Details see https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html // Possible errors: invalid_request|invalid_client|invalid_grant|unauthorized_client|unsupported_grant_type // Should not happen unless configuration is wrong; return (await tokenExchangeResponse.json()) as OAuthTokenExchangeResult; }; export const revokeAuthNTokens = async ({ userPoolClientId, refreshToken, endpointDomain, }: { userPoolClientId: string; refreshToken: string; endpointDomain: string; }): Promise => { const searchParams = createUrlSearchParamsForTokenRevocation({ client_id: userPoolClientId, token: refreshToken, }); const oAuthTokenRevocationEndpoint = createRevokeEndpoint(endpointDomain); const response = await fetch(oAuthTokenRevocationEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Cache-Control': 'no-cache', }, body: searchParams.toString(), }); const contentLength = parseInt( response.headers.get('Content-Length') ?? '0', 10, ); return contentLength === 0 ? {} : ((await response.json()) as OAuthTokenRevocationResult); };