Financial API 実装の技術課題

2019年1月21日：新しい記事、**『[【2019年版】世界最先端の API セキュリティー技術、実装者による『Financial-grade API』解説](https://qiita.com/TakahikoKawasaki/items/83c47c9830097dba2744)』**を公開しました。そちらをご参照ください。

---
# **はじめに**

[OpenID Foundation](http://openid.net/) の [Financial API Working Group](http://openid.net/wg/fapi/) で仕様策定中の Financial API に対応するため、技術上課題になると思われる点を書き出してみようと思います。

なお、本記事執筆時点（2017 年 6 月 29 日）において Financial API 仕様は策定作業真っ最中であり、今後仕様変更される可能性があることに注意してください。

また、私の理解不足により、ここでの記述内容が誤っている可能性もあるのでご注意ください。間違いに気付かれましたら教えていただけると助かります。

さらに、加えてご留意いただきたいのは、私は [Authlete](https://www.authlete.com/) 社創業者であるため、Financial API に関する発言には多分にポジショントーク的な部分があります。ですので、その点を念頭に置いて適宜割り引いて読んでいただければと思います。


# **背景**

国際標準化団体 [OpenID Foundation](http://openid.net/) の作業部会の一つである [Financial API Working Group](http://openid.net/wg/fapi/)（FAPI WG）において、[PSD2](https://ec.europa.eu/info/law/payment-services-psd-2-directive-eu-2015-2366_en) や [Open Banking Standard](https://theodi.org/open-banking-standard) を考慮し、[ISO/TC 68](http://isotc.iso.org/livelink/livelink/open/tc68)（Financial services）への提出も視野に入れながら、金融 API の標準仕様策定作業が進められています。

Financial API（FAPI）には、共通 API 仕様だけではなく、むしろより重要な、金融機関による使用に耐えうるセキュリティー要件が含まれています。ID 連携技術『[OpenID Connect](http://openid.net/connect/)』および認可仕様『[OAuth 2.0](https://tools.ietf.org/html/rfc6749)』の関連仕様は全て OpenID Foundation で議論・策定が行われるため、認証・認可のセキュリティー要件まで含めた API 仕様策定を行える団体は同団体をおいて他になく、他の金融 API 仕様策定企業・団体とは一線を画しています。

OpenID Foundation には、Microsoft 社、Google 社、Oracle 社、Salesforce 社、その他多くの企業・団体が[スポンサー](http://openid.net/foundation/sponsoring-members/)として名を連ね、仕様策定作業にも参画しているため、同団体が策定する仕様は業界の支持を得られやすい傾向があります。実際、同団体が定めた OAuth 2.0 と OpenID Connect はデファクトスタンダードとなっており、FAPI に関しても、英国の The Open Banking Implementation Entity（OBIE）が FAPI WG と協力していくことを公式に[発表](https://www.openbanking.org.uk/about-us/news/open-banking-forms-collaboration-openid-foundation/)しました。

<sup>2017 年 7 月 06 日 追記： 2017 年 7 月 5 日、OBIE は [Account and Transaction API](https://www.openbanking.org.uk/read-write-apis/account-transaction-api/) と [Payment Initiation API](https://www.openbanking.org.uk/read-write-apis/payment-initiation-api/) の[仕様](https://www.openbanking.org.uk/read-write-apis/)を[公開](https://www.openbanking.org.uk/2017/07/05/open-banking-launches-account-transaction-information-payment-initiation-api-specifications/)しました。</sup>
<sup>2017 年 7 月 25 日 追記： 全国銀行協会がとりまとめ、2017 年 7 月 13 日に[公表](https://www.zenginkyo.or.jp/news/detail/nid/8261/)した「[オープン API のあり方に関する検討会報告書](https://www.zenginkyo.or.jp/fileadmin/res/news/news290713_1.pdf)」でも Financial API が言及されています。</sup>
<sup>2017 年 8 月 02 日 追記： FAPI Part 2 (Read & Write Security Profile) の Implementer's Draft が承認されたと、OpenID Foundation が 2017 年 7 月 24 日に[発表](http://openid.net/2017/07/24/fapi-part-2-implementers-draft-approved/)しました。</sup>

上記の状況を踏まえると、金融業界のエコシステムが FAPI を中心に構築されていく可能性が高いため（少なくとも英国金融業界はほぼ間違いなく）、これをビジネスチャンスと捉え、金融機関および FinTech 企業は準備を始めるのが良いと思われます。

この記事では FAPI に対応するための技術課題を挙げていこうと思います。


# **技術課題**

以下、若干長い文章になっておりますが、ポイントとなる箇所は下記のような形で目立たせているので、そこだけ拾い読みしていただいても結構です。

| ✅ | （ポイントの要約） |
|:-:|:--|

また、最後に「まとめ」もしてありますので、概要だけ知りたい方はそちらをご参照ください。


## ***FAPI 全体構成***

FAPI 仕様は下記の 5 つのパートで構成されています。

| パート | タイトル | 説明 |
|:-:|:--|:--|
| Part 1 | Read Only API Security Profile | 参照系 API セキュリティー要件 |
| Part 2 | Read & Write API Security Profile | 更新系 API セキュリティー要件 |
| Part 3 | Open Data API | 公開データ API 仕様 |
| Part 4 | Read Only API | 参照系 API 仕様 |
| Part 5 | Read & Write API | 更新系 API 仕様 |

Part 1 と Part 2 では、サーバー群やクライアントアプリケーションに対するセキュリティー要件が定められています。金融機関による使用に耐えられるよう既存仕様よりもかなりセキュリティー要件が厳しくなっているため、実装難易度が高く、FAPI 対応する上で一つの大きなハードルになりそうです。

| ✅ | 既存の仕様よりも、かなりセキュリティー要件が厳しい。 |
|:-:|:--|

Part 1 は既に Public Review 期間が終わり、Part 2 は現在 Public Review 期間中です（2017 年 7 月 16 日まで）。このため、セキュリティー要件に関しては、ほぼ項目が出揃った状況となっています。

Part 3 から Part 5 は API 仕様になっており、API を呼び出す際のパラメーターや、API からの応答のフォーマット等が定められています。これらの Part 群については今後議論が活発になっていくと思われます。


## ***FAPI Part 1***

ここでは、参照系 API のセキュリティー要件を定める FAPI Part 1 から、既存の実装の改良もしくは新規開発が必要になる可能性の高い項目を書き出してみます。（注：全ての項目を網羅しているわけではありません。）


<br/>
> ***5.2.2. Authorization Server***
> ***The Authorization Server***
> ......
> *shall provide a client secret that adheres to the requirements in section 16.19 of [OIDC] if a symmetric key is used;*

これは、署名処理等で共有鍵を使う場合、[OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html) の [16.19. Symmetric Key Entropy](http://openid.net/specs/openid-connect-core-1_0.html#SymmetricKeyEntropy) に記載されている要件をクライアントシークレットが満たす必要があるということを意味しています。例えば [ID トークンの署名アルゴリズム](https://tools.ietf.org/html/rfc7518#section-3.1)として `HS256`（HMAC using SHA-256）を使用する場合、クライアントシークレットには最低限 256 ビットのエントロピーが求められるということです。これが、`HS384`、`HS512`、となると、それぞれ 384 ビット、512 ビットのエントロピーが求められることになります。関連する議論として『[OAuth 2.0 + OpenID Connect のフルスクラッチ実装者が知見を語る](http://qiita.com/TakahikoKawasaki/items/f2a0d25a4f05790b3baa)』の『[クライアントシークレット](http://qiita.com/TakahikoKawasaki/items/f2a0d25a4f05790b3baa#%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E3%82%B7%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88)』も参照していただければと思います。

| ✅ | クライアントシークレットに高いエントロピーが求められるケースがある。 |
|:-:|:--|


<br/>
> *shall authenticate the confidential client at the Token Endpoint using one of the following methods:*
>
>  *1. TLS mutual authentication [TLSM];*
>  *2. JWS Client Assertion using the `client_secret` or a private key as specified in section 9 of [OIDC];*

[トークンエンドポイント](https://tools.ietf.org/html/rfc6749#section-3.2)におけるクライアント認証の方法として、[Mutual TLS](https://tools.ietf.org/html/draft-ietf-oauth-mtls)（現在ドラフト段階）もしくは [JWT Client Assertion](https://tools.ietf.org/html/rfc7523) を用いなければならないということで、これは、[RFC 6749](https://tools.ietf.org/html/rfc6749)（The OAuth 2.0 Authorization Framework）の [2.3. Client Authentication](https://tools.ietf.org/html/rfc6749#section-2.3) で説明されている方法とは別の方法です。

| ✅ | クライアント認証には Mutual TLS もしくは JWT Client Assertion の実装が必要となる。 |
|:-:|:--|


<br/>
> *shall support [RFC7636] with `S256` as the code challenge method;*

認可コード横取り攻撃への対抗策である [RFC 7636](https://tools.ietf.org/html/rfc7636)（Proof Key for Code Exchange by OAuth Public Clients）の実装が必須となっています。RFC 7636 については、『[PKCE: 認可コード横取り攻撃対策のために OAuth サーバーとクライアントが実装すべきこと](http://qiita.com/TakahikoKawasaki/items/00f333c72ed96c4da659)』を参考にしていただければと思います。

| ✅ | RFC 7636 の実装が必須である。 |
|:-:|:--|


<br/>
> *shall require the `redirect_uri` parameter in the authorization request;*

RFC 6749 では、条件によっては、認可リクエストに `redirect_uri` パラメーターを含める必要はありませんでした。一方、FAPI 対応の認可サーバーは、`redirect_uri` パラメーターを含まない認可リクエストを拒絶しなければなりません。既存仕様との兼ね合いもあるので、柔軟な認可サーバー実装であれば、静的設定や実行時判定で動作を切り替えることになるでしょう。

| ✅ | `redirect_uri` パラメーターを必ず要求する。 |
|:-:|:--|


<br/>
> *shall require the value of `redirect_uri` to exactly match one of the pre-registered Redirect URIs;*

RFC 6749 では、`redirect_uri` パラメーターで指定されたリダイレクト URI が登録されているリダイレクト URI と合致するかの判定方法は、（登録されているリダイレクト URI が完全 URI でない限り）[RFC 3986](https://tools.ietf.org/html/rfc3986)（Uniform Resource Identifier (URI): Generic Syntax）の [6. Normalization and Comparison](https://tools.ietf.org/html/rfc3986#section-6) に記載されている方法を用いることになっています。一方、FAPI では、単純文字列比較による完全一致が求められます。

| ✅ | リダイレクト URI の合致判定は、単純文字列比較による完全一致。 |
|:-:|:--|


<br/>
> *shall require user authentication at LoA 2 as defined in [X.1254] or more;*

認可処理時に実行されるユーザー認証処理が、[X.1254](https://www.itu.int/rec/T-REC-X.1254)（Entity authentication assurance framework）で定義されている LoA（Level of assurance）の 2 以上を満たすことが求められています。下記は X.1254 から LoA 2 の定義を抜粋したものです。

| X.1254, 6.2 Level of assurance 2 (LoA2) |
|:--|
| *At LoA2, there is some confidence in the claimed or asserted identity of the entity. This LoA is used when moderate risk is associated with erroneous authentication. Single-factor authentication is acceptable. Successful authentication shall be dependent upon the entity proving, through a secure authentication protocol, that the entity has control of the credential. Controls should be in place to reduce the effectiveness of eavesdroppers and online guessing attacks. Controls shall be in place to protect against attacks on stored credentials.*<br/><br/>*For example, a service provider might operate a website that enables its customers to change their address of record. The transaction in which a beneficiary changes an address of record may be considered an LoA2 authentication transaction, as the transaction may involve a moderate risk of inconvenience. Since official notices regarding payment amounts, account status, and records of changes are usually sent to the beneficiary's address of record, the transaction additionally entails moderate risk of unauthorized release of PII. As a result, the service provider should obtain at least some authentication assurance before allowing this transaction to take place.* |

| ✅ | FAPI Part 1 ではユーザー認証に LoA 2 以上が求められる。 |
|:-:|:--|


<br/>
> *shall return the list of allowed scopes with the issued access token;*

認可サーバーがクライアントアプリケーションにアクセストークンを発行する際、そのアクセストークンに紐付けられたスコープ群に関する情報をクライアントに知らせるかどうかは、クライアントが元々要求したスコープ群と結果として付与されたスコープ群が異なる場合を除き、任意でした（RFC 6749, [5.1. Successful Response](https://tools.ietf.org/html/rfc6749#section-5.1)）。しかし、FAPI では付与されたスコープ群の情報を返すことが必須とされています。

| ✅ | アクセストークンとともに、付与されたスコープ群の情報を必ず返す。 |
|:-:|:--|


<br/>
> *shall provide opaque non-guessable access tokens with a minimum of 128 bits as defined in section 5.1.4.2.2 of [RFC6819].*

発行されるアクセストークンのエントロピーが 128 ビット以上であることが要求されています。例えば 128 ビットの値を base64url でエンコーディングすると 22 文字になるため、もしも手元の認可サーバーが、英数字のみで構成されるアクセストークンを発行し、その長さが 22 文字未満なのであれば、この要件を満たしていないことは明らかなので、実装改良が必要になります。

| ✅ | アクセストークンのエントロピーは 128 ビット以上。 |
|:-:|:--|


<br/>
> *should provide a mechanism for the end-user to revoke access tokens and refresh tokens granted to a Client as in 16.18 of [OIDC].*

アクセストークンやリフレッシュトークンを取り消す仕組みをエンドユーザーに提供すべきとされています。shall ではなく should なので、実装が必須というわけではありません。ただし、アクセストークンを取り消せない認可サーバーを選定・導入したばっかりに大きな問題を抱え込んでしまった金融機関を現実に知っているので、個人的にはアクセストークン・リフレッシュトークン取り消し機能は必須級だと考えています。関連する議論として『[OAuth 2.0 + OpenID Connect のフルスクラッチ実装者が知見を語る](http://qiita.com/TakahikoKawasaki/items/f2a0d25a4f05790b3baa)』の『[アクセストークン](http://qiita.com/TakahikoKawasaki/items/f2a0d25a4f05790b3baa#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3)』も参照していただければと思います。

なお、アクセストークン・リフレッシュトークンを削除する API は [RFC 7009](https://tools.ietf.org/html/rfc7009)（OAuth 2.0 Token Revocation）として標準化されています。

| ✅ | エンドユーザーがアクセストークン・リフレッシュトークンを削除できる仕組みを提供すべき。 |
|:-:|:--|


## ***FAPI Part 2***

ここでは、更新系 API のセキュリティー要件を定める FAPI Part 2 から、既存の実装の改良もしくは新規開発が必要になる可能性の高い項目を書き出してみます。（注：全ての項目を網羅しているわけではありません。）


<br/>
> ***5.1 Introduction***
> ......
> ***s_hash***
> *State hash value. Its value is the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the `state` value, where the hash algorithm used is the hash algorithm used in the `alg` Header Parameter of the ID Token’s JOSE Header. For instance, if the `alg` is `HS512`, hash the code value with SHA-512, then take the left-mots 256 bits and base64url encode them. The s_hash value is a case sensitive string.*

`s_hash` というのは新たに定義されたクレームです。リクエストに含まれていた `state` パラメーターの値のハッシュ値を計算し、[ID トークン](http://openid.net/specs/openid-connect-core-1_0.html#IDToken)に埋め込んでクライアントに返します。ID トークンに埋め込む他のハッシュ値は、`at_hash`（アクセストークンのハッシュ）や `c_hash`（認可コードのハッシュ）が [OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html) で既に定義されています。

| ✅ | ID トークンに `s_hash` を埋め込む。 |
|:-:|:--|


<br/>
> ***5.2.2. Authorization Server***
> *1. shall require the `request` or `request_uri` parameter to be passed as a JWS signed JWT as in clause 6 of [OIDC];*

認可リクエストに `request` パラメーターもしくは `request_uri` パラメーターを付けることが必須となっています。さらっと書いてありますが、これはかなり重い要求になります。クライアントはリクエストを投げるためにリクエストオブジェクトを生成しなければならず、認可サーバーは [OpenID Connect Core 1.0](http://openid.net/specs/openid-connect-core-1_0.html) の [6. Passing Request Parameters as JWTs](http://openid.net/specs/openid-connect-core-1_0.html#JWTRequests) をサポートしなければなりません。

例えば `request_uri` でリクエストオブジェクトが指定された場合、認可サーバーは次のような処理を行うことになります。

1. `request_uri` で指定された場所にあるリクエストオブジェクトを取ってくる。
2. リクエストオブジェクトの署名検証用の鍵を得るためクライアントの [JWK Set](https://tools.ietf.org/html/rfc7517#section-5) を取ってくる。
  - クライアントの JWK Set が既に `jwks` [クライアントメタデータ](https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata)の値として登録されていればそれを使う。
  - 登録されていなければ、`jwks_uri` クライアントメタデータの値が指す場所からクライアントの JWK Set を取ってくる。
  - 毎回 JWK Set を取りに行くのはよくないので、適宜有効期間を計算してキャッシュする。
3. リクエストオブジェクトが暗号化されていれば復号化する。
4. リクエストオブジェクトの署名を検証する。
5. からの、[6. Passing Request Parameters as JWTs](http://openid.net/specs/openid-connect-core-1_0.html#JWTRequests) に記載されている各種整合性チェックを行う。

個人的な経験から、リクエストオブジェクトのサポートは OpenID Connect 関連仕様の中でもかなり実装が大変な部類に入ると考えています。

なお、[OpenID Connect Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html) の [2. Client Metadata](https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata) 内の `request_object_signing_alg` の説明によれば、`request_uri` パラメーターの指すリクエストオブジェクトに署名をしないケースも許容されますが、FAPI Part 2 の記述によれば署名は必須（*as a JWS* ***signed*** *JWT*）となっています。 

| ✅ | リクエストオブジェクトのサポートが必須。 |
|:-:|:--|


<br/>
> *2. shall require the `response_type` values `code id_token` or `code id_token token`;*

認可リクエストの `response_type` パラメーターの値は、`code id_token` もしくは `code id_token token` であることが求められています。短い文ですが、これも重い要求になります。

`reponse_type` に `id_token` が含まれるているので、認可リクエストの応答として必ず ID トークンが発行されることになります。この動作を実現するということは、OpenID Connect を実装することに等しいです。これまでは「OpenID プロバイダーになる気が無いのであれば OpenID Connect をサポートする必要はない」ということで済みましたが、FAPI Part 2 に対応する場合は、OpenID プロバイダーになるつもりがなくても OpenID Connect をサポートする必要があります。

| ✅ | OpenID Connect の実装が必須。 |
|:-:|:--|

元々は ID トークンはユーザー認証情報及び属性情報を引き回すためのものでしたが、FAPI Part 2 では、よりセキュリティーを高めるため、各種攻撃への対抗策として ID トークンを流用することにしています。下記は FPAI Part 2, 5.1. Introduction からの抜粋です。

> _to mitigate the attacks that leverage on the weak binding of endpoints in RFC6749 (e.g. Malicious Endpoints attacks, IdP Mix-up attacks) and attacks that involve modification of the authorization requests and responses that are not protected in [RFC6749] **by leveraging on OpenID Connect's Hybrid Flow that returns an ID Token** in the authorization response._

文章中にも明記されているので、OpenID Connect の[ハイブリッドフロー](http://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth)の実装が必要なことがわかります。世の中には「OpenID Connect をサポートしていると謳っているがハイブリッドフローはサポートしていない」という OpenID プロバイダーの実装はいくらでも存在するので、FAPI 用の認可サーバー実装を探す際は注意してください。

| ✅ | ハイブリッドフローの実装が必須。 |
|:-:|:--|


<br/>
>*shall only issue holder of key authorization code, access token, and refresh token for write operations;*
>*shall support [OAUTB] or [MTLS] as a holder of key mechanism;*

更新系操作のために認可コード・アクセストークン・リフレッシュトークンを発行する際はそれらのトークンをトークン所有者を特定するキーと紐付けて生成することが求められています（もちろん、それらのトークンが使用される際には正当なトークン所有者による使用であることを確認することになります）。そして、その実現方法として [OAuth 2.0 Token Binding](https://tools.ietf.org/html/draft-ietf-oauth-token-binding)（現在ドラフト段階）もしくは [Mutual TLS](https://tools.ietf.org/html/draft-ietf-oauth-mtls)（現在ドラフト段階）のどちらかをサポートすることが求められています。

OAuth 2.0 Token Binding をサポートする認可サーバーを実装するのが難しい理由は、他のレイヤーの実装を待たなければならないからです。トークンバインディングプロトコル（[The Token Binding Protocol Version 1.0](https://tools.ietf.org/html/draft-ietf-tokbind-protocol)（現在ドラフト段階））を使用するためは、クライアントとサーバーがトークンバインディングプロトコルのバージョンとパラメーター群について合意しなければならず、その合意手順は [Transport Layer Security (TLS) Extension for Token Binding Protocol Negotiation](https://tools.ietf.org/html/draft-ietf-tokbind-negotiation)（現在ドラフト段階）で定義されているものの、それは、TLS ハンドシェイクを拡張する形で実現されています。つまり、TLS レイヤーに手を入れなければなりません。その上で、TLS レイヤーでやり取りした内容を HTTP レイヤーに伝えることができる必要あります。というのも、[Token Binding over HTTP](https://tools.ietf.org/html/draft-ietf-tokbind-https)（現在ドラフト段階）に定義されている仕様に従い、トークンバインディングメッセージを `Sec-Token-Binding` という HTTP リクエストヘッダーの値として送信しなければならないからです。ここまで実現できてから、 OAuth 2.0 Token Binding 対応の認可サーバーを実装することになります。加えて OAuth 2.0 Token Binding の仕様には [RFC 7636](https://tools.ietf.org/html/rfc7636) で定義されている `code_challenge_method` パラメーターに対する拡張も含まれており、新たに `TB-S256` と `referred_tb` という値が定義されています。

OAuth 2.0 Token Binding に比べれば Mutual TLS の実装は難しいとは言えませんが、（１）トークンエンドポイントにおけるクライアント認証の方法として `tls_client_auth` が追加され（＝認可サーバーの `token_endpoint_auth_methods_supported` 属性およびクライアントの `token_endpoint_auth_method` 属性の取りうる値が一つ増え）、（２）クライアント証明書のサブジェクト識別名とルート発行者識別名の期待値を示す `tls_client_auth_subject_dn` と `tls_client_auth_root_dn` がクライアントのメタデータとして追加され、（３）アクセストークン自体か[イントロスペクション API](https://tools.ietf.org/html/rfc7662) の応答にクライアント証明書のハッシュ値を埋め込む、など、対応が必要な箇所が複数あります。

| ✅ | トークンバインディングもしくは Mutual TLS の実装が必須。 |
|:-:|:--|


<br/>
> *7. shall support user authentication at LoA 3 or greater as defined in [X.1254];*

FAPI Part 1 で求められるユーザー認証の LoA は 2 以上でしたが、FAPI Part 2 では 3 以上となっています。下記は [X.1254](https://www.itu.int/rec/T-REC-X.1254)（Entity authentication assurance framework）から LoA 3 の定義を抜粋したものです。

| X.1254, 6.3 Level of assurance 3 (LoA3) |
|:--|
| *At LoA3, there is high confidence in the claimed or asserted identity of the entity. This LoA is used where substantial risk is associated with erroneous authentication. This LoA shall employ multifactor authentication. Any secret information exchanged in authentication protocols shall be cryptographically protected in transit and at rest (although LoA3 does not require the use of a cryptographic-based challenge-response protocol). There are no requirements concerning the generation or storage of credentials; they may be stored or generated in general purpose computers or in special purpose hardware.*<br/><br/>*For example, a transaction in which a company submits certain confidential information electronically to a government agency may require an LoA3 authentication transaction. Improper disclosure could result in a substantial risk for financial loss. Other LoA3 transaction examples include online access to accounts that allow the entity to perform certain financial transactions, or use by a third party contractor of a remote system to access potentially sensitive client personal information.* |

| ✅ | FAPI Part 2 ではユーザー認証に LoA 3 以上が求められる。 |
|:-:|:--|


<br/>
> ***5.2.3. Public Client***
> ......
> *shall support [OAUTB] as a holder of key mechanism;*

Public クライアント（参照：RFC 6749, [2.1. Client Types](https://tools.ietf.org/html/rfc6749#section-2.1)）が更新系 API を使うためには、[Mutual TLS](https://tools.ietf.org/html/draft-ietf-oauth-mtls) ではなく[トークンバインディング](https://tools.ietf.org/html/draft-ietf-oauth-token-binding)を用いてアクセストークンの発行を受ける必要があるということです。なお、Confidential クライアントでは Mutual TLS も許容されます。

| ✅ | Public クライアント用にはトークンバインディングの実装が必須。 |
|:-:|:--|


<br/>
> ***5.2.4.  Confidential Client***
> ......
> *shall require both JWS signed and JWE encrypted ID Tokens to be returned from endpoints
> for write operations.*

Confidential クライアント（参照：RFC 6749, [2.1. Client Types](https://tools.ietf.org/html/rfc6749#section-2.1)）が更新系処理のためにアクセストークンの発行を受けるときは、認可リクエストの応答に含まれる ID トークンに対して、署名されていること及び暗号化されていることを要求しなければならないとされています。元々 ID トークンには署名が必須なので、追加要件は「ID トークンの暗号化」です。

ID トークンの暗号化に非対称鍵系アルゴリズムを用いる場合、クライアント側も [JWK Set](https://tools.ietf.org/html/rfc7517#section-5) を用意することが必要なのと、その JWK Set に認可サーバーがアクセスできるようにする仕組みを用意する、すなわち

* JWK Set そのものを認可サーバーに登録する、もしくは
* JWK Set の場所を示す URI のみを認可サーバーに登録して JWK Set を公開するサーバー自体は別途立てる、

という対応も必要になるので、作業項目が増えます。

署名・暗号の話も含めた ID トークンの構造に関する一般的な情報は『[[前編] IDトークンが分かれば OpenID Connect が分かる](http://qiita.com/TakahikoKawasaki/items/8f0e422c7edd2d220e06)』に解説してありますので、参考にしていただければと思います。

| ✅ | Confidential クライアントの更新系処理のために ID トークンの暗号化が必須。 |
|:-:|:--|


<br/>
> ***7. Request object endpoint***

セクションを一つ割いて「リクエストオブジェクトエンドポイント」という新たなエンドポイントの仕様が記述されています。これは、クライアントがリクエストオブジェクトを認可サーバーに登録するためのエンドポイントで、このエンドポイントからの応答には、認可リクエストの `request_uri` パラメーターの値として指定可能な URI が含まれます。簡単に言うと、クライアントのリクエストオブジェクトを認可サーバーにホスティングさせる仕組みです。

| ✅ | リクエストオブジェクトエンドポイントという新たな仕様が定義されている。 |
|:-:|:--|


<br/>
> ***8.6.  JWS algorithm considerations***
> ......
> *JWS signatures shall use the `PS256` or `ES256` algorithms for signing.*

[JSON Web Signature](https://tools.ietf.org/html/rfc7515)（JWS）の署名アルゴリズムとして、`PS256`（RSASSA-PSS using SHA-256 and MGF1 with SHA-256）もしくは `ES256`（ECDSA using P-256 and SHA-256）を使うこととされています（仕様書内の上記文言は今後若干変更される見込みです）。

JWS は汎用的な仕様で、OpenID Connect では [ID トークン](http://openid.net/specs/openid-connect-core-1_0.html#IDToken)や[リクエストオブジェクト](http://openid.net/specs/openid-connect-core-1_0.html#JWTRequests)、[ユーザー情報エンドポイント](http://openid.net/specs/openid-connect-core-1_0.html#UserInfo)の応答などで利用されています。JWS の仕様自体は [RFC 7515](https://tools.ietf.org/html/rfc7515)（JSON Web Signature）で定義されていますが、署名アルゴリズムのリストは別仕様書の [RFC 7518](https://tools.ietf.org/html/rfc7518)（JSON Web Algorithms）の [3.1. "alg" (Algorithm) Header Parameter Values for JWS](https://tools.ietf.org/html/rfc7518#section-3.1) にあります。そのリストには `PS256` や `ES256` 以外にも色々含まれており、特に、より強度のある `PS384`、`PS512`、`ES384`、`ES512` や、実装必須の `HS256`（HMAC using SHA-256）、実装推奨の `RS256`（RSASSA-PKCS1-v1_5 using SHA-256）などがあります。

なぜ `PS256` と `ES256` に限定されているのか疑問だったので、「[JWS signature algorithms for RW](https://bitbucket.org/openid/fapi/issues/101/jws-signature-algorithms-for-rw)」という質問を投げたところ、次の回答をもらうことができました。

> *From the interoperability point of view, it is good to have a limited set of algorithms to support. From that point of view, PS256 and ES256 seem to be good options given it provides adequate protection. We have ruled out RS256 because PKCS1-v1.5 is broken and insecure. (We knew that even when we were writing JWS but at the time the library support for PSS was limited so we opted for PKCS1-v1.5.) Algorithm 'none' is also ruled out for an obvious reason.*
>
>*I am OK with re-phrasing it as "Implementations shall implement `PS256` and `ES256` as the algorithm for JWS signatures. Algorithm `none` and `RS256` shall not be used."*

主旨を要約すると次のようになります。

> *相互運用性の観点からアルゴリズムの種類を制限するのがよい。PKCS1-v1.5 は安全ではないので、`RS256` は排除している（JWS 仕様策定時もこの問題は認識していたがライブラリ群のアルゴリズムサポート状況を勘案して PKCS1-v1.5 を選択）。言うまでもなくアルゴリズム `none` も排除している。*

つまり、`PS256` と `ES256` に限定しているのは、記述ミスではなく、意図的ということです。

[OpenID Connect Dynamic Client Registration 1.0](http://openid.net/specs/openid-connect-registration-1_0.html) に「`id_token_signed_response_alg`（ID トークンの署名に使うアルゴリズムを指定するパラメーター）が省略された場合は `RS256` とする」という記述もあるため、署名アルゴリズムとして `RS256` を決め打ちで使用し、他のアルゴリズムをサポートしない OpenID プロバイダーの実装も存在しますが、そのような実装を FAPI Part 2 用に使うためには、新たに `PS256` もしくは `ES256` のサポートを追加する必要があります。

| ✅ | JWS 署名アルゴリズムとして `PS256` もしくは `ES256` のサポートが必須。 |
|:-:|:--|

<sup>2017 年 8 月 02 日 追記： `RS256` しかサポートしていない HSM (Hardware Security Module) の扱いについて検討中です。「[JWS signature algorithms for RW](https://bitbucket.org/openid/fapi/issues/101/jws-signature-algorithms-for-rw)」への追加コメントと、「[FAPI Part 2 がImplementer’s Draft 投票通過しました](https://www.sakimura.org/2017/07/3821/)」（＠_Nat Zone）を参照してください。</sup>
<br/>
> ***10. Acknowledgement***
> *Following people contributed heavily towards this document.*
> ......
> _・Joseph Heenan (Authlete)_
> ......

いや、これは技術仕様には全く関係ないのですが、「[Authlete](https://www.authlete.com/) 社の英国在住スーパーエンジニアが FAPI 仕様策定作業に貢献している」という話でございます。なお、Authlete 社は、仕様策定作業への貢献だけではなく、FAPI 実装作業も進めています。

| ✅ | FAPI 仕様策定作業に Authlete 社も貢献している。 |
|:-:|:--|


## ***FAPI Part 3 〜 Part 5***

Part 3 から Part 5 はまだ Public Review 入りしておらず、これから内容が追加・変更されていくと予想されるので、現時点で事細かに技術詳細に言及するのは避けようと思います。


# **まとめ**

これまでに挙げた項目をここにまとめます。なお、これらが FAPI による新要求事項の全てというわけではないので注意してください。必要に応じて原文を参照してください。
<br/>

||クライアントシークレットのエントロピー|
|:-:|:--|
|通常|要求なし|
|FAPI|署名・暗号アルゴリズムに必要なエントロピーを持たせる。|
|目的|署名・暗号アルゴリズムの強度を意味あるものとするため。|
<br/>

||トークンエンドポイントのクライアント認証|
|:-:|:--|
|通常|Basic 認証やフォームパラメーター|
|FAPI|Mutual TLS もしくは JWT Client Assertion|
|目的|クライアント認証をより安全におこなうため。|
<br/>

||RFC 7636 実装|
|:-:|:--|
|通常|任意|
|FAPI|必須|
|目的|認可コード横取り攻撃への対抗策として。|
<br/>

||`redirect_uri` パラメーター|
|:--|:--|
|通常|条件によっては不要|
|FAPI|必須|
|目的|リダイレクト URI にまつわる脆弱性問題を回避するため。|
<br/>

||リダイレクト URI の合致条件|
|:--|:--|
|通常|RFC 3986, 6. Normalization and Comparison|
|FAPI|単純文字列比較による完全一致|
|目的|リダイレクト URI にまつわる脆弱性問題を回避するため。|
<br/>

||ユーザー認証の確からしさ|
|:--|:--|
|通常|要求なし|
|FAPI|参照系 API 用には LoA 2 以上、更新系 API 用には LoA 3 以上|
|目的|ユーザー認証の強度を高めるため。|
<br/>

||アクセストークン発行時の `scope` パラメーター|
|:--|:--|
|通常|要求したスコープ群と実際に付与されたスコープ群が異なれば必須|
|FAPI|必須|
|目的|付与されたスコープ群をはっきりさせるため。|
<br/>

||アクセストークンのエントロピー|
|:-:|:--|
|通常|要求なし|
|FAPI|128 ビット以上のエントロピーを持たせる。|
|目的|アクセストークンの推測による攻撃を難しくするため。|
<br/>

||エンドユーザーによるトークン削除|
|:-:|:--|
|通常|要求なし|
|FAPI|仕組みを提供すべき|
|目的|トークン不正利用発覚時にユーザー自身でも対処できるようにするため。|
<br/>

||`s_hash` クレーム|
|:-:|:--|
|通常|要求なし|
|FAPI|更新系 API 用には必須|
|目的|リクエストとレスポンスの改変攻撃への対策として。|
<br/>

||リクエストオブジェクトのサポート|
|:-:|:--|
|通常|任意|
|FAPI|更新系 API 用には必須|
|目的|リクエストの出所を検証できるようにするため。|
<br/>

||OpenID Connect のサポート|
|:-:|:--|
|通常|任意|
|FAPI|更新系 API 用には必須|
|目的|更新系 API 用の認可リクエストへの応答に ID トークンを含める必要があるため。|
<br/>

||ハイブリッドフローのサポート|
|:-:|:--|
|通常|任意|
|FAPI|更新系 API 用には必須|
|目的|更新系 API 用の認可リクエストへの応答で、アクセストークン and/or 認可コードに加え、ID トークンも同時に発行する必要があるため。|
<br/>

||トークン所有者とトークンの紐付け|
|:-:|:--|
|通常|要求なし|
|FAPI|更新系 API 用に必須で、confidential クライアントでは Mutual TLS もしくはトークンバインディングのどちらか、public クライアントではトークンバインディングが必須|
|目的|正当な所有者以外トークンを使えないようにするため。|
<br/>

||ID トークン暗号化|
|:-:|:--|
|通常|任意|
|FAPI|Confidential クライアントの更新系 API 用に必須|
|目的|ID トークンの内容を正当なクライアント以外読めないようにするため。|
<br/>

||リクエストオブジェクトエンドポイント|
|:-:|:--|
|通常|要求なし|
|FAPI|新しい仕様。ただし、必須ではない。|
|目的|リクエストオブジェクトのホスティングの役目を認可サーバーが担えるようにするため。|
<br/>

||JWS 署名アルゴリズム|
|:-:|:--|
|通常|`HS256` のサポートは必須。`RS256` と `ES256` のサポートは推奨。他は任意。|
|FAPI|`ES256` もしくは `PS256` に限定。ただし、`RS256` しかサポートしていない HSM（Hardware Security Module）の扱いについて検討中。 |
|目的|相互運用性を高めるため。`RS256` は、安全性を考慮し、意図的に排除されている。|
<br/>



# **おわりに**

FAPI セキュリティー要件のうち、実装において大きな技術課題となりそうな項目を私見で列挙しますと下記の通りです。

✅ OpenID Connect
✅ ハイブリッドフロー
✅ リクエストオブジェクト
✅ リクエストオブジェクトエンドポイント
✅ Mutual TLS
✅ トークンバインディング
✅ LoA 3

リクエストオブジェクトエンドポイント、Mutual TLS、トークンバインディングは、ドラフト段階の仕様のため、既存のプレイヤーも実装はこれからです。

より高いセキュリティーのため、認可サーバー、リソースサーバー、クライアントアプリケーションの実装作業が従来に比べて大変になりますが、頑張っていきましょう！