[CmdletBinding()] Param( # https://console.cloud.google.com/iam-admin/serviceaccounts [Parameter(Mandatory,Position=0,HelpMessage='Enter path to Google Service Account credentials json file')][string]$serviceCredentialsJsonPath, # https://developers.google.com/identity/protocols/oauth2/scopes [Parameter(Mandatory,Position=1,HelpMessage='Enter required Google API scopes')][string[]]$scopes, [Parameter(Position=3,HelpMessage='Enter token duration in seconds')][int]$duration=3540 ) Set-StrictMode -Version 3.0 $ErrorActionPreference = "Stop" function base64urlbytes ($Object) { ([String]([System.Convert]::ToBase64String($Object))).TrimEnd('=').Replace('+','-').Replace('/','_') } function base64url ($Object) { base64urlbytes ([System.Text.Encoding]::UTF8.GetBytes($Object)) } $creds = Get-Content $serviceCredentialsJsonPath | ConvertFrom-Json $rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider $rsa.ImportFromPem($creds.private_key) $rawheader = [Ordered]@{ alg = "RS256" typ = "JWT" } | ConvertTo-Json -Compress $header = base64url $rawheader [int]$createDate = Get-Date (Get-Date).ToUniversalTime() -UFormat "%s" $expiryDate = $createDate + $duration $rawclaims = [Ordered]@{ iss = "$($creds.client_email)" sub = "$($creds.client_email)" scope = "$($Scopes -join " ")" aud = "https://www.googleapis.com/oauth2/v4/token" exp = "$expiryDate" iat = "$createDate" } | ConvertTo-Json $claims = base64url $rawclaims $sig = base64urlbytes ($rsa.SignData([System.Text.Encoding]::UTF8.GetBytes($header + "." + $claims),"SHA256")) $jwt = $header + "." + $claims + "." + $sig $fields = [Ordered]@{ grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer' assertion = $jwt } $response = Invoke-WebRequest -Uri "https://www.googleapis.com/oauth2/v4/token" -Method Post -Body $fields -ContentType "application/x-www-form-urlencoded" ($response | ConvertFrom-Json).access_token