'Google API GMail oauth2 can't refresh a RefreshToken after a week

I've a system that sends an email every day using GMail API.

  • I get the RefreshToken once then save it to a file.
  • before send daily mail the RefreshToken is refreshed to get the SingleUse AccessToken

These are my functions:

function GoogleAPI-GetRefreshToken($clientID, $clientSecret, $redirect_url = "urn:ietf:wg:oauth:2.0:oob")   
{   
    # https://developers.google.com/identity/protocols/oauth2/native-app

    Set-Clipboard ("https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/gmail.send&include_granted_scopes=true&response_type=code&redirect_uri={0}&client_id={1}" -f $redirect_url, $clientID)
    Write-Host "The authorization URL has been copied into the clipboard. Paste it in the browser and follows the instruction."
    $clientAuthCode = Read-Host "AuthorizationCode"

    $tokenParams = @{
          client_id=$clientID;
          client_secret=$clientSecret;
          code=$clientAuthCode;
          grant_type='authorization_code';
          redirect_uri=$redirect_url
        }

    $token = Invoke-WebRequest -Uri "https://accounts.google.com/o/oauth2/token" -Method POST -Body $tokenParams | ConvertFrom-Json

    # Use refresh token to get new access token
    # The access token is used to access the api by sending the access_token parm with every request. 
    # Access tokens are only valid for an hour, after that you will need to request a new one using your refresh_token
    
    return $token.refresh_token  
}

function GoogleAPI-GetAccessToken($clientID, $clientSecret, $refreshToken)
{
    $RefreshTokenParams = @{
      client_id=$clientID;
      client_secret=$clientSecret;
      refresh_token=$refreshToken;
      grant_type='refresh_token';
    }

    $refreshedToken = (Invoke-WebRequest -Uri "https://oauth2.googleapis.com/token" -Method POST -Body $refreshTokenParams | ConvertFrom-Json)
    
    return $refreshedToken.access_token
}

Main code, first I get the RefreshToken from the API (first time) or from the previous saved one (from file):

if (! (Test-Path $clientFile))
{
    $refreshToken = GoogleAPI-GetRefreshToken $clientID $clientSecret
    $refreshToken | ConvertTo-Json | Set-Content -Path $clientFile
}
else
{
    $refreshToken = Get-Content $clientFile | ConvertFrom-Json
}

Next I get a new AccessToken:

$accessToken = GoogleAPI-GetAccessToken $clientID $clientSecret $refreshToken

Finally I use the AccessToken to send the daily mail:

Mail-Send -accessToken $accessToken -from [email protected] -to [email protected] -subject "daily mail" -body "hello"

THE PROBLEM:
This only works for a week than I get an error from GoogleAPI-GetAccessToken


Invoke-WebRequest : The remote server returned an error: (400) Bad Request.

I know there's a limit of 50 on client/user and user refresh operation (doc) but I don't know how to overcome that problem and let the system send daily mail for ever without having to ask user to do the authentication again.

Any idea ?
Thank you



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source