import { GaxiosOptions , GaxiosResponse } from 'gaxios' ; import * as querystring from 'querystring' ; import { DefaultTransporter } from '../transporters' ; import { Headers } from './oauth2client' ; import { ClientAuthentication , OAuthClientAuthHandler , OAuthErrorResponse , getErrorFromOAuthErrorResponse , } from './oauth2common' ; /**
 * Defines the interface needed to initialize an StsCredentials instance.
 * The interface does not directly map to the spec and instead is converted
 * to be compliant with the JavaScript style guide. This is because this is
 * instantiated internally.
 * StsCredentials implement the OAuth 2.0 token exchange based on
 * https://tools.ietf.org/html/rfc8693.
 * Request options are defined in
 * https://tools.ietf.org/html/rfc8693#section-2.1
 */ export interface StsCredentialsOptions { /**
     * REQUIRED. The value "urn:ietf:params:oauth:grant-type:token-exchange"
     * indicates that a token exchange is being performed.
     */ grantType : string ; /**
     * OPTIONAL. A URI that indicates the target service or resource where the
     * client intends to use the requested security token.
     */ resource ? : string ; /**
     * OPTIONAL. The logical name of the target service where the client
     * intends to use the requested security token.  This serves a purpose
     * similar to the "resource" parameter but with the client providing a
     * logical name for the target service.
     */ audience ? : string ; /**
     * OPTIONAL. A list of space-delimited, case-sensitive strings, as defined
     * in Section 3.3 of [RFC6749], that allow the client to specify the desired
     * scope of the requested security token in the context of the service or
     * resource where the token will be used.
     */ scope ? : string [ ] ; /**
     * OPTIONAL. An identifier, as described in Section 3 of [RFC8693], eg.
     * "urn:ietf:params:oauth:token-type:access_token" for the type of the
     * requested security token.
     */ requestedTokenType ? : string ; /**
     * REQUIRED. A security token that represents the identity of the party on
     * behalf of whom the request is being made.
     */ subjectToken : string ; /**
     * REQUIRED. An identifier, as described in Section 3 of [RFC8693], that
     * indicates the type of the security token in the "subject_token" parameter.
     */ subjectTokenType : string ; actingParty ? : { /**
         * OPTIONAL. A security token that represents the identity of the acting
         * party.  Typically, this will be the party that is authorized to use the
         * requested security token and act on behalf of the subject.
         */ actorToken : string ; /**
         * An identifier, as described in Section 3, that indicates the type of the
         * security token in the "actor_token" parameter. This is REQUIRED when the
         * "actor_token" parameter is present in the request but MUST NOT be
         * included otherwise.
         */ actorTokenType : string ; } ; } /**
 * Defines the standard request options as defined by the OAuth token
 * exchange spec: https://tools.ietf.org/html/rfc8693#section-2.1
 */ interface StsRequestOptions { grant_type : string ; resource ? : string ; audience ? : string ; scope ? : string ; requested_token_type ? : string ; subject_token : string ; subject_token_type : string ; actor_token ? : string ; actor_token_type ? : string ; client_id ? : string ; client_secret ? : string ; options ? : string ; } /**
 * Defines the OAuth 2.0 token exchange successful response based on
 * https://tools.ietf.org/html/rfc8693#section-2.2.1
 */ export interface StsSuccessfulResponse { access_token : string ; issued_token_type : string ; token_type : string ; expires_in ? : number ; refresh_token ? : string ; scope ? : string ; res ? : GaxiosResponse | null ; } /**
 * Implements the OAuth 2.0 token exchange based on
 * https://tools.ietf.org/html/rfc8693
 */ export class StsCredentials extends OAuthClientAuthHandler { private transporter : DefaultTransporter ; param tokenExchangeEndpoint param clientAuthentication constructor ( private readonly tokenExchangeEndpoint , clientAuthentication ? ) { super ( clientAuthentication ) ; this . transporter = new DefaultTransporter ( ) ; } param stsCredentialsOptions param additionalHeaders param options return async exchangeToken ( stsCredentialsOptions , additionalHeaders ? , options ? ) { const values = { grant_type : stsCredentialsOptions . grantType , resource : stsCredentialsOptions . resource , audience : stsCredentialsOptions . audience , scope : stsCredentialsOptions . scope ?. join ( ' ' ) , requested_token_type : stsCredentialsOptions . requestedTokenType , subject_token : stsCredentialsOptions . subjectToken , subject_token_type : stsCredentialsOptions . subjectTokenType , actor_token : stsCredentialsOptions . actingParty ?. actorToken , actor_token_type : stsCredentialsOptions . actingParty ?. actorTokenType , options : options && JSON . stringify ( options ) , } ; Object . keys ( values ) . forEach ( key => { if ( typeof ( values as { [ index ] : any ; } ) [ key ] === 'undefined' ) { delete ( values as { [ index ] : any ; } ) [ key ] ; } } ) ; const headers = { 'Content-Type' : 'application/x-www-form-urlencoded' , } ; Object . assign ( headers , additionalHeaders || { } ) ; const opts = { url : this . tokenExchangeEndpoint , method : 'POST' , headers , data : querystring . stringify ( values as unknown as querystring . ParsedUrlQueryInput ) , responseType : 'json' , } ; this . applyClientAuthenticationOptions ( opts ) ; try { const response = await this . transporter . request < StsSuccessfulResponse > ( opts ) ; const stsSuccessfulResponse = response . data ; stsSuccessfulResponse . res = response ; return stsSuccessfulResponse ; } catch ( error ) { if ( error . response ) { throw getErrorFromOAuthErrorResponse ( error . response . data as OAuthErrorResponse , error ) ; } throw error ; } } }