OAuth Client ID Metadata Document (CIMD)

はじめに

RFC 6749 The OAuth 2.0 Authorization Framework で定義される認可リクエストでは、client_id リクエストパラメータを用いてクライアントアプリケーション (以降『クライアント』) の識別子 (以降『クライアント ID』) を指定しなければなりません。また、認可サーバは redirect_uri リクエストパラメータで指定されたリダイレクト URI が当該クライアントのものとして登録済みかどうか (当該クライアントの redirect_uris メタデータにそのリダイレクト URI が含まれているかどうか) を確認しなければなりません。

これらの要件を考慮すれば、クライアントが認可サーバにリクエストを送信するのに先立ち、当該クライアントの識別子やメタデータが認可サーバに事前に登録されている必要があることが分かります。

OpenID Connect Dynamic Client Registration 1.0 (DCR) や RFC 7591 OAuth 2.0 Dynamic Client Registration Protocol (DCR)、 OpenID Federation 1.0 (解説記事) の Explicit Registration など、クライアントを事前に登録のための標準仕様が幾つか存在します。 認可サーバがこれらの標準仕様をサポートするかどうかは任意です。

認可リクエストを投げる際に必要となるので、アプリケーションは認可サーバから割り当てられたクライアント ID を保持しておかなければなりません。もしもそのアプリケーションが複数の認可サーバのクライアントとして動作する場合、通信相手となる認可サーバの数だけ異なるクライアント ID を管理することになります。この状態は決して珍しいことではありません。 『GAIN POC 中間報告 (2023年春)』の『現行のエコシステムアーキテクチャ』で紹介している通り、イギリスのオープンバンキングを参考に構築されたエコシステムは、概ねこのような状況となっています。

DCR を活用するこの仕組みは機能するものの、認可サーバ毎にクライアント ID を使い分けなければならず、認可サーバの数が増えてくると識別子管理が厄介になってきます。 アプリケーションの立場からすれば、可能であれば一つのクライアント ID を全ての認可サーバで共通して使い回したいところです。

実は、クライアント ID を全ての認可サーバで共通化する仕組みは、OpenID Federation 1.0 という仕様で既に実現されています。同仕様では、クライアント ID はグローバルで一意となる、https:// ではじまる URL となります。 そして、当該クライアントのメタデータは、その URL に /.well-known/openid-federation を付加した場所から提供されます (下図は解説文書から抜粋したものです)。

OpenID Federation 1.0 をサポートする認可サーバは、認可リクエストの client_id リクエストパラメータで指定された識別子に対応するクライアントが未登録であり、そしてその識別子が https:// で始まる URL の場合、その URL に /.well-known/openid-federation を追加した場所からクライアントメタデータを取得し、クライアントを自動的に登録します (Automatic Registration)。 そして、何事もなかったかのように認可リクエストの処理を継続します。

このような先行仕様があるところに、OAuth Client ID Metadata Document (CIMD) という新しい仕様が提案されました。この仕様でも、クライアント ID は https:// で始まる URL であり、クライアントメタデータはその URL が指す場所から提供されます。

OpenID Federation 1.0 に比べると、CIMD はかなり単純な仕様です。 おかげでクライアントやサーバの実装は楽になります。しかし、その単純さと引き換えに、CIMD 仕様には、クライアントが信頼できる通信相手であるかどうかを確認する方法が定義されていません。 そのため、認可サーバの実装が何らかの独自機能で制限をかけない限り、CIMD をサポートする認可サーバには誰でも勝手にクライアントを登録できてしまいます。 これは、トラストチェーンを用いてエンティティ間の信頼関係を築く方法を具体的に定めている OpenID Federation 1.0 とは対照的です。

この記事では、CIMD 仕様と、それを補完する Authlete の独自機能について説明します。


仕様

概要

CIMD 仕様を簡潔に説明すると、「クライアント識別子を https:// で始まる URL とする。クライアントメタデータは、その URL が指す場所から取得する」、となります。

順を追って見ていきましょう。まず、クライアントが認可サーバに認可リクエストを送信します。 認可リクエストには client_id リクエストパラメータを含めますが、その値として https:// で始まる URL を指定します。

認可サーバは受け取った認可リクエストを解析します。そして、クライアント ID が https:// で始まることを認識します。

そのクライアント ID に該当するクライアントが未登録であれば、認可サーバはその URL が指す場所にアクセスします。

アクセスした場所から、クライアントメタデータが JSON 形式で返されます。

認可サーバは、そのクライアントメタデータを元にクライアントを自身に登録し、認可リクエストの処理を継続します。


クライアント ID の要件

  • スキームは https でなければならない
  • パス部を含まなければならない
  • パスセグメントに ... を含んではならない
  • フラグメント部を含んではならない
  • ユーザ名やパスワードを含んではならない
  • クエリー部を含めるべきではない

クライアントメタデータの制限

  • メタデータの URL と、そこから得られるメタデータ内の client_id の値は一致しなければならない
  • client_secret_basicclient_secret_postclient_secret_jwt などの対称鍵系クライアント認証方式を token_endpoint_auth_method に指定してはならない
  • client_secretclient_secret_expires_at を使ってはならない

サービス設定

Authlete では、バージョン 3.0.22 以降で CIMD をサポートします。 このセクションでは、CIMD サポートのためにサービスに追加されたプロパティ群と、関連する API リクエストパラメータについて紹介します。


clientIdMetadataDocumentSupported プロパティ

CIMD をサポートするかどうかを示す新しい真偽値プロパティ clientIdMetadataDocumentSupported がサービスに追加されました。 このプロパティのデフォルト値は false なので、CIMD を利用する場合は明示的に true に設定する必要があります。

{
  "clientIdMetadataDocumentSupported": true
}

clientIdMetadataDocumentSupported プロパティは、CIMD 仕様が定義するサーバメタデータの client_id_metadata_document_supported に対応しています。 clientIdMetadataDocumentSupportedtrue に設定されている場合、Authlete の /service/configuration API が生成するディスカバリ文書 (OpenID Connect Discovery 1.0) に次のエントリが追加されます。

{
  "client_id_metadata_document_supported": true
}

許可リスト

クライアント ID として許可する URL を、許可リストを用いて制限することができます。 許可リストはサービスの cimdAllowlist プロパティで指定します。 また、許可リストによる制限を有効化するために cimdAllowlistEnabled プロパティに true を設定します。

{
  "cimdAllowlistEnabled": true,
  "cimdAllowlist": [
    "https://example.com/a/b"
  ]
}

cimdAllowlist プロパティの値は文字列の配列で、各要素は有効な URL でなければなりません。

クライアント ID は、許可リスト内の URL のどれか一つとマッチすれば、有効とみなされます。 マッチするかどうかの判定は単純な文字列比較ではなく、次の要領で行われます。

コンポーネント 比較処理
1 スキーム スキーム部が一致する
2 オーソリティ オーソリティ部が一致する (単純文字列比較であり、デフォルトポートは考慮されない)
3 パス クライアント ID のパスが許可リスト内の URL のパスを完全に含む
4 クエリー 許可リスト内の URL がクエリー部を含む場合、クエリー部が一致する

パス部の比較はセグメント単位で行われます。例えば許可リストが https://example.com/a/b を含んでいる場合、https://example.com/a/b/c は有効なクライアント ID とみなされますが、https://example.com/ahttps://example.com/a/bb は無効とみなされます。


常時取得

認可サーバは取得したクライアントメタデータをある程度の期間キャッシュします。 その期間が切れるまではメタデータの再取得を行わず、キャッシュされたものを参照し続けます。

この動作は一般的には好ましいですが、時にはキャッシュの期限切れを待たずに認可サーバにクライアントメタデータの再取得をしてもらいたいこともあるでしょう。 特に、クライアントアプリケーションの開発中にクライアントメタデータの内容を頻繁に変更している場合などです。 あなたが Web サイトのコンテンツ制作に関わった経験があるならば、Web ブラウザの Super Reload を有用だと感じたことがあるでしょう。クライアントメタデータの強制再取得機能は、いわば Super Reload のようなものです。

OpenID Federation 1.0 では、trust_chain リクエストパラメータを使うことで、キャッシュの期限切れ前に認可サーバにクライアントメタデータの更新を促すことができます。 一方、CIMD にはそのような仕組みはありません。 そこで、「クライアントメタデータの再取得を促す方法を標準化してはどうか」と提案してみました (CIMD ISSUE 59)。 しかし、賛同を得られる見込みがほとんどなかったため、Authlete 独自の仕組みを作り込むことにしました。

サービスの cimdAlwaysRetrieved プロパティに true を設定しておくと、Authlete は常にクライアントメタデータを再取得するようになります。 正確に言うと、認可フローの開始リクエストの際に常に再取得をおこないます。 「認可フローの開始リクエスト」が意味するところは、具体的には次のとおりです。

  • 認可コードフロー (などの認可エンドポイントへのリクエストから開始するフロー) では認可リクエストの際に再取得を実行するが、後続のトークンリクエストでは再取得を実行しない
  • クライアントクレデンシャルズフロー (などのトークンエンドポイントへのリクエストから開始するフロー) ではトークンリクエストが開始リクエストなので、トークンリクエストのタイミングで再取得を実行する
  • CIBA フロー (CIBA Core) ではバックチャネル認証リクエストの際に再取得を実行するが、後続のトークンリクエストでは再取得は実行しない
  • デバイスフロー (RFC 8628) ではデバイス認可リクエストの際に再取得を実行するが、後続のトークンリクエストでは再取得は実行しない

常に再取得をおこなう機能は、開発中は有用でしょう。 しかし、システムが安定稼働してクライアントメタデータが更新されることがほとんどなくなった場合、常時再取得はやり過ぎです。 そのため、システムが安定稼働し始めたら、cimdAlwaysRetrieved プロパティに false を設定することになるでしょう。

とは言っても、システム安定稼働開始後も強制再取得を実行したい事情が発生することはありえます。 そのため、幾つかの Authlete API、具体的には下記の API 群は、リクエストパラメータとして cimdOptions.alwaysRetrieved を受け付け、その値が true の場合、サービス設定の cimdAlwaysRetrievedfalse の場合でも、クライアントメタデータの再取得を (キャッシュが有効か否かに関わらず) 実行します。

API 説明
/api/{service-id}/auth/authorization 認可リクエストの処理
/api/{service-id}/auth/token トークンリクエストの処理
/api/{service-id}/backchannel/authentication バックチャネル認証リクエストの処理
/api/{service-id}/device/authorization デバイス認可リクエストの処理

このランタイム時の機能を用い、認可サーバは独自のクライアントメタデータ強制再取得機能を実装することができます。


HTTP スキーム許可

CIMD 仕様では、クライアント ID を示す URL のスキームは https でなければなりません。

しかし、サービスの cimdHttpPermitted フラグに true を設定すると、Authlete は http スキームも許容するようになります。 この機能をオンにすることで、TLS による保護を省いた Web サーバをクライアントメタデータをホスティングするサーバとして用いることができます。 この機能は開発中に利用されることを想定しています。

cimdAlwaysRetrieved プロパティに対応する cimdOptions.alwaysRetrieved リクエストパラメータが存在するのと同様、 cimdHttpPermitted プロパティに対応する cimdOptions.httpPermitted リクエストパラメータも存在します。


クエリー部許可

CIMD 仕様では、クライアント ID を示す URL はクエリー部を持つべきではない (SHOULD NOT) とされています。Authlete は、デフォルトでは、クエリー部を含む URL を CIMD のクライアント ID として受け入れません。

クエリー部を含む URL を CIMD クライアント ID として Authlete に受け入れさせるためには、サービスの cimdQueryPermitted プロパティに true を設定する必要があります。

このプロパティにも、対応するリクエストパラメータ cimdOptions.queryPermitted が存在します。


HTTP エイリアス禁止

Authlete はクライアントに対して内部的に数値の識別子を割り振ります。 これに加え、クライアント ID エイリアスという機能が存在し、この機能により開発者はクライアントに任意の名前を設定することができます。 Authlete 2.3 まではクライアント ID エイリアス機能のオン・オフを切り替えることができましたが、歴史的な経緯により、Authlete 3.0 ではこの機能は常に有効になっており、オフにすることはできません。

任意の名前を設定することができるので、例えば https スキームを持つ URL をクライアント識別子として設定することができます。 しかし、そのようなクライアント識別子は、見た目は OpenID Federation 1.0CIMD のクライアント ID に見えるものの、実際はエイリアスにしか過ぎないので、クライアントメタデータの自動更新処理が走ることはありません。

この状況は混乱を招きかねないので、Authlete は新たに httpAliasProhibited というサービスプロパティを導入し、https://http:// で始まる文字列をエイリアスとして設定できないようにする機能を提供することにしました。

後方互換性のため、この httpAliasProhibited プロパティの初期値は false となっていますが、可能な限り true に設定することを推奨します。


メタデータポリシー

取得したクライアントメタデータをデータベースに登録する前に、メタデータポリシーを適用してメタデータを調整する機能を Authlete は提供します。これは、OpenID Federation 1.0Section 6.1. Metadata Policy で定義されているメタデータポリシーを CIMD に応用する機能です。

例えば、クライアント ID が指す URL から得られるクライアントメタデータの内容が次のものであるとしましょう。

{
  "client_name": "Example Client",
  "grant_types": [
    "authorization_code",
    "refresh_token"
  ],
  "response_types": [
    "code"
  ],
  "token_endpoint_auth_method": "none",
  "client_id": "https://example.com/client.json",
  "redirect_uris": [
    "https://example.com/redirect"
  ]
}

このクライアントメタデータに対して、次のメタデータポリシーを適用すると、

{
  "id_token_signed_response_alg": {
    "default": "ES256",
    "one_of": ["ES256", "ES384", "ES512"]
  },
  "redirect_uris": {
    "add": [
      "http://localhost:12345/redirect"
    ]
  }
}

結果として得られるクライアントメタデータは次のようになります。redirect_urishttp://localhost:12345/redirect が追加され、ES256 という値を持つ id_token_signed_response_alg プロパティが新しく追加されていることに注目してください。

{
  "client_name": "Example Client",
  "grant_types": [
    "authorization_code",
    "refresh_token"
  ],
  "response_types": [
    "code"
  ],
  "token_endpoint_auth_method": "none",
  "client_id": "https://example.com/client.json",
  "redirect_uris": [
    "https://example.com/redirect",
    "http://localhost:12345/redirect"
  ],
  "id_token_signed_response_alg": "ES256"
}

この機能を利用するには、サービスの cimdMetadataPolicyEnabled プロパティに true を設定し、cimdMetadataPolicy プロパティにメタデータポリシーを設定します。

{
  "cimdMetadataPolicyEnabled": true,
  "cimdMetadataPolicy": "{\"redirect_uris\":{\"add\":\"http://localhost:12345/redirect\"},\"id_token_signed_response_alg\":{\"default\":\"ES256\",\"one_of\":[\"ES256\",\"ES384\",\"ES512\"]}}"
}

クライアントプロパティ

Authlete が Authlete API を通じて Authlete 外部にクライアントの情報を伝える際、Client というデータ構造が用いられます。CIMD をサポートするにあたり、このデータ構造に次のプロパティ群が追加されました。

プロパティ 説明
metadataDocumentLocation クライアントメタデータの場所
metadataDocumentExpiresAt クライアントメタデータの有効期間終了時刻 (Unix epoch からの経過ミリ秒数)
metadataDocumentUpdatedAt クライアントメタデータの最終更新時刻 (Unix epoch からの経過ミリ秒数)
discoveredByMetadataDocument CIMD により登録されたクライアントかどうかを示す真偽値

Authlete は、CIMD 仕様が言及しているように、HTTP の既存のメカニズム (参考: RFC 9111 HTTP Caching) を利用してクライアントメタデータの有効期間を算出します。 metadataDocumentExpiresAt プロパティは、その有効期間が終了する時刻を示します。

クライアントメタデータをホスティングする Web サーバが max-age 等のキャッシュに関する設定をし忘れていたり、極端に長い max-age を設定しているなどの理由で、算出したクライアントメタデータの有効期間が、期待されるクライアントメタデータ更新間隔を大きく超えてしまう可能性があります。 そのような想定をはるかに超える有効期間が設定されてしまうと、クライアントメタデータの更新が適切な時間間隔で検知されなくなってしまいます。 このような事態を避けるため、現在の Authlete の実装では、算出された値に関わらず、有効期間の最大値を 86400 秒 (1日) としています。

下記はクライアント識別子に関係のあるプロパティ群です。

プロパティ 仕様 説明
clientId 数値 数値のクライアント識別子
clientIdAlias 文字列 クライアント識別子のエイリアス
clientIdAliasEnabled 真偽値 エイリアス機能が有効かどうか (Authlete 3.0 では常に真)
dynamicallyRegistered 真偽値 DCR DCR により登録されたかどうか
entityId 文字列 OIDFED エンティティ ID
automaticallyRegistered 真偽値 OIDFED Automatic Registration により登録されたかどうか
explicitlyRegistered 真偽値 OIDFED Explicit Registration により登録されたかどうか
metadataDocumentLocation 文字列 CIMD クライアントメタデータの場所
metadataDocumentExpiresAt 数値 CIMD クライアントメタデータの有効期間終了時刻
metadataDocumentUpdatedAt 数値 CIMD クライアントメタデータの最終更新時刻
discoveredByMetadataDocument 真偽値 CIMD CIMD により登録されたかどうか

歴史的な経緯により、クライアントの出所を示す真偽値が複数存在します — すなわち dynamicallyRegisteredautomaticallyRegisteredexplicitlyRegistereddiscoveredByMetadataDocument という真偽値フラグが存在し、お互いに排他の関係にあります (同時に複数のフラグが真になることはありません)。

相互排他の関係にあるフラグ群が別々に存在しているのは厄介なので、バージョン 3.0.22 以降の Authlete は、これらのフラグに加えて clientSource という文字列プロパティも Authlete API のレスポンスに含めます。 このプロパティは次の値を取ります。

説明
DYNAMIC_REGISTRATION DCR による登録
AUTOMATIC_REGISTRATION OpenID Federation 1.0Automatic Registration による登録
EXPLICIT_REGISTRATION OpenID Federation 1.0Explicit Registration による登録
METADATA_DOCUMENT CIMD による登録
STATIC_REGISTRATION 上記以外 (静的登録)

レスポンスパラメータ

/api/{service-id}/auth/authorization API など、幾つかの Authlete API のレスポンスには、リクエストで使用されたクライアント ID の出所に関する情報が含まれます。

パラメータ 仕様 説明
clientIdAliasUsed 真偽値 エイリアスがクライアント ID として用いられた
clientIdAlias 文字列 エイリアス
clientEntityIdUsed 真偽値 OIDFED エンティティ ID がクライアント ID として用いられた
clientEntityId 文字列 OIDFED エンティティ ID
metadataDocumentUsed 真偽値 CIMD クライアントメタデータの場所がクライアント ID として用いられた
metadataDocumentLocation 文字列 CIMD クライアントメタデータの場所

おわりに

MCP (Model Context Protocol) 仕様の 2025 年 11 月 25 日版で、CIMD が仕様として取り込まれました (MCP 2025-11-25 Authorization)。

Authlete は 2025 年 11 月中に CIMD 仕様を実装し終え、本記事でもご紹介している通り、Authlete 独自機能として次のものも併せて実装しました。

  • 許可リスト (cimdAllowlist, cimdAllowlistEnabled)
  • 常時取得 (cimdAlwaysRetrieved | cimdOptions.alwaysRetrieved)
  • HTTP 許可 (cimdHttpPermitted | cimdOptions.httpPermitted)
  • クエリー部許可 (cimdQueryPermitted | cimdOptions.queryPermitted)
  • メタデータポリシー (cimdMetadataPolicy, cimdMetadataPolicyEnabled)

CIMD は策定中の仕様であり、今後も進化していくことが予想されます。 また、CIMD の実装・運用経験が業界に積み上がっていくのはこれからです。 Authlete は、仕様の進化や業界へのフィードバックに合わせて、適宜機能を追加していく予定です。 機能追加のご要望がありましたら、コンタクトフォームでお問い合わせください。