> ## Documentation Index
> Fetch the complete documentation index at: https://developers.authlete.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Userinfo API のレスポンスに任意のクレームを追加する

> Userinfo API に追加するクレームの判別と追加方法

## はじめに

Userinfo API が応答するクレームは [ID トークンに任意のクレームを追加する方法](/ja/configuration-reference/tokens-and-claims/adding-claims-to-an-id-token/) と同様に、claims パラメータを利用することでカスタマイズできます。

この記事では Userinfo エンドポイントのレスポンスに任意のクレームを追加する方法と、クレームの決定に役立つ Authlete の機能について解説します。

## 基本的な Userinfo エンドポイントの実装

OpenID プロバイダーが Authlete を利用し Userinfo API エンドポイントを実装する場合、以下の 2 つの API を呼び出す必要があります。

* Userinfo Request [/api/\{serviceId}/auth/userinfo](/api-reference/userinfo-endpoint/process-userinfo-request)
* Issue Userinfo Response [/api/\{serviceId}/auth/userinfo/issue](/api-reference/userinfo-endpoint/issue-userinfo-response)

Authlete の Userinfo Request エンドポイントはアクセストークンを提示することにより、アクセストークンの検証をしたうえで、トークンに紐づくユーザーの情報を応答します。
OpenID プロバイダーは Userinfo Request の応答からトークンの有効性と紐づいたユーザーを確認し、対象ユーザーの属性をデータストアから収集し、Issue Userinfo Response API に提示します。

### Userinfo Request API の呼び出し例

具体的な例は以下の通りです。まず OpenID プロバイダーはユーザーが提示したアクセストークンを Authlete の Userinfo Request API に送信します。

```sh theme={null}
curl --request POST \
  --url https://jp.authlete.com/api/{{serviceId}}/auth/userinfo \
  --header 'authorization: Bearer {{serviceAccessToken}}' \
  --header 'content-type: application/json' \
  --data '{"token": "{{accessToken}}"}'
```

アクセストークンが有効な場合の応答例は以下の通りです。

```sh theme={null}
{
  "action": "OK",
  "clientId": 2064424232,
  "subject": "john",
  "scopes": [
    "openid",
    "email"
  ],
  "claims": [
    "email",
    "email_verified"
  ],
  "token": "{{accessToken}}",
  "clientIdAlias": "2064424232",
  "clientIdAliasUsed": true,
  "consentedClaims": [
    "email",
    "email_verified"
  ],
  "clientEntityIdUsed": false,
  "resultCode": "A091001",
  "resultMessage": "[A091001] The access token presented at the userinfo endpoint is valid."
}
```

この例では `action` が `OK` でトークンが有効であることが示され、さらに `subject` が `john` であると判別できるため、 OpenID プロバイダーは `john` に紐づく属性を収集し、 Issue Userinfo Response に提示します。

### Issue Userinfo Response の呼び出し例

Authlete はユーザーに紐づく属性の値は保持しないため、Userinfo エンドポイントの応答に含める属性の値は OpenID プロバイダーが用意する必要があります。一方、OpenID プロバイダーは Userinfo に含める属性を決定するために Authlete が応答する `claims` パラメータを利用できます。

Userinfo Request API の 応答に含まれる `claims` パラメータは [IDトークンに追加する「クレーム」の判別](/ja/configuration-reference/tokens-and-claims/identifying-claims-expected-to-be-included-into-an-id-token) と同様に、`/auth/authorization` エンドポイントに提示された parameters 内の [スコープ（scope）に対応するクレーム](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims) と、[claims パラメーターを用いて個別に指定される](https://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter)クレームがマージされたリストです。

例えば上記例では `scope` に `openid` `email` が含まれていたため、`email` スコープが展開され `email`, `email_verified` が含めるべきクレームとして `claims` 応答に含まれます。スコープとそれに対応するクレームの一覧は Authlete Java Common の Javadoc [ClaimsScope](https://authlete.github.io/authlete-java-common/com/authlete/common/types/ClaimsScope.html) をご確認ください。

ここでは OpenID プロバイダーが Authlete からの応答 `claims` に含まれる以下の項目を Userinfo レスポンスに追加する例を示します。

| 項目                | 値                                             |
| ----------------- | --------------------------------------------- |
| "email"           | "[john@example.com](mailto:john@example.com)" |
| "email\_verified" | true                                          |

上記のクレームを追加する場合のリクエストは以下のようになります。(読みやすさのため折り返しています。)

```sh theme={null}
curl --request POST \
  --url https://jp.authlete.com/api/{{serviceId}}/auth/userinfo/issue \
  --header 'authorization: Bearer {{serviceAccessToken}}' \
  --header 'content-type: application/json' \
  --data '{"token": "{{accessToken}}",
    **"claims": "{
      \"email\": \"john@example.com\",
      \"email_verified\": true}"** }'
```

正常な応答は以下の通りです。`responseContent` のクレームに指定したクレームが追加されていることが確認できます。

```json theme={null}
{
  "action": "JSON",
  "responseContent": "{\"sub\":\"john\",\"email\":\"john@example.com\",\"email_verified\":true}",
  "resultCode": "A096001",
  "resultMessage": "[A096001] User information was obtained successfully."
}
```

## 含めるべきクレームのリストをカスタマイズする

Authlete が自動で計算する `claims` は OpenID Connect Core の仕様に則したものですが、実際の運用環境には適さない場合があります。例えば ID トークンに含めるクレームと異なるクレームを Userinfo から返したい、`scope` は `openid`, `email` のみを指定するが OpenID プロバイダーがユーザーの同意内容をもとに追加のクレームを Userinfo エンドポイントから応答したいといった要件があるでしょう。

この場合、Authlete の `consentedClaims` を利用しユーザーが認可エンドポイントで RP に公開することを許可したクレームを、Introspection エンドポイント や Userinfo エンドポイントに伝達することが可能です。

> `consentedClaims` は Authlete 2.3 以降で利用できます。
> `consentedClaims` の詳細は Authlete Java Doc [AuthorizationIssueRequest.html#setConsentedClaims()](https://authlete.github.io/authlete-java-common/com/authlete/common/dto/AuthorizationIssueRequest.html#setConsentedClaims\(\)) を確認ください。

### ユーザーが提供に同意したクレームを Authlete に伝える

例えばユーザーが認可処理を行った際、氏名とユーザー名、メールアドレスを RP に伝えることに同意し、 OpenID プロバイダーの実装ではそれらの情報を Userinfo エンドポイントから情報を返すような実装を考えます。

認可エンドポイントは以下のようなリクエストを Authlete に送信しチケットを得ます。

```sh theme={null}
curl --request POST \
  --url https://jp.authlete.com/api/{{serviceId}}/auth/authorization \
  --header 'authorization: Bearer {{serviceAccessToken}}' \
  --header 'content-type: application/json' \
  --data '{"parameters": "client_id=rest-client-client&scope=openid%20email&response_type=code&redirect_uri=https://example.com&state=xyz&nonce=12345"}'
```

応答例 (一部省略)

```json theme={null}
{
  "action": "INTERACTION",
  "service": {
  },
  "client": {
  },
  "display": "PAGE",
  "maxAge": 0,
  "scopes": [
    {
      "name": "email",
      "defaultEntry": false,
      "description": "A permission to request an OpenID Provider to include the email claim and the email_verified claim in an ID Token. See OpenID Connect Core 1.0, 5.4. for details."
    },
    {
      "name": "openid",
      "defaultEntry": false,
      "description": "A permission to request an OpenID Provider to issue an ID Token. See OpenID Connect Core 1.0, 3.1.2.1. for details."
    }
  ],
  "ticket": "IWjy7qiCFJsHYHBKAfwJNLHfoV86lL7KYC0ojmi-Qrk",
  "resultCode": "A004001",
  "resultMessage": "[A004001] Authlete has successfully issued a ticket to the service (API Key = 666990377) for the authorization request from the client (ID = 1110197986). [response_type=code, openid=true]"
}
```

OpenID プロバイダーは、氏名とユーザー名、メールアドレスを対象のクライアントに提供するための同意を得たのち、`auth/authorization/issue` エンドポイントを呼び出します。この際に `consentedClaims` として `name`, `username`, `email`, `email_verified` を指定します。

```sh theme={null}
curl --request POST \
  --url https://jp.authlete.com/api/{{serviceId}}/auth/authorization \
  --header 'authorization: Bearer {{serviceAccessToken}}' \
  --header 'content-type: application/json' \
  --data '{
    "ticket": "{{ticket}}",
    "subject": "john",
    "claims": "{\"claim_for_id_token\":\"value_for_id_token\"}",
    "consentedClaims": ["name", "username", "email", "email_verified"]
}'
```

Authlete は認可時に指定された `consentedClaims` をデータベースに保存し、`/auth/userinfo` や `/auth/introspection` の応答に含めます。

> ここで `consentedClaims` に指定するクレームはあらかじめ対象サービスの `トークン&クレーム` > `クレーム` > `サポート可能なクレーム` に追加しておく必要がある点に注意してください。
>
> <img src="https://mintcdn.com/authlete/WGQFc11Y4wUplGrc/img/kb/ja/oauth-and-openid-connect/userinfo-endpoint/supported-claims.png?fit=max&auto=format&n=WGQFc11Y4wUplGrc&q=85&s=980b7f7c80b74e942ecc9c9fad779bde" alt="supported claims" width="1187" height="659" data-path="img/kb/ja/oauth-and-openid-connect/userinfo-endpoint/supported-claims.png" />

*>*

### ユーザーが提供に同意したクレームを Userinfo API の応答に含める

先ほどの認可リクエストに紐づくトークンを Userinfo Request API に送信すると以下のような応答が得られます。

```sh theme={null}
curl --request POST \
  --url https://jp.authlete.com/api/{{serviceId}}/auth/userinfo \
  --header 'authorization: Bearer {{serviceAccessToken}}' \
  --header 'content-type: application/json' \
  --data '{"token": "{{accessToken}}"}'
```

```json theme={null}
{
  "action": "OK",
  "clientId": 1110197986,
  "subject": "john",
  "scopes": [
    "email",
    "openid"
  ],
  "claims": [
    "email",
    "email_verified"
  ],
  "token": "ytaniPwocUVRSDuCBn6EEIR7SYYRxIHkmvv2ht7oPLU",
  "clientIdAlias": "rest-client-client",
  "clientIdAliasUsed": true,
  "clientEntityIdUsed": false,
  "consentedClaims": [
    "name",
    "username",
    "email",
    "email_verified"
  ],
  "resultCode": "A091001",
  "resultMessage": "[A091001] The access token presented at the userinfo endpoint is valid."
}
```

OpenID プロバイダーは `claims` 応答の代わりに、`consentedClaims` 応答を参照し、ユーザーが提供に同意したクレームを Userinfo エンドポイントの応答として返却することが可能となります。

```sh theme={null}
curl --request POST \
  --url https://jp.authlete.com/api/{{serviceId}}/auth/userinfo/issue \
  --header 'authorization: Bearer {{serviceAccessToken}}' \
  --header 'content-type: application/json' \
  --data '{"token": "{{accessToken}}",
    **"claims": "{
      \"name\": \"John Doe\",
      \"username\": \"jdoe\",
      \"email\": \"john@example.com\",
      \"email_verified\": true}"** }'
```

上記リクエストの結果、Userinfo エンドポイントから、以下のようにユーザーが提供に同意した氏名とユーザー名、メールアドレスを含む応答が得られます。

```json theme={null}
{
  "action": "JSON",
  "responseContent": "{\"sub\":\"john\",\"name\":\"John Doe\",\"email\":\"john@example.com\",\"email_verified\":true,\"username\":\"jdoe\"}",
  "resultCode": "A096001",
  "resultMessage": "[A096001] User information was obtained successfully."
}
```
