Auth0 management APIでClientを登録する

## 0.はじめに

以前、[こんな記事](https://qiita.com/OtsukaTomoaki/items/916be8ff24ecd822e2b5)を書きましたが、Auth0でClient自体をAPIで登録する方法について追加で調べました。

## 1. management APIの Domain, Client ID, Client Secretを取得する
Auth0のダッシュボードの>Applicationから任意のアプリケーションを選択し`Settings`の`Basic Information`から`Domain`, `Client ID`, `Client Secret`を取得します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/77dcc62a-68e5-37d5-b7ee-39549b492bf1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/969056e4-2703-3bbc-4888-1d744d6b190a.png)

## 2. apiからclientを登録する

今回はPythonでコードを書いてみました。
clientを登録して利用できるまでのステップとしては以下になります。
- Domain, Client ID, Client Secretからアクセストークンを取得する
- アクセストークンを使ってClient作成APIにリクエストする
- 登録したClientにGrantを登録するAPIにリクエストする

### Domain, Client ID, Client Secretからアクセストークンを取得する
事前に取得した Domain, Client ID, Client Secretからアクセストークンを取得します。
以下はサンプルコードで環境変数にDomain, Client ID, Client Secretが登録されているものとします。

```python
import os
from dotenv import load_dotenv
import requests

class FetchManagementApiTokenService:
    def __init__(self, url, client_id, client_secret):
        self.url = url
        self.client_id = client_id
        self.client_secret = client_secret

    def fetch_token(self):
        fetch_token_url = f'{self.url}/oauth/token'

        headers = {
            'content-type': 'application/json'
        }
        request_body = {
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'audience': f'{self.url}/api/v2/',
            'grant_type': 'client_credentials'
        }

        response = requests.post(fetch_token_url, headers=headers, json=request_body)
        response.raise_for_status()
        return response.json()['access_token']

load_dotenv()
url = os.environ['AUTH0_MANAGEMENT_URL']
client_id = os.environ['AUTH0_MANAGEMENT_CLIENT_ID']
client_secret = os.environ['AUTH0_MANAGEMENT_CLIENT_SECRET']
service = FetchManagementApiTokenService(url=url, client_id=client_id, client_secret=client_secret)
token = service.fetch_token()
print(token)
```

実行してみるとjwt形式のアクセストークンが取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/17eaca4a-d77c-5329-9be8-6d7268236acd.png)


### アクセストークンを使ってClient作成APIにリクエストする
次にこのアクセストークンから[Client作成API](https://auth0.com/docs/api/management/v2/clients/post-clients)にリクエストします。


```python
class CreateClientService:
    def __init__(self, url, token):
        self.url = url
        self.token = token

    def create_client(self):
        create_client_url = f'{self.url}/api/v2/clients'

        headers = {
            'content-type': 'application/json',
            'authorization': f'Bearer {self.token}'
        }

        # 登録するClientの情報。各パラメータは以下を参照
        # https://auth0.com/docs/api/management/v2/clients/post-clients
        body = {
            'name': 'my-new-client',
            'app_type': 'non_interactive',
            'jwt_configuration': {
                'alg': 'RS256',
                'lifetime_in_seconds': 36000
            }
        }

        response = requests.post(create_client_url, headers=headers, json=body)
        print(response.json())
        response.raise_for_status()
        return response.json()

# tokenは前のセクションで取得したアクセストークンを代入してください。
service = CreateClientService(url, token)
service.create_client()
```

実行してみると以下のレスポンスが得られます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/76235a26-13c7-65af-1620-70de194b555a.png)

このJSONの中にclient_id, Client_secretが含まれるためそれぞれ取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/d6cbfc98-22bb-4f74-bcaa-5b265351e3f9.png)

またダッシューボードの`Applications`を確認すると指定したClientが登録されていることが確認できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/f096aee4-5e62-46bf-f36a-9a5afaadf062.png)


### 登録したClientにGrantを登録するAPIにリクエストする
次にこのアクセストークンと登録したClient IDから[Client-Grants作成API](https://auth0.com/docs/api/management/v2/client-grants/post-client-grants)にリクエストします。

このAPIを使用することによって登録したClientを使って操作できるリソースを選択することができます。

```python
class CreateClientGrantsService:
    def __init__(self, url, client_id, token):
        self.url = url
        self.client_id = client_id
        self.token = token

    def create_client_grants(self):
        update_client_grants_url = f'{self.url}/api/v2/client-grants'

        headers = {
            'content-type': 'application/json',
            'authorization': f'Bearer {self.token}'
        }

        # このClientで取得したいリソースの内容をscopeに記載します。
        # 今回はユーザの読み取りをつけます。
        body = {
            'client_id': self.client_id,
            'audience': f'{self.url}/api/v2/',
            'scope': ['read:users']
        }
        print(body)

        response = requests.post(update_client_grants_url, headers=headers, json=body)
        print(response.json())
        response.raise_for_status()
        return response.json()

# client_idは前回のコードのjsonから取得してください
service = CreateClientGrantsService(url, client_id, token)
```
実行すると以下のようなレスポンスを取得でき、scopeにもユーザの読み取りが設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/769e91a4-9ee6-94e1-6e74-45f29183db10.png)

Auth0で該当のClientのPermissionsを確認すると`read:users`に✅がついています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2527942/edbc365a-4cec-66be-46ef-123f393ea002.png)


ClientをAPIで登録し、使用できるようにするまでの手順は以上です。
あとは以前書いた[この記事](https://qiita.com/OtsukaTomoaki/items/916be8ff24ecd822e2b5#2clientcredentialsflow%E3%81%AB%E3%82%88%E3%82%8B%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97)に書いてある方法で、登録したClientからアクセストークンの取得とリソースの取得が行えるようにないます。

## 3.おわりに

Auth0便利🎉
機会があったら別の機能も使ってみます。