「DiscordのIDでログイン」を実装する(Oauth2)

# 🐼はじめに
この世にはソーシャルログインというものがある。
「GoogleIDでログイン」「TwitterIDでログイン」「FacebookIDでログイン」と言ったもので、
既に様々なサイトで利用されている。

今回は「DiscordIDでログイン」が実装できるように頑張りましょう。

### 更新
2023/02/02 更新

### 参照
 + [Discord公式リファレンス](https://discord.com/developers/docs/topics/oauth2)

# 目次
+ Discord Developer Portal にてApplicationを登録
 + 「CLIENT ID」「CLIENT SECRET」を取得
 + Oauth用URLを作成
+ 作成したURLを実行し「code」を取得する
+ 「code」を「token」に変換する
+ 「token」と共にアクセスしユーザ情報を得る
+ リフレッシュトークンでアクセスしアクセストークンを再取得する


# Discord Developer Portal にてApplicationを登録
## 「CLIENT ID」「CLIENT SECRET」を取得
Discord Developer Portal にログイン
https://discord.com/developers/applications
![Discord Developer Portal](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/7f78ff8a-b657-b592-3f8f-267cdf185565.png)
右上にある「New Application」をクリック

![Discord Developer Portal](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/91b68fa5-9e12-3632-b7f3-bf7a68d021b2.png)
任意のアプリケーション名を付けてください。

ここでは`OauthTest`とする。
「Create」をクリックするとアプリケーションの登録が完了。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/e6ec8d5b-f13d-dbd6-bee5-d683d6871f33.png)
赤枠で囲った部分が「CLIENT ID」(左)「CLIENT SECRET」(右/クリックすると表示)。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/c21ebdf9-77e4-27c8-c34a-9df83d980167.png)
このようになっている場合は 「Reset Secret」を押すことで新規に生成できる。

## Oauth用URLを作成
**自サイトに戻るときのURLを入力する。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/06ee6dc1-bcde-2334-221b-8e512d4574f7.png)


`自サイト　＞　Discordログイン画面　＞　自サイト(←ここ)`
![Discord Developer Portal](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/0993a0f3-e18b-6611-a620-f55043f63732.png)
ここでは`http://localhost:8080/afterlogin`を例とする。

下部の「SCOPE」(どういう情報が欲しいか)　にチェックを入れ、生成されたURLをコピーする。
ここでは、identify(DiscordのID番号のこと) と email を選択する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/f3cc1b44-1301-627c-9b12-423d33281623.png)
見ての通り生成されたURLは、
`https://discord.com/api/oauth2/authorize?client_id=`<font color="DeepPink">CLIENT ID</font>`&redirect_uri=`<font color="DeepPink">リダイレクト先</font>`&response_type=code&scope=`<font color="DeepPink">スコープ</font>
となっている。

# 作成したURLを実行し「code」を取得する
前項で作成したURLを実行し、URLパラメータから「code」部分の値を取得する。
検証段階ではアクセス可能ではないサイトでも良い。
**実際のシステムに組み込む場合は、戻り先ページに
1. 
次項以降の処理を行った上でリダイレクトさせる。**

認証後のURLパラメータ　（`code=`<font color="DeepPink">コード</font>）
![URL](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/1ee8001b-00cd-305b-94a7-52420aa1b70c.png)


# 「code」を「token」に変換する
以下の形式でcurlコマンドにてAPIを叩く。（赤文字は適宜置換してください）
今回はPowerShell7を使用。
>curl -X POST -H "Content-Type:application/x-www-form-urlencoded" -d "client_id=<font color="DeepPink">CLIENT ID</font>&client_secret=<font color="DeepPink">CLIENT SECRET</font>&grant_type=authorization_code&code=<font color="DeepPink">コード</font>&redirect_uri=<font color="DeepPink">リダイレクト先（認証URLのものと同一である必要あり）</font>" https://discordapp.com/api/oauth2/token

![ps7](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/f9eb0950-b24d-dcac-2165-77236f977019.png)
以下のような応答が来た場合は成功している。
>{"access_token": <font color="DeepPink">アクセストークン</font>, "expires_in": 604800, "refresh_token": <font color="DeepPink">リフレッシュトークン</font>, "scope": <font color="DeepPink">スコープ</font>, "token_type": "Bearer"}

**コードは使い捨てのため、同じコードでの再度のアクセスは不可。**

**アクセストークンの有効時間は　604800　秒、つまり１週間。
切れる前にリフレッシュトークンにて新しいアクセストークンを要求する必要あり。**

# 「token」と共にアクセスしユーザ情報を得る
アクセストークンを使用してユーザの情報を取得する。
以下の形式でcurlコマンドにてAPIを叩く。
>curl -H "Authorization: Bearer <font color="DeepPink">アクセストークン</font>" https://discordapp.com/api/users/@me

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/1c3ba0c5-94c9-c7e2-d27e-ec59e660b64d.png)
以下のような応答が来た場合は成功している。
>{"id": <font color="DeepPink">Discord ID</font>, "username": <font color="DeepPink">ユーザ名</font>, "avatar": <font color="DeepPink">アバターID</font>, "discriminator": <font color="DeepPink">ユーザ名識別番号(ユーザ名#の後ろの番号)</font>, "public_flags": 0, "flags": 0, "email": <font color="DeepPink">メールアドレス</font>, "verified": true, "locale": <font color="DeepPink">言語</font>, "mfa_enabled": false}

アイコンは
https://cdn.discordapp.com/avatars/<font color="DeepPink">Discord ID</font>/<font color="DeepPink">アバターID</font>
でアクセス可能。

# リフレッシュトークンでアクセスしアクセストークンを再取得する
以下の形式でcurlコマンドにてAPIを叩く。
>curl -X POST -H "Content-Type:application/x-www-form-urlencoded" -d "client_id=<font color="DeepPink">CLIENT ID</font>&client_secret=<font color="DeepPink">CLIENT SECRET</font>&grant_type=refresh_token&refresh_token=<font color="DeepPink">リフレッシュトークン</font>" https://discordapp.com/api/oauth2/token

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679178/d3798cf4-7b41-bd72-b68b-2b4eed0aa388.png)
以下のような応答が来た場合は成功している。
>{"access_token": <font color="DeepPink">アクセストークン</font>, "expires_in": 604800, "refresh_token": <font color="DeepPink">リフレッシュトークン</font>, "scope": <font color="DeepPink">スコープ</font>, "token_type": "Bearer"}

# 🐼最後に
「Discordでログイン」を流行らせて行きましょう。
時代はDiscord！