Python/Django による OAuth/OIDC サーバー

Python 用の Web フレームワークである **[Django](https://www.djangoproject.com/)**（ジャンゴ）で、OAuth 2.0 および OpenID Connect 対応の認可サーバー / OpenID プロバイダーを作るのも、**[Authlete](https://www.authlete.com/ja/)**（オースリート）をバックエンドに使えば簡単です。

# 1. 準備

## 1.1. ライブラリインストール

```shell-session
$ pip install authlete
$ pip install authlete-django
```

| ライブラリ | GitHub | PyPI |
|:--|:--|:--|
| authlete | [authlete-python](https://github.com/authlete/authlete-python) | [authlete](https://pypi.org/project/authlete/) |
| authlete-django | [authlete-python-django](https://github.com/authlete/authlete-python-django) | [authlete-django](https://pypi.org/project/authlete-django/)


## 1.2. Authlete アカウント

Authlete に[アカウント登録](https://so.authlete.com/accounts/signup)をおこない、事前にサービス API キー、サービス API シークレット、クライアント ID を取得しておいてください。詳細手順は[こちら](https://qiita.com/TakahikoKawasaki/items/18d5b05dabe246fb239e#3-%E6%8A%80%E8%A1%93%E8%A9%B3%E7%B4%B0)。


# 2. 認可サーバー

## 2.1. サンプル実装ダウンロード

```shell-session
$ git clone https://github.com/authlete/django-oauth-server.git
$ cd django-oauth-server
```


## 2.2. 設定

```shell-session
$ vi authlete.ini
```

※ Authlete から取得したサービス API キーとサービス API シークレットを設定します。


## 2.3. テスト用アカウント作成

```
 $ python manage.py migrate
 $ python manage.py shell
 >>> from django.contrib.auth.models import User
 >>> user = User()
 >>> user.username = 'john'
 >>> user.first_name = 'John'
 >>> user.last_name = 'Smith'
 >>> user.email = 'john@example.com'
 >>> user.set_password('john')
 >>> user.is_active = True
 >>> user.save()
 >>> quit()
```

※ Django に標準で入っている django.contrib.auth を用いています。


## 2.4. 起動

```
$ python manage.py runserver 8000
```


# 3. リソースサーバー


## 3.1. サンプル実装ダウンロード

```shell-session
$ git clone https://github.com/authlete/django-resource-server.git
$ cd django-resource-server
```


## 3.2. 設定

```shell-session
$ vi authlete.ini
```

※ Authlete から取得したサービス API キーとサービス API シークレットを設定します。


## 3.3. テスト用アカウント作成

```
 $ python manage.py migrate
 $ python manage.py shell
 >>> from django.contrib.auth.models import User
 >>> user = User()
 >>> user.username = 'john'
 >>> user.first_name = 'John'
 >>> user.last_name = 'Smith'
 >>> user.email = 'john@example.com'
 >>> user.set_password('john')
 >>> user.is_active = True
 >>> user.save()
 >>> quit()
```

※ Django に標準で入っている django.contrib.auth を用いています。


## 3.4. 起動

```
$ python manage.py runserver 8001
```

※ 認可サーバーのポート番号とぶつからないよう、8001 を指定しています。


# 4. 動作確認

## 4.1. アクセストークン発行

Web ブラウザを起動し、アドレスバーに次の URL（認可リクエスト）を入力してください。「{クライアントID}」の箇所は適宜置き換えてください。

```
http://localhost:8000/api/authorization?client_id={クライアントID}&response_type=token
```

認可ページが表示されるので、ログイン ID 入力欄とパスワード入力欄に、両方とも `john` を入力し、Authorize ボタンを押してください。（「テスト用アカウント作成」の手順でアカウント作成済みであることを想定しています。）

次のような画面が表示されたら成功です。`access_token` の右隣にある値が発行されたアクセストークンです。

|![redirection_endpoint_with_access_token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106044/72d5e0b3-b68b-c55a-0fbf-ad0962ac26e2.png)|
|:-:|


## 4.2. API コール

発行されたアクセストークンを用いて、リソースサーバーに API コールを行います。「{発行されたアクセストークン}」の箇所は適宜置き換えてください。

```shell-session
$ ACCESS_TOKEN={発行されたアクセストークン}
$ curl -v http://localhost:8001/api/time \
       -H "Authorization: Bearer ${ACCESS_TOKEN}"
```

次のような出力が得られれば成功です。

```json
{
  "year":   2019,
  "month":  8,
  "day":    9,
  "hour":   14,
  "minute": 45,
  "second": 2
}
```


# おわりに

OAuth 2.0 と OpenID Connect の難しい処理は全て、Authlete のサーバー側で処理されます。そのため、Authlete をバックエンドとして用いると、フロントエンドの認可サーバーとリソースサーバーの実装は簡単になります。このため、フロントサーバー開発者は、ユーザー管理やログイン処理など、OAuth 2.0 と OpenID Connect 以外の部分の開発により多くのリソースを割くことができるようになります。

Authlete は、下記の [OpenID Certification](https://openid.net/certification/) を取得済みです。

* Basic OP
* Implicit OP
* Hybrid OP
* Config OP
* Dynamic OP
* Form Post OP
* FAPI R/W OP w/ MTLS
* FAPI R/W OP w/ Private Key

これらに加えて、[CIBA](https://qiita.com/TakahikoKawasaki/items/9b9616b999d4ce959ba3) や Device Flow（[RFC 8628](https://tools.ietf.org/html/rfc8628)）、[JARM](https://openid.net/specs/openid-financial-api-jarm-ID1.html) など、世界最先端の仕様も実装済みです。

是非 Authlete の利用をご検討ください！ :arrow_forward: :arrow_forward: :arrow_forward: [お問い合わせフォーム](https://www.authlete.com/ja/contact/)