5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Golang + AWS APIGateway & Lambda & DynamoDB + TwitterAPIでサーバーレスなログイン機能

Last updated at Posted at 2019-03-02

概要

・Go言語を触りたい
・AWS Lamda & APIGateway使いたい
・TwitterAPI使ってみたい
という願望があったので、全てをまとめてサーバーレスでTwitterログインをできる環境を作ってみた。

結論

実際に稼働させるにはまだまだ課題があるものの、一通り動いてくれるものができた。
AWSもAPIも楽しいので、もっと遊んでいきたい。

できたページ
https://mb8mab272h.execute-api.us-east-2.amazonaws.com/twimal/login
リポジトリ(不要なものが多いため、そのうち作り直します。。)
https://github.com/CHooooCLate/protoTwiM/tree/master/tweet_src

機能

・Twitterログイン
・CookieとSessionによるログイン状態の保持
・ログアウト

実装内容

共通

APIGateway

リクエスト

URLクエリ文字列パラメータを使いたい場合、「メソッドリクエスト / URLクエリ文字列パラメータ」で名前を設定、「統合リクエスト / マッピングテンプレート」に下記のように記載します。

URLクエリ文字列パラメータのマッピングテンプレート
{
    "oauth_token": "$input.params('oauth_token')",
    "oauth_verifier": "$input.params('oauth_verifier')"
}

スクリーンショット 2019-02-21 14.38.07.png
スクリーンショット 2019-02-21 14.38.47.png
スクリーンショット 2019-02-22 10.18.16.png

Cookieの内容はリクエストとして送られてくるため、「メソッドリクエスト / HTTPリクエストヘッダー」で「Cookie」を指定する。
さらに、「統合リクエスト / HTTPヘッダー」で名前に「Cookie」、マッピング元に「method.request.header.Cookie」を指定する。
これをLambda上のGoで扱えるよう、マッピングテンプレートに「application/json」を指定して下記を記載する。

Cookieのマッピングテンプレート
{
    "Cookie": "$input.params().header.Cookie"
}
レスポンス

Lambdaからのレスポンス方法は後述しますが、Lambdaのレスポンスで指定した名前で扱います。
APIGatewayの「統合レスポンス / ヘッダーのマッピング」で「レスポンスヘッダー」にレスポンスヘッダーで使いたい名前、「マッピングの値」に「integration.response.body.(Lambdaで指定した名前)」を指定します。
これによって、レスポンスヘッダーにLcationでリダイレクト先のURLの指定やSet-CookieでCookieの指定などができるようになります。
スクリーンショット 2019-02-21 19.05.19.png
スクリーンショット 2019-02-21 19.05.36.png

また、Lambdaの出力結果にHTMLを含ませたい場合には、「統合レスポンス / マッピングテンプレート」に「application/json」を指定して下記を指定します。

マッピングテンプレート
# set($inputRoot = $input.path('$'))
  
$inputRoot

さらに、「メソッドレスポンス / 200のレスポンス本文」の「コンテンツタイプ」は「text/html」、「モデル」に「Empty」を指定することでHTMLとして返ります。
スクリーンショット 2019-02-21 19.06.07.png

Lambda

以下に気をつけてLambda関数を作成します。
・ランタイムは「Go 1.x」
・ディレクトリごとzip化した場合は、ハンドラは「ディレクトリ名/コンパイル後のファイル名」とする。
・DynamoDBを操作する関数なら、実行ロールにはDynamoDBの操作権限を持ったロールを指定する。(なければ新たに作成)
また、.envなど、ソース以外のファイルを入れることも可能です。この場合、絶対パスは「/var/task/」以下になります。
Goでレスポンスを指定する場合、下記のように構造体を作成して返り値とします。
APIGatewayで使用する場合には、json:"name"の部分の「name」がキーになります。

レスポンスの構造体例
type Response struct {
    Location string `json:"location"`
    Cookie string `json:"cookie"`
}

スクリーンショット 2019-02-21 19.06.55.png

DynamoDB

下記2つのテーブルを作成した。
・TwitterAPI利用時の一時トークンを格納するTokenテーブル(id, oauth_token, secret_token, register_date)
・ユーザーごとのアクセストークンを格納するSessionテーブル(id, access_token, secret_token, register_date)
各テーブルのインデックスがidに指定されており、このidを使って呼び出している。
スクリーンショット 2019-02-21 19.07.51.png

ログイン

login

ソース : https://github.com/CHooooCLate/protoTwiM/blob/master/tweet_src/login.go
・TwitterAPI利用申請時に取得したCONSUMER_KEYとCONSUMER_SECRETを使用してTwitterAPIから一時トークンを取得
・一時トークンを使用して、TwitterAPIからログインページのURLを取得
・上記で使用した一時トークンをセッションとしてDynamoDBへ保存
・セッションのIDをCookieとしてユーザーに保存
・ログインページのURLへリダイレクト

callback

ソース : https://github.com/CHooooCLate/protoTwiM/blob/master/tweet_src/callback.go
・loginで使用した一時トークンをCookieのidを元にDynamoDBから取得し、URLクエリ文字列パラメータとして渡される一時トークンと同じであることを確認する
・一時トークンとURLクエリ文字列パラメータに含まれる認証用トークンを使用して、ユーザーのアクセストークンをTwitterAPIから取得する
・アクセストークンをDynamoDBへ保存する
・アクセストークンに紐付けたセッションIDをCookieとしてユーザー側に保存
・マイページへリダイレクト

マイページ

mypage

ソース : https://github.com/CHooooCLate/protoTwiM/blob/master/tweet_src/mypage.go
・アクセストークンをCookieのidを元にDynamoDBから取得
・アクセストークンを使用して、ユーザー情報を取得する
・特定の項目(ここでは「screen_name」のみ)を取り出して、HTMLを返す
・セッションIDを新たに作り直し、DynamoDBとCookieを更新

ログアウト

logout

ソース : https://github.com/CHooooCLate/protoTwiM/blob/master/tweet_src/logout.go
・Cookieからidを取得
・DynamoDBから対象のアクセストークンを削除
・ユーザーのCookieを削除

まとめ

当初は「AWS APIGateway + Lambda + DynamoDBでログイン機能」を考えていたが、すでにnode.jsで実現した記事が存在したため、TwitterAPIを取り入れた。
結果としては、予定していた機能は一通り実装でき、AWSとAPIを使ったことで見た目としては十分なものができた。
ただ、同じ処理を何回も書いてしまっているという点では不十分だったため、今後の課題としてはコードの設計をより強化して行きたいと考えている。

参考

【PHP】新TwitterOAuthでログイン機能を実装する
Go言語でGoogle,Twitter,FacebookのOauth認証をしてメールアドレスを取得するまで
GolangでTwitterのOAuth1.0認証
【PHP超入門】Cookieとセッションについて
API GatewayでCookieを扱う
気楽にDynamoDBを使おう
AWS Lambdaにクエリ文字列(get値)を引数で渡すトリガを設定する
AWS Lambda, API Gateway, DynamoDB, Golang でREST APIを作る

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?