Flaskを使ってDiscordのOAuth2認証をする

# OAuth2認証とは？
インターネット上で安全にアクセス権を委譲するための認可フレームワーク。あるアプリがユーザーのGoogleアカウントの一部の情報（メールアドレスなど）にアクセスしたい場合に、ユーザーのパスワードを教えずにそのアクセスを許可するための仕組み。Googleでログインなどの機能がこれにあたる。
内部的にはサービス側にパスワードを教えることなく認証にも使うことができるので安全である。

# OAuth2認証をしてみよう
文章で理解するよりも実際に手を動かしたほうが理解力が高まると思うので実際にコードを書いてみましょう。
今回使用するフレームワークはFlaskです。似たようなフレームワークにDjangoというものがありますがあちらは高性能高機能に対し、Flaskは軽量手軽なことがメリットとしてあげられる。ここではPythonのインストールが終わっていてpipが利用できることを想定する

# OAuth2認証に必要なclient secretとclient idを入手しよう
https://discord.com/developers/applications にアクセスし、ログインをしたあとに左上のNew Applicationを押す
![2025-04-24_00h59_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058165/29efc0cf-b740-4e33-8d71-fecb026bbc3b.png)

By clicking Create, you agree to the Discord にチェックを入れてアプリケーションの名前を作る。ここでは例としてtestAppと名付ける。
![2025-04-24_01h01_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058165/a09061cb-30dc-44fd-b47b-33ac4501155a.png)
この画面が出たら成功だ。
次に画面左のOAuth2を押す。ここでClient informationに書いてあるClient IDをコピーしテキストエディタ等にメモしておく、その後Reset Secretを押すと下のようにでるのでYes do it!を押したあとDiscordをログインするときのパスワードを入力する。
![2025-04-24_01h03_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058165/6f3e9a8e-2b60-467d-9380-706b225fc1ac.png)

![2025-04-24_01h04_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058165/335818b3-7b1a-4498-b28b-f03a69b26edb.png)
その後Client secretも見れる状態になっていると思うのでこれもメモしておく。

# callbackのurlを設定しよう
色々なサービスでGoogleにログインするときなど、ログインした後に自動でログインしたいサービスのURLへリダイレクトされると思うがここではDiscordでログインした後にリダイレクトされるURLを設定する。OAuth2の仕様上、ここのURLへ、リクエストクエリが追加されてFlaskに情報が渡される。詳しくは後で見る。
上のclient idとclient secretを取得した画面のまま、画面下部までスクロールすると以下のようなものがあるはずだ
![2025-04-24_01h11_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058165/9dec1e59-bc4d-4089-b442-352427858a4b.png)
ここでリダイレクトされるurlを設定することができる。
![2025-04-24_01h09_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4058165/5bf50f4c-89a4-48b4-94c6-468a989eb86d.png)
ここでは開発用にhttp://localhost:5100/callback と設定する。これは複数追加することができ、リダイレクトするURLその中から選択することもできる。

# PythonでFlaskのプログラムを作ってみよう
今回はFlaskを使うのでまず、Flaskをインストールする。また、Discordサーバーと通信するためにrequestsと呼ばれる超定番ライブラリもインストールする。

```
pip install flask requests
```
これでインストールは完了となる。


ここまででclient id、client secretをメモしてあるはずだ。これをPythonのプログラム内では変数としてCLIENT_SECRET、CLIENT_IDとする。



```app.py
from flask import Flask, redirect, request
import requests
import os

app = Flask(__name__)

CLIENT_ID = '自分のメモを参照する'
CLIENT_SECRET = '自分のメモを参照する'
REDIRECT_URI = 'http://localhost:5100/callback'
OAUTH_SCOPE = 'identify email'

DISCORD_AUTH_URL = 'https://discord.com/api/oauth2/authorize'
DISCORD_TOKEN_URL = 'https://discord.com/api/oauth2/token'
DISCORD_API_URL = 'https://discord.com/api/users/@me'

@app.route('/')
def login():
    return redirect(
        f"{DISCORD_AUTH_URL}?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&response_type=code&scope={OAUTH_SCOPE}"
    )

@app.route('/callback')
def callback():
    code = request.args.get('code')
    data = {
        'client_id': CLIENT_ID,
        'client_secret': CLIENT_SECRET,
        'grant_type': 'authorization_code',
        'code': code,
        'redirect_uri': REDIRECT_URI,
        'scope': OAUTH_SCOPE,
    }
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    # トークン取得
    response = requests.post(DISCORD_TOKEN_URL, data=data, headers=headers)
    response.raise_for_status()
    access_token = response.json()['access_token']

    # ユーザー情報取得
    user_info = requests.get(
        DISCORD_API_URL,
        headers={
            'Authorization': f'Bearer {access_token}'
        }
    ).json()

    return f"<pre>{user_info}</pre>"

if __name__ == '__main__':
    app.run(debug=True,port=5100)
```

ここまでプログラムを入力したら
```
python3 app.py
```
と入力するとflaskが起動する。
その後、http://localhost:5100/callback にアクセスするとDiscordのログインが求められ認証すると取得したユーザー情報が確認できる。