Google APIのアクセストークンをPowerShellでリフレッシュトークンも考えて取得する

この記事は要するに[Google APIのAccess Tokenをお手軽に取得する](https://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5)を読んで実装してみた
ちゃんとリフレッシュトークンとかを保存しておくサンプルコードです。

言語はあまり関係がなく流れはこんな感じかなっていう感じで読んでもらえればと思います。
powershell以外だと結構便利なのもあるんですけれど諸々の事情でpowershellちゃんかわいいよ

```powershell

function Get-AccessTokenFromAuthorizationCode
{
    #それぞれClientID.txtとClientSecret.txtだけあればOK
    $ClientID = Get-Content $PSScriptRoot/ClientID.txt
    $ClientSecret= Get-Content $PSScriptRoot/ClientSecret.txt
    
    $RedirectUri="urn:ietf:wg:oauth:2.0:oob"
    # スコープは適宜変えてください
    $Scope="https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets"

    Write-Host "ブラウザ認証を行います"

    $Uri = "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=${ClientID}&redirect_uri=${RedirectUri}&scope=${Scope}&access_type=offline"
    
    Write-Host $Uri

    Start-Process $Uri

    $AuthorizationCode = Read-Host "認証コードを入力してください"


    $AuthData = @{
        code = $AuthorizationCode;
        client_id = $ClientID;
        client_secret = $ClientSecret;
        redirect_uri = $RedirectUri;
        grant_type = "authorization_code";
        access_type="offline";
    }
    
    $tokenResponse = Invoke-WebRequest -Body $AuthData -Uri "https://www.googleapis.com/oauth2/v4/token" -Method Post 
    $token = $tokenResponse.Content | ConvertFrom-Json
    $token.access_token > $PSScriptRoot/AccessToken.txt
    $token.refresh_token > $PSScriptRoot/RefreshToken.txt

    return $token.access_token
    
}

function Get-AccessToken{
    if( !(Test-Path $PSScriptRoot/RefreshToken.txt) ){
        return Get-AccessTokenFromAuthorizationCode
    }

    $RefreshToken = Get-Content $PSScriptRoot/RefreshToken.txt
    $ClientID = Get-Content $PSScriptRoot/ClientID.txt
    $ClientSecret= Get-Content $PSScriptRoot/ClientSecret.txt
    $param = @{
        refresh_token = $RefreshToken
        client_id = $ClientID
        client_secret = $ClientSecret
        grant_type="refresh_token"
    }

    #アクセストークンは3回リトライしてみる（ダメだと認証が必要なためめんどくさい）
    for( $i =0; $i -lt 3;$i++ ){

        try{
            $response = Invoke-WebRequest -Uri https://www.googleapis.com/oauth2/v4/token -Body $param -Method Post 
            $token = $response.Content | ConvertFrom-Json

            $token.access_token > $PSScriptRoot/AccessToken.txt
            return $token.access_token
            
        }catch{
            Start-Sleep -Seconds 10
            continue
        }
    }

    return Get-AccessTokenFromAuthorizationCode
}

#アクセストークン取得はこれだけでOK
$accessToken = Get-AccessToken
$header = @{
    Authorization = "Bearer $AccessToken"
}

```

# 使い方

コメントの通り
ClientID.txtとClientSecret.txtをスクリプトと同じディレクトリに入れてそこにClientIDとSlientSecretを一行書いておけばOK
スコープは適宜

```powershell
    #それぞれClientID.txtとClientSecret.txtだけあればOK
    $ClientID = Get-Content $PSScriptRoot/ClientID.txt
    $ClientSecret= Get-Content $PSScriptRoot/ClientSecret.txt
    
    $RedirectUri="urn:ietf:wg:oauth:2.0:oob"
    # スコープは適宜変えてください
    $Scope="https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets"
```

# 解説

Get-AccessTokenでアクセストークンを取得しますがそれの流れはこんな感じです

1. リフレッシュトークン持ってる？
   * 持ってなかったらGet-AccessTokenFromAuthorizationCodeでブラウザ認証から始める
   * 持ってたらリフレッシュトークンからアクセストークンもらってきて返す
2. アクセストークンの取得に失敗したらGet-AccessTokenFromAuthorizationCode


Get-AccessTokenFromAuthorizationCodeはClientIDとClientSecretはすでに持っているとして

1. 認証URL作ってブラウザで開く
2. 認証コードを要求する
3. それをもとにアクセストークンとリフレッシュトークンを取得
4. リフレッシュトークンを保存

という感じです。

毎回リフレッシュトークンから作るなら保存するのは本当はリフレッシュトークンだけでいいはず