GoでTwitter認証をまとめてみた

こんにちわ
ゴリラです。

最近Twitter認可機能を実装する必要があって、
全く知見がないのでこの際、仕組みを理解するために記事をまとめてみました。

内容の理解に間違いがありましたら、コメントで教えてくださいm(_ _)m

# 目的
今回はより気軽にサービスを利用してもらえるように、
普段使っているSNSアカウントでサービスにログインできるすることが目的です。

Twitterだと、診断系サービスを利用する時に、
認可を行ったりすることが多いですね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/66178/89a66cd5-ad7a-0fe1-f1e3-248294477058.png)

# 認証と認可について
認証と認可の仕組みについては、こららの記事を参考にしました。

- [一番分かりやすい OAuth の説明](https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be)
- [OAuth 2.0 + OpenID Connect のフルスクラッチ実装者が知見を語](https://qiita.com/TakahikoKawasaki/items/f2a0d25a4f05790b3baa#%E8%AA%8D%E8%A8%BC%E3%81%A8%E8%AA%8D%E5%8F%AF)

TwitterはOAuthという認可の仕組みを使用しています。
ここで一つポイントですが、「OAuthは認証の仕組み」ではないということです。
OAuthは「認可の仕組み」であり、**「認証が目的ではない**」です。

今回は**Twitterユーザのデータを取得する権限をアプリ側に付与する**ために、認可の仕組みを実装します。

# Twitterでの認可
参考記事で認証・認可の大枠を掴んだどころで、必要なものを整理します。

必要なものは以下２つです。

- コンシューマキー
- アクセストークン

今回やりたいのは「Twitterアカウントでアプリケーションにログインする」ことです。
なのでアプリケーション側でログインしようとするユーザの情報を取得して、保存する必要があります。

ただ、どのアプリケーションでも好きにTwitterからユーザ情報をリクエストできるわけではなく、
Twitterにアプリケーションのプロジェクトを登録して、**コンシューマキー**というのを取得する必要があります。
コンシューマキーは、**Twitterがアプリケーションを認識するための一意なもの**です。
Twitter側がアプリを識別できないと、悪さをするアプリがあった場合特定＆対処できないので、
サービスの健全性を維持するためにも必要ですね。

次に、ユーザのリソースを取得するのにまずユーザのアクセストークンを取得する必要があります。
参考記事にあったように、アクセストークンはを用いることで、ユーザのリソースを取得することができます。

[公式のドキュメント](https://developer.twitter.com/en/docs/basics/authentication/overview/3-legged-oauth)を見ると、アクセストークンを取得するまでの流れは以下になります。

1. **callback url**と**consumer api key**を`POST https://api.twitter.com/oauth/request_token`して、リクエストトークン(**oauth_token**と**oauth_token_secret**)と**oauth_callback_confirmed**を取得する。HTTPステータスコードが200かどうかを確認する。
2. **oauth_callback_confirmed** がtrueになっていれば、**oauth_token**, **oauth_token_secret** をセッションに保存する。
3. `GET https://api.twitter.com/oauth/authorize?oauth_token={{oauth_token}}`で認可（未ログインの場合はログイン画面）に遷移する。
4. 認可が完了したら、**oauth_token**と**oauth_verifier**を含んだ状態で、callback_urlにリダイレクトされる。
5. 4で帰ってきた**oauth_token**と2でセッションに保存した**oauth_token**を比較して、同じであることを確認する。
6. **consumer api key**と**oauth_token**と**oauth_verifier**を含んで`POST https://api.twitter.com/oauth/access_token`でアクセストークン(**oauth_token**と**oauth_token_secret**)を取得する。

# Twitterにアプリを登録する方法
[こちらの記事](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)を参考にしてみてください。
ぼくの場合は一瞬で許可降りました。
ユーザのプロフィールしか使わないからかな…？

# アプリでの大まかの流れ
フロントはSPAでvue.jsを使っています。
vue.jsだけでOAuth認可だと、アプリのコンシューマキーをサーバーから取得する必要があり、漏れるリスクが増えます。
サーバーだけで処理を完結したいのですが、フロントでTwitterの認可画面に遷移する必要があるので、以下の様に実装してみました。

1. ログインボタンを押して、認可APIをコールする
2. 認可API内で1、2を処理して、Twitter認可画面のURLを返却する
3. 2で受け取った認可URLをjs側で画面遷移させる（location.herf)
4. ユーザが認可ボタンをポチッと押して4の通り予め設定したcallback_urlに遷移する
5. callback_url自体はAPIのエンドポイントにして、5、６の処理を行い、アクセストークンを取得する
6. アクセストークンをDBなりセッションなりに保存して、画面側に200ステータスコードを返してログイン後の画面に遷移する

# 実装
今回API側の実装に用いたフレームワークは以下になります。

- [Echo](https://echo.labstack.com/guide)
軽量ウェブフレームワーク
- [Gorm](http://doc.gorm.io/)
ORMフレームワーク
- [oauth](https://github.com/gomodule/oauth1)
Oauthライブラリ

そして、サンプルはこちらです。
ソースを見て頂ければ、大体わかると思いますのでソースに関する説明は省かせていただきます。
https://github.com/skanehira/vue-go-oauth

サンプルはこんな感じです。
![twitter-oauth.gif](https://qiita-image-store.s3.amazonaws.com/0/66178/6ce53c15-7d83-5c37-7af4-f1c18adcaa17.gif)

# まとめ
Twitterの認証・認可について大まかの流れは理解しましたが、
トークンとシークレットを必要とする意味など、理解しきれていないので、
引き続きそこらへんを勉強していきます。

この記事は、GoでTwitterの認証認可を実装したいけどよくわからない方に役に立てたらと思います。