AI-generated Key Takeaways
-
The provided code offers a simple library for making OAuth2 authenticated requests, particularly for third-party APIs.
-
It includes functions for authenticating using refresh tokens, client credentials, service accounts, and username/password.
-
An
OAuth2UrlFetchAppobject is created with a stored access token to perform authenticated HTTP requests. -
The
authenticate_function handles the authentication step and retrieves the access token. -
The library is added to the global scope under the name
OAuth2.
Create an object for OAuth2-authorized requests
/** * Simple library for sending OAuth2 authenticated requests . * See : https : // developers . google . com / google - ads / scripts / docs / features / third - party - apis #oauth_2 * for full details . */ /** * Adds a OAuth object , for creating authenticated requests , to the global * object . */ ( function ( scope ) { /** * Creates an object for making authenticated URL fetch requests with a * given stored access token . * @ param { string } accessToken The access token to store and use . * @ constructor */ function OAuth2UrlFetchApp ( accessToken ) { this . accessToken_ = accessToken ; } /** * Performs an HTTP request for the given URL . * @ param { string } url The URL to fetch * @ param { ? Object = } options Options as per UrlFetchApp . fetch * @ return { ! HTTPResponse } The HTTP Response object . */ OAuth2UrlFetchApp . prototype . fetch = function ( url , opt_options ) { const fetchOptions = opt_options || {}; if ( ! fetchOptions . headers ) { fetchOptions . headers = {}; } fetchOptions . headers . Authorization = 'Bearer ' + this . accessToken_ ; return UrlFetchApp . fetch ( url , fetchOptions ); }; /** * Performs the authentication step * @ param { string } tokenUrl The endpoint for use in obtaining the token . * @ param { ! Object } payload The authentication payload , typically containing * details of the grant type , credentials etc . * @ param { string = } opt_authHeader Client credential grant also can make use * of an Authorisation header , as specified here * @ param { string = } opt_scope Optional string of spaced - delimited scopes . * @ return { string } The access token */ function authenticate_ ( tokenUrl , payload , opt_authHeader , opt_scope ) { const options = { muteHttpExceptions : true , method : 'POST' , payload : payload }; if ( opt_scope ) { options . payload . scope = opt_scope ; } if ( opt_authHeader ) { options . headers = { Authorization : opt_authHeader }; } const response = UrlFetchApp . fetch ( tokenUrl , options ); const responseData = JSON . parse ( response . getContentText ()); if ( responseData && responseData . access_token ) { const accessToken = responseData . access_token ; } else { throw Error ( 'No access token received: ' + response . getContentText ()); } return accessToken ; } /** * Creates a OAuth2UrlFetchApp object having authenticated with a refresh * token . * @ param { string } tokenUrl The endpoint for use in obtaining the token . * @ param { string } clientId The client ID representing the application . * @ param { string } clientSecret The client secret . * @ param { string } refreshToken The refresh token obtained through previous * ( possibly interactive ) authentication . * @ param { string = } opt_scope Space - delimited set of scopes . * @ return { ! OAuth2UrlFetchApp } The object for making authenticated requests . */ function withRefreshToken ( tokenUrl , clientId , clientSecret , refreshToken , opt_scope ) { const payload = { grant_type : 'refresh_token' , client_id : clientId , client_secret : clientSecret , refresh_token : refreshToken }; const accessToken = authenticate_ ( tokenUrl , payload , null , opt_scope ); return new OAuth2UrlFetchApp ( accessToken ); } /** * Creates a OAuth2UrlFetchApp object having authenticated with client * credentials . * @ param { string } tokenUrl The endpoint for use in obtaining the token . * @ param { string } clientId The client ID representing the application . * @ param { string } clientSecret The client secret . * @ param { string = } opt_scope Space - delimited set of scopes . * @ return { ! OAuth2UrlFetchApp } The object for making authenticated requests . */ function withClientCredentials ( tokenUrl , clientId , clientSecret , opt_scope ) { const authHeader = 'Basic ' + Utilities . base64Encode ([ clientId , clientSecret ] . join ( ':' )); const payload = { grant_type : 'client_credentials' , client_id : clientId , client_secret : clientSecret }; const accessToken = authenticate_ ( tokenUrl , payload , authHeader , opt_scope ); return new OAuth2UrlFetchApp ( accessToken ); } /** * Creates a OAuth2UrlFetchApp object having authenticated with OAuth2 username * and password . * @ param { string } tokenUrl The endpoint for use in obtaining the token . * @ param { string } clientId The client ID representing the application . * @ param { string } username OAuth2 Username * @ param { string } password OAuth2 password * @ param { string = } opt_scope Space - delimited set of scopes . * @ return { ! OAuth2UrlFetchApp } The object for making authenticated requests . */ function withPassword ( tokenUrl , clientId , username , password , opt_scope ) { const payload = { grant_type : 'password' , client_id : clientId , username : username , password : password }; const accessToken = authenticate_ ( tokenUrl , payload , null , opt_scope ); return new OAuth2UrlFetchApp ( accessToken ); } /** * Creates a OAuth2UrlFetchApp object having authenticated as a Service * Account . * Flow details taken from : * https : // developers . google . com / identity / protocols / OAuth2ServiceAccount * @ param { string } tokenUrl The endpoint for use in obtaining the token . * @ param { string } serviceAccount The email address of the Service Account . * @ param { string } key The key taken from the downloaded JSON file . * @ param { string } scope Space - delimited set of scopes . * @ return { ! OAuth2UrlFetchApp } The object for making authenticated requests . */ function withServiceAccount ( tokenUrl , serviceAccount , key , scope ) { const assertionTime = new Date (); const jwtHeader = '{"alg":"RS256","typ":"JWT"}' ; const jwtClaimSet = { iss : serviceAccount , scope : scope , aud : tokenUrl , exp : Math . round ( assertionTime . getTime () / 1000 + 3600 ), iat : Math . round ( assertionTime . getTime () / 1000 ) }; const jwtAssertion = Utilities . base64EncodeWebSafe ( jwtHeader ) + '.' + Utilities . base64EncodeWebSafe ( JSON . stringify ( jwtClaimSet )); const signature = Utilities . computeRsaSha256Signature ( jwtAssertion , key ); jwtAssertion += '.' + Utilities . base64Encode ( signature ); const payload = { grant_type : 'urn:ietf:params:oauth:grant-type:jwt-bearer' , assertion : jwtAssertion }; const accessToken = authenticate_ ( tokenUrl , payload , null ); return new OAuth2UrlFetchApp ( accessToken ); } scope . OAuth2 = { withRefreshToken : withRefreshToken , withClientCredentials : withClientCredentials , withServiceAccount : withServiceAccount , withPassword : withPassword }; })( this );

