Google API OAuth2.0トークンをほぼ自動で取得しよう！

## はじめに
GASで作ったAPIをキックして、ファイルの格納や、スプレッドシートの編集などをする必要が出てきた。
GASは、デプロイすることで、「ウェブアプリ」や「実行可能API」を作ることが出来る。なので、APIを作るのは簡単だ。
だけど、APIを動かすには、「アクセストークン」が必要で、それぞれ取得方法が違う。

| APIの種類 | アクセストークン取得方法 | トークンの寿命 |
|:-|:-|:-|
| ウェブアプリ | ・getOAuthToken()メソッドで取得。<br>・メソッドはエディタから手動実行。またはトリガー起動。<br>※ブラウザから実行する場合、自動取得。| 数分 |
| 実行可能API  | ・リフレッシュトークンやクライアントＩＤ等の情報をPOSTメソッドで送信して取得。 |数分|

上記の通り、好きなタイミングでアクセストークンを取得したいのなら、**実行可能API一択**になる。ウェブアプリだと、アクセストークンを取得したいときは、エディタから手動実行するか、トリガーを５分おきに実行し、アクセストークンを取得し続けないとならない。（※なぜなら、アクセストークンの寿命が数分なので、５分以上の間隔でトリガーを実行するとトークンが「寿命切れ」している可能性がある。）

参考にした記事によると、アクセストークンを取得するには、長いURLをエディタでゴリゴリ作ったり、Curlを駆使したりする必要がある。
それって、素人にはハードルが高すぎるじゃん。

ほぼ自動で取得できないかと考えたのがこの記事なのだ。

なお、本記事では、作ったGAS付スプレッドシートの公開が主で、アクセストークンを取得する手順についてはほぼ触れていない。
取得手順は以下の素晴らしい記事たちを参考にしてほしい。

https://qiita.com/giiko_/items/b0b2ff41dfb0a62d628b

https://qiita.com/kossacks/items/8d279bcc1acc2c2153ab

## 認証コード取得用URLの生成は簡単
参考記事によると、認証コード取得用URLは、以下のようなプロクラムで生成することが出来る。
とても簡単で、僕もここまではすんなり行けた。
スコープで少しつまづいたが、[Googleの「Google API の OAuth 2.0 スコープ」](https://developers.google.com/identity/protocols/oauth2/scopes?hl=ja "Google API の OAuth 2.0 スコープ")という記事を見ればわかると思う。

```javascript:サンプル.js
function getAuthUrl() {
  const authUrl = 'https://accounts.google.com/o/oauth2/v2/auth';
  const clientId = '1234hoge-fuga.apps.googleusercontent.com';
  const redirectUri = 'https://hogefuga.co.jp/L/exec';
  const scopes = ['https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/spreadsheets','https://www.googleapis.com/auth/script.external_request'];

  //スペース区切りでJOIN
  const scope = scopes.join(' ');

  //認証コード取得用URL生成
  const requestUrl = `${authUrl}?scope=${scope}&access_type=offline&prompt=consent&include_granted_scope=true&response_type=code&redirect_uri=${redirectUri}&client_id=${clientId}`;
  Logger.log(requestUrl);
}

```


## え？　認証コードはCurlでは取れないの？
上で挙げた記事たちはとても分かりやすいんだけど、行を読み飛ばす癖のある僕にとっては、ここがつまづいたポイント。
認証コード取得用URLにCurlでアクセスしたら、認証コードが取得できると思っていた。
しかし、Curlコマンドから出力されるのは、なんかエラーが書かれているHTMLだった。

## 認証コードはリダイレクトURLに引き渡されるらしい。
再度、上で挙げた記事たちを読み返してみると、
>ブラウザでアクセスする

と書いてあるではあ～りませんか。（古い）

さっそく、認証コード取得用URLにブラウザでアクセスすると、権限許可の画面が出てきた。
適当に承認すると、ブラウザのURL欄に

> https://hogefuga.co.jp/L/exec?code=xxxxxxxxxxxxxxxx

のように表示されて、**?code=** の後ろが認証コードなのだそうだ。
この、?code=　の後ろの文字列を手順に則って、リフレッシュトークン、アクセストークンを取得するのだけど、なんか面倒くさい。
?code=　以下の文字列をプログラムに自動で渡すことはできないのだろうか？

## リダイレクトURLのためのWebサイトを作ろう。
ここで、URLをよく見てみよう。
URLは、こうなっている。

```https
https://[リダイレクトURL]?code=xxxxxxxxxxxxxxxx
```
これは、GETメソッドの構文そのものだ。

そして、GASは、doGet()というGETメソッドを簡単に処理するメソッドが用意されている。
これを使わない手はない。

## 作ってみた
https://docs.google.com/spreadsheets/d/1ePVhZERUiBMJPWISzOZ1_FrfckB0XQEyq8_b1dCeUsI/edit?usp=sharing

どうせなら、クライアントＩＤ等は外部設定しようと思い、スプレッドシートに記載してもらうことにした。
なお、どんなものを設定すればいいのかわかるように、設定値をところどころ書き換えてセットしておくぞ。
**あくまでも例なので、このまま動かさないでください。絶対動きません。**

1. 上記スプレッドシートをご自分のマイドライブに**コピーしよう。（これ、重要）**
1. 続いて、拡張機能->Apps ScriptでGASを表示し、デプロイボタンを押して、**ウェブアプリ**としてデプロイしよう。
1. デプロイ後に表示されるウェブアプリURLをコピーし、スプレッドシートのウェブアプリURL欄にペーストしよう。
1. GCPプロジェクト側の、リダイレクトURLにもウェブアプリURLを設定しよう。
1. authUrl欄、token取得用url欄は、Google側の仕様が変わらない限りそのままで大丈夫。
1. クライアントID、クライアントシークレット欄に、GCPプロジェクトで取得したものを設定しよう。
1. スコープは１０個まで設定できます。設定しない場合は空白を設定しよう。
1. いよいよ、認証コード取得用URLの生成です。メニューの一番右に、「追加」というものが追加されているので、追加->IRL生成の順でクリックしよう。**※追加が表示されていない場合はコピーがうまくいってない可能性あり。**
1. ２０行目に認証コード取得用URLが表示されるので、それをコピーし、ブラウザのURL欄に貼り付けよう。

どんな処理をしているかは、コードを見てもらったほうが早いので省略。
必要に応じてご質問聞いてね。

肝となる部分だけ解説。
```js
function doGet(e) {
  const code = e.parameter.code;
  const param = getParam();
  const res = getToken(code,param);
  return createHtmlPage(code,res.access_token,res.refresh_token);
}

```
| 行番号| 説明 |
|:-:|:-|
| 1 |知っていると思うけど、このウェブアプリURLにGetメソッドでアクセスすると、呼ばれる関数。|
| 2 |Getメソッドで、このウェブアプリURLにアクセスすると、code=　以下の文字列（すなわち認証コード）を取得。|
| 3 |スプレッドシートに記載された各種パラメータを取得する関数を呼んでる。|
| 4 |認証コードと、スプレッドシートに記載された各種パラメータを基に、**リフレッシュトークン**（←これが目当て）とアクセストークンを取得する関数を呼ぶ。|
| 5 |**リフレッシュトークン**を表示するHTMLを生成する関数を呼んで、リHTMLを返す。|