トークンに任意のプロパティをひもづける方法

はじめに


アクセストークンを含む API リクエストを受け取ったリソースサーバーは、そのトークンに付随する情報をもとに、API アクセスの可否や、レスポンスの内容を決定します。基本的な付随情報としてはたとえば、トークンの状態(有効・無効)や、誰(リソースオーナー)が何(クライアント)にどのようなアクセス権(スコープ)を移譲したかなどですが、場合によっては、認可サーバーからさらに他の関連情報を得る必要があります。

Authlete では、アクセストークンまたは認可コードに任意のプロパティ群 (properties) をひもづける機能を持っています。この機能により、認可サーバーはリソースサーバーに対し、API リクエストの可否判定やリクエストの処理内容に必要な情報を提供しやすくなります。また、プロパティの受け渡しはクライアントを介さずに行うことが可能であり、不必要な情報露見を防止できます。

ユースケース


例 1: 送金 API の制御


送金機能をもつ銀行 API において「ABC商店へ5,000円を送金する」といった機能を実現するとします。

これを「ABC商店へ5,000円を送金する」というスコープを作って実現しようとすると、送金先および送金額を組み合わせた数のスコープが必要になってしまいます。これは現実的ではありません。

Authlete のプロパティを用いると、認可サーバーがクライアントに対して発行するアクセストークンに、上記の情報をプロパティとして直接埋め込む、ないしは、上記情報を管理する DB のレコードにひもづけておくことができます。クライアントからアクセストークンを受け取った銀行 API は、そのトークンにひもづいているプロパティから上記の情報を取得し、送金可否の判断が可能となります。

例 2: ロールベースのアクセス管理


リソースサーバーが、クライアントから提示されたアクセストークンから、そのトークンにひもづくユーザーの識別子だけではなく、ユーザーの属するグループやロールを知りたいとします。

単純な実現方法としては、リソースサーバーは受け取ったアクセストークンのイントロスペクションを行ってユーザー識別子を取得した上で、そのユーザーのグループやロールを得るために、別のデータベースに問い合わせを行うことになります。

これもまた、Authlete のプロパティを用いると、認可サーバーがユーザーのグループやロールをトークンにひもづけ、その値をリソースサーバーが Authlete から取得する、という連携が可能となり、前述したような、リソースサーバーからデータベースへの問い合わせが不要となります。

extra-properties-rbac_ja.png 95.01 KB

利用方法


本セクションではプロパティの設定・取得の利用方法を紹介します。

Property データタイプ


Authlete では、アクセストークンないしは認可コードにひもづけるプロパティ(任意のパラメーター群)を、Property データタイプとして定義しています。Property データタイプは次のようなエントリーを持つ JSON オブジェクトです。
名前
説明
key
文字列
プロパティのキー
value
文字列
プロパティの値
hidden
真偽値
プロパティをクライアントから秘匿するか否かを示すフラグ。true の場合には秘匿する。false の場合には秘匿しない(クライアントに露見する)。


たとえば、キーが example_key、値が example_value であり、クライアントから秘匿しない(クライアントへの露見を許容する)プロパティは、以下のような JSON オブジェクトになります。

{
  "key":"example_key",
  "value":"example_value",
  "hidden":false
}

プロパティのひもづけ


アクセストークンへのプロパティのひもづけは、下記のタイミングで行います。

認可サーバーが「認可エンドポイント」から認可コードもしくはアクセストークンを返却する直前


認可サーバーが /auth/authorization/issue API を呼び出す際にプロパティをセットします。

以下は curl コマンドによる実行例です。(見やすさのため折り返しています)

  • リクエスト
curl -s -X POST .../auth/authorization/issue 
 -u ...:... 
 -H 'Content-type: application/json'
 -d '{"subject":"<subject>",
      "ticket":"<ticket>",
      "properties":[
        {"key":"example_key",
         "value":"example_value",
         "hidden":true}
        ]
     }'

  • レスポンス
{
  "type": "authorizationIssueResponse",
  "resultCode": "A040001",
  "resultMessage": "[A040001] The authorization request was processed 
    successfully.",
  "accessTokenDuration": 0,
  "accessTokenExpiresAt": 0,
  "action": "LOCATION",
  "authorizationCode": "...",
  "responseContent": "https://client.example.org/cb/example.com?code=..."


認可サーバーが「トークンエンドポイント」からアクセストークンを返却する直前


認可サーバーが /auth/token API を呼び出す際にプロパティをセットします。以下は curl コマンドによる実行例です。(見やすさのため折り返しています)

  • リクエスト
curl -s -X POST .../auth/token 
 -u ...:...
 -H 'Content-type: application/json'
 -d '{"clientId":"<clientId>",
      "clientSecret":"<clientSecret>",
      "parameters":
        "redirect_uri=https://client.example.org/cb/example.com
         &grant_type=authorization_code
         &code=...",
      "properties":[
        {"key":"example_key",
         "value":"example_value",
         "hidden":false}
        ]
    }'

  • レスポンス
{
  "type": "tokenResponse",
  "resultCode": "A050001",
  "resultMessage":
    "[A050001] The token request (grant_type=authorization_code) was processed
     successfully.",
  "accessToken": "...",
  "action": "OK",
...
  "properties": [
    {
      "hidden": false,
      "key": "example_key",
      "value": "example_value"
    }
  ],
  "refreshToken": "...",
  "responseContent":
    "{\"access_token\":\"...\",
      \"refresh_token\":\"...\",
      \"scope\":\"payment\",
      \"token_type\":\"Bearer\",
      \"expires_in\":300,
      \"example_key\":\"example_value\"
     }",
  "subject": "<subject>"
}


プロパティの取得


リソースサーバーが /auth/introspection API を呼び出すと、そのレスポンスにプロパティが含まれます。以下は curl コマンドによる実行例です。(見やすさのため折り返しています)

  • リクエスト
curl -s -X POST .../auth/introspection 
 -u ...:...
 -H 'Content-type: application/json'
 -d '{"token":"<accessToken>"}'

  • レスポンス
{
  "clientId" : <clientId>,
  "properties" : [
    {
      "key":"example_key",
      "value":"example_value",
      "hidden" : false
    }
  ],
  "action" : "OK",
  "resultCode" : "A056001",
  "expiresAt" : 1565847795000,
  "subject" : "<subject>",
  "type" : "introspectionResponse",
  "refreshable" : true,
  "usable" : true,
  "existent" : true,
  "resultMessage" : "[A056001] The access token is valid.",
  "responseContent" : "Bearer error=\"invalid_request\""
...
}


制限事項


キーの値


以下の値は認可サーバーから返される応答に含まれるパラメーター群として、 RFC 6749OpenID Connect Core 1.0 にて予約されているため、キーとして指定できません。指定された場合には Authlete サーバーが破棄します。 
  • access_token
  • token_type
  • expires_in
  • refresh_token
  • scope
  • error
  • error_description
  • error_uri
  • id_token

プロパティの値


指定可能な値は文字列のみです。真偽値や配列等は指定できません。

サイズ


指定されたプロパティー群は、次のような処理を経て Authlete サーバー側のデータベース内に保存されます。最終的に生成された文字列の長さが 65,535 を超える場合にはエラーとなります。
  1. 三次元の文字列に変換する
    • 例:[["example_parameter","example_value",null]]
      (hidden の値は null か空文字列に変換されます。それぞれ、false と true を表します。)
  2. JSON 文字列に変換する
    • 例: "[[\"example_parameter\":\"example_value\",null]]"
  3. AES/CBC/PKCS5Padding で暗号化する
  4. base64url でエンコードする

関連情報


How did we do with this article?