powershell with neo

google authentication with powershell

Introduction

I recently wanted to experiment with Google API and looked for the available module, but I haven’t found a good result. I had to make a first step myself, and that’s the authentication part. I spent a few hours on this subject and wrote a post.

GOOGLE AUTHENTICATION WITH POWERSHELL

First, you must provision the service account, grant it proper rights, and download the JSON-based credential file – this is out of the scope of this post; you can find plenty of information online.
The JSON file stores essential information to create the connection.
 
At the bottom of this page, you can find the function New-GoogleApiAccessToken. This function is a well-crafted masterpiece in PowerShell that effectively handles the complexities of creating a JSON Web Token (JWT) and exchanging it for an access token from Google API. This access token is the key that unlocks the door to a wide range of Google services, such as accessing files on Google Drive and managing calendars.
 
Now, let’s delve into how this script operates:
 
Input Parameters: The script requires a JSON string containing the service account credentials, the requested access scope from Google API, and, optionally, the user’s email address for whom the application is requesting delegated access.
 
JWT Generation: The script converts the JSON credentials into an object, extracts the necessary information, and constructs a JWT with a header and claim set. The claim set includes the issuer, scope, audience, expiration time, issued at the time, and subject (the target user’s email).
 
Digital Signature: Next, the script signs the JWT using the RSA SHA-256 algorithm to ensure that the token cannot be tampered with and can be verified by Google’s servers.
Token Exchange: After obtaining the JWT, the script sends a POST request to Google’s OAuth2 endpoint, which exchanges the JWT for an access token.
 
Access Token: Lastly, the script saves the access token in a variable that is specific to the script, ensuring its availability for authorized Google API calls.
 
How to use it?
If you plan to call Google APIs using PowerShell, you can place the function within your module and develop the other functions.
This function creates for you the authentication header, which you can refer to in all other functions by using the variable $script:authorizationHeader
You can always rewrite it to return the header instead of having it as the variable in the script scope.
 
The New-GoogleApiAccessToken script shows the power of automation and emphasizes the significance of secure and efficient API access. Whoever likes using PowerShell during their development, it’s a function you want handy.
 
Follow the white rabbit.
Neo
 
				
					function Get-GoogleApiAccessToken {
    <#
    .SYNOPSIS
    Retrieves an access token from Google API using a service account.

    .DESCRIPTION
    This function generates a JWT and exchanges it for an access token from Google API.
    The access token can then be used for authenticated requests to Google services.

    .PARAMETER GoogleAccessJson
    A JSON string containing the service account credentials including the private key and client email, this is the content of a file you downloaded as a Google credential file.

    .PARAMETER Scope
    The scope of access requested from Google API (e.g., 'https://www.googleapis.com/auth/drive').

    .PARAMETER TargetUserEmail
    The email address of the user for which the application is requesting delegated access (optional).

    .EXAMPLE
    $credentialsJson = Get-Content 'path/to/credentials.json' -Raw
    $accessToken = Get-GoogleApiAccessToken -GoogleAccessJson $credentialsJson -Scope 'https://www.googleapis.com/auth/drive.readonly'
    Use the $accessToken for authorized Google API calls.

    .NOTES
    Ensure that the service account has been granted the necessary permissions for the requested scope.
    #>
    param (
        [Parameter(Mandatory)]
        [string]$GoogleAccessJson, 

        [Parameter(Mandatory)]
        [string]$Scope,

        [Parameter(Mandatory)]
        [string]$TargetUserEmail 
    )
    $jsonContent = ConvertFrom-Json -InputObject $GoogleAccessJson -Depth 10
    $ServiceAccountEmail = $jsonContent.client_email
    $PrivateKey = $jsonContent.private_key -replace '-----BEGIN PRIVATE KEY-----\n' -replace '\n-----END PRIVATE KEY-----\n' -replace '\n'
    $header = @{
        alg = "RS256" 
        typ = "JWT" 
    }
    $headerBase64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(($header | ConvertTo-Json))) 
    $timestamp = [Math]::Round((Get-Date -UFormat %s)) 
    $claimSet = @{
        iss   = $ServiceAccountEmail 
        scope = $Scope 
        aud   = "https://oauth2.googleapis.com/token" 
        exp   = $timestamp + 3600 
        iat   = $timestamp 
        sub   = $TargetUserEmail 
    }
    $claimSetBase64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(($claimSet | ConvertTo-Json))) 
    $signatureInput = $headerBase64 + "." + $claimSetBase64 
    $signatureBytes = [System.Text.Encoding]::UTF8.GetBytes($signatureInput) 
    $privateKeyBytes = [System.Convert]::FromBase64String($PrivateKey) 
    $rsaProvider = [System.Security.Cryptography.RSA]::Create() 
    $bytesRead = $null
    $rsaProvider.ImportPkcs8PrivateKey($privateKeyBytes, [ref]$bytesRead) 
    $signature = $rsaProvider.SignData($signatureBytes, [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) 
    $signatureBase64 = [System.Convert]::ToBase64String($signature) 
    $jwt = $headerBase64 + "." + $claimSetBase64 + "." + $signatureBase64 
    $body = @{
        grant_type = "urn:ietf:params:oauth:grant-type:jwt-bearer" 
        assertion  = $jwt 
    }
    $response = Invoke-RestMethod -Uri "https://oauth2.googleapis.com/token" -Method POST -Body $body -ContentType "application/x-www-form-urlencoded" 
    $script:authorizationHeader = @{Authorization = 'Bearer {0}' -f $response.access_token }
}
				
			
Scroll to Top