GoogleのAPI認証奮闘記

みなさん、こんばんは。

 

先日から作成していた,「Dashボタンで出勤管理」がエンドポイントで叩けるところまでいけました。

 

Lambda(出勤スクリプト) + API Gateway

 

までが完成した感じです。

 

先日の記事段階では、Lambda上でGoogleAPIを叩けない状態だったのですが、解決しました。

 

APIを叩けなかった理由としては

そもそも、以下の記事で掲載した「認証の手順」の認識に誤りがあったからです。

k12si.hatenablog.com

 

今日は

  1. 「認証の手順」について
  2. 実際にAPIを叩けるまでに行ったこと(Lambda + API Gateway
  3. 結果

についてお話ししていこうと思います。

「認証の手順」について

まず,アプリケーション(クライント)がGoogleAPIを利用するには認証が必要です。

これはアクセストークを取得するためです。

 

先日の記事で述べたようにGoogleAPIを利用するにはアクセストークが必要です。

そしてそのトークンはOAuthという認可サーバに発行してもらわないといけません。

ここまでは、先日述べた通り正しいと思います。

 

しかし,ここから認識の誤りがありました。

それは,OAuthによるアクセストークンの発行方法は2種類存在するといった点です。

 

それが以下です。

  • ユーザによる承認方式
  • サービスアカウント方式

上の方式名はわかりやすいように勝手につけました。

 

順番に図で見ていきます。

ユーザによる承認方式

全体像は,前回の図からごっそりサービスアカウント部分を取り除き,yamlファイルを追加した形となります。

f:id:k12si:20190403010012p:plain

前回記事で紹介したクイックスタートはこちらの方式を採用していました。

事前にダウンロードする「credentials.json」はGoogle側で自動作成されたものです。

以下の情報が含まれています。

  • クライアント情報(ID, シークレットキー)
  • 認可サーバURI(auth_uri
  • OAuthを用いたGoogleトークン作成URI(token_uri

このクライアントは今回の方式ではユーザによって一時的に承認され,GoogleAPIを利用可能であるため,クライアントIDなどはGoogle側で自動で作成された適当なものとなっている。

 

認証手順としては上記図の番号通りに遷移していきます。

 

ポイントとなるのは,以下2点です。

  • ユーザによる同意画面での同意
  • アクセストークンの有効期限は1時間(リフレッシュトークンすると延期)

まず1点目について,この方式でAPIを利用するにはユーザによる手動での同意が必要になってきます。

そのため,今回のようなLambda上では動かせませんでした。

 

さらに2点目ですが,この方式ではアクセストークンの有効期限があります。

アクセストークンを利用し続けるには,yamlファイル中に定義された「refresh_token」にアクセスし,期限の延長が必要になります。

(これをしとけば,初めの一回の同意のみでAPIを利用できそう)

 

この方式はだいたいこんな感じです。手動での同意が必要という部分が重要ですね。

サービスアカウント方式

こちらの全体像は以下のようになります。

f:id:k12si:20190403014053p:plain

ポイントとしては以下2点です。

  • 事前にサービスアカウント(アプリケーション用のGoogleアカウントみたいなもの)を作成
  • アクセストークン生成にユーザによる同意は必要ない

まず1点目について。

GoogleAPIを利用するには,ここの理解がとても重要でした。

 

書いてある通りなんですが,サービスアカウントとはアプリケーション用に作成するGoogleアカウントのようなものです。

 

この解釈は2点目にもつながってくるのですが,アプリケーションそのものがユーザのような認識なので,ユーザによる同意も必要なくなってきます。

アプリケーションのみでアクセストークンの発行までを自己完結してくれます。

 

故に,今回のようなLambda環境でAPIを実行したい場合はこちらの認証方式を採用すべきでした。

 

事前にアプリケーションの実行環境に置いておくJSONファイルの中身は,credentials.jsonとは異なり,詳細なクライアント情報が保持されています。

 

肝心のサービスアカウント自体は,事前にユーザが作成しておきます。その際,そのサービスアカウントに付与する権限(IAM)も設定します。

 

そして,今回でいうとスプレッドシートアプリ側の管理者にもサービスアカウントを追加しておかないといけません。(このとき,本当にアカウントみたいな扱いだなと感じました。)

 

認証方式については以上です。

以下に参考にしたリンクを掲載しておきます。

実際にAPIを叩けるまでに行ったこと(Lambda + API Gateway)

まず,行ったことは以下です。

  1. 認証情報の作成 & サービスアカウントの作成
  2. Google Spread Sheet の編集権限にサービスアカウントを追加
  3. 退勤処理の関数作成
  4. S3に出勤,退勤,apiクライアントファイルを挙げる
  5. Lambda作成
  6. API Gateway作成

1,2に関しては上記でも触れたので省略します。

3に関してはソースコードを掲載しますので参考にしていただけたらと思います。

取り上げたいのは4 ~ 6です。

 

まず,4に関してですが,前記事でも述べていたように

Lambdaにアップロードできるファイルサイズには制限があります。

しかし,S3を経由すればファイルサイズが大きくてもアップロード可能となるために行っています。

 

5でLambdaを作成したのですが,注意する点としては以下です。

  • Lambdaでは呼び出す関数に`event`と`context`を引数に持たせる(必須かどうかは不明だが,指定しないと動かなかった)
  • 時刻を日本に合わせるため,環境変数を設定

気をつけるべき点としては上記くらいで,本当に簡単に動かすことができました。

 

6についても,Lambdaを作成した際,Lambda発火のトリガーを簡単に指定することができます。

1分もしないうちにLambda起動のためのエンドポイントの生成が完了しました。(すごい!!)

 

しかし,作成したAPI Gatewayのセキュリティを現状オープンにしているため後々変更しようと思っています。(今度はAWSAPI認証とかの話になってきそう😱)

結果

実際に出力された結果が以下です。

f:id:k12si:20190403022314p:plain

最後のレコード行が,実際に作成したエンドポイントを叩いて出力されている部分です。

 

最後にソースコードは以下に掲載しています。

TIL/dash_button/attendance_manager at master · k12si/TIL · GitHub

 

あとは,以前作成したDashボタンでSlack通知のSlackWebhookをエンドポイントにすればできそうです🙌

 

長くなりましたが,この辺で今日は終わりにします!👋

 

最後まで読んでいただきありがとうございました!🙇‍♂️