FastAPIでOAuth2を体験する

# はじめに
最近FastAPIにハマっています。直観的にコードが書けるところやSwaggerを自動生成してくれるところに魅力を感じています。
また[公式ドキュメント](https://fastapi.tiangolo.com/ja/)いわく
> 高速: NodeJS や Go 並みのとても高いパフォーマンス (Starlette と Pydantic のおかげです)。 最も高速な Python フレームワークの一つです.

と性能もかなり高水準なようです!!
SQLAlchemy2.0以降はDBとの非同期接続に対応しており、より高速な処理が期待できそうです。

FastAPIにはOAuth2が組み込まれており、簡単にOAuth2認証を実装できます。
今回はFastAPIを使用して、タスク管理アプリを例にOAuth2認証を体験したいと思います。

# 概要
FastAPIの[公式チュートリアル](https://fastapi.tiangolo.com/ja/tutorial/security/)にはOAuth2の実装方法が書いてあるのですが少し読みづらい部分があります。
Githubにコードをあげているので、こちらも参考にしていただければ幸いです。

https://github.com/Tanakaryuki/FastAPI_OAuth2

FastAPIの実装に関しては以下の記事を参考にしています。

https://zenn.dev/sh0nk/books/537bb028709ab9

この記事では、ファイル分割やテストコードなど必要な情報が網羅されておりチュートリアルとしてお勧めです。

# OAuth2がなかったらどうなるのか
まず、OAuth2を使用しないでAPIを設計すると、どのような問題が生じるかを体験してみましょう。
```
$ git clone https://github.com/Tanakaryuki/FastAPI_OAuth2.git
$ cd FastAPI_OAuth2
$ git checkout fix
$ docker-compose build
$ docker-compose up
```
[localhost:8000/docs](http://localhost:8000/docs)にアクセスするとSwaggerが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/71690e77-cbf7-cbe0-7e86-853638db4ede.png)

始めにアカウント作成をしてみましょう。
`/api/signup`から`Try it out`をクリックし、現れた`Execute`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/1a41f61f-b9e7-2062-c5df-bfebf96521c6.png)
下の画像のようになっていたら成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/ac667ed3-5fb4-b080-d2cb-3cbca9cf868d.png)

次にタスクを作成してみましょう。
`/api/task`からタスクを作成出来ます。
`administrator_username`は先ほど作成したアカウントの`username`を利用してください。
`id`は記録しておいてください。

下の画像のようになったら成功です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/7dbdfef5-3a43-6443-1797-33596a86c374.png)

通常、ユーザの情報はユーザ自身しか閲覧できません。しかし、現状APIを実行することで誰でも閲覧できる状態にあります。
現に`/api/task/{id}`から誰でも閲覧可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/9a9211bb-55fe-c73f-8cc3-ac86199c03ca.png)

このままでは個人情報が保護されません。
そこで登場するのがOAuth2です。さっそく利用してみましょう。

# OAuth2があったらどうなるか
それではOAuth2が実装されているブランチに移動してみましょう。
このブランチでは、タスクの作成・取得にOAuth認証が必要になります。
```
$ git checkout main
```
OAuth2を利用する際にはJWTトークンの署名に使用されるランダムな秘密鍵が必要になりますので、以下のコマンドで生成します。
```
$ openssl rand -hex 32
```
生成した秘密鍵を保存したら.env.sampleを参考にして.envファイルを作成します。
以下を例に入力してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/0d4a820d-3ac3-5135-7105-f7e0cb216915.png)
SECRET_KEYには先ほど作成した秘密鍵を配置してください。

設定が完了したら起動してみましょう。
```
docker-compose up
```
起動に成功したら以下のような画面が表示されるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/d64b1c09-6896-2d49-417c-e344d8730ce5.png)

先ほど作成したタスクを`/api/task/{id}`から取得してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/19960e97-30e9-a456-c1fd-e120cab3784f.png)

認証エラーが返ってきました。

次に認証してからタスクを取得してみましょう。
右上にある鍵アイコンをクリックします。
usernameとpasswordを求められるので入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/41995644-a6eb-0886-fa86-53fbb829cd62.png)
入力が完了したら`Authorize`をクリックします。
認証が完了したら以下の画像のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/469afaf4-6405-4ec7-e31f-b09e2ed86b5b.png)

もう一度タスクを取得してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1133847/e3655341-c299-93d0-5510-3d0b2358c102.png)
これでタスクを正常に取得出来ました。

# OAuth2を利用するメリット
### セキュリティの向上
OAuth2は高度なセキュリティ機能を提供する認証プロトコルであり、ユーザの認証情報を安全に管理できます。
トークンベースの認証を採用することで、アクセストークンが漏洩しても被害範囲を抑えることが可能です。

### アクセス制限
OAuth2はアクセストークンを使用してアクセス制限を効果的に管理できます。これによりクライアントがどのリソースにアクセスできるかを制限し、セキュリティを向上させることができます。

### 外部サービスとの統合
OAuth2は標準化されたプロトコルであり、多くの開発者やサービスが採用しています。
これにより異なるアプリケーションやサービス間での相互運用性が向上し、外部サービスとの統合が容易になります。

# まとめ
今回、OAuth2を利用してセキュアなAPIを実現する過程を体験しました。
FastAPIとOAuth2を組み合わせることで、高い開発生産性とセキュアな認証・認可の仕組みを構築することが可能です。
またFastAPIはスキーマ設計と相性がとても良いので、是非触ってみて欲しいです。