Skip to content

Latest commit

 

History

History
383 lines (305 loc) · 21.6 KB

File metadata and controls

383 lines (305 loc) · 21.6 KB

カスタマイズ

このドキュメントでは、この認可サーバーの実装をカスタマイズする方法を説明します。

概要

この認可サーバーの実装では、Authlete をバックエンドとして使用しています。 これは、(1) OAuth 2.0OpenID Connect の実装の中心となる部分が java-oauth-server のソースツリー内ではなくクラウド上の Authlete サーバー内にあること、そして (2) アクセストークンなどの認可データ、認可サーバー自体の設定やクライアントアプリケーションの設定が、 ローカルデータベース内ではなくクラウド上のデータベースに保存されるということ、 を意味します。 そのため、非常に単純化して言うと、次の図が示すように、 この実装はクライアントアプリケーションと Authlete サーバーの間の仲介役でしかありません。

+--------+          +-------------------+          +----------+
|        |          |                   |          |          |
| Client | <------> | java-oauth-server | <------> | Authlete |
|        |          |                   |          |          |
+--------+          +-------------------+          +----------+

とはいえ、Authlete は認可に特化しており、エンドユーザーの認証に関することは何もしないので、 認証に関わる機能は java-oauth-server のソースツリー内に実装されています。

ですので、少なくとも、エンドユーザーの認証に関する部分についてはカスタマイズが必要です。 一方、認可画面の UI デザインなどの他の部分のカスタマイズは任意です。

全体の構成

Authlete が提供する Web API を使い、認可サーバーを書くことができます。 authlete-java-common は、その Web API と直接通信をおこなうライブラリです。 authlete-java-jaxrs は、authlete-java-common API をラッピングするユーティリティークラス群を含むライブラリで、それらのクラス群を使えば、 authlete-java-common API を直接使用するよりもかなり簡単に認可サーバーを書くことができます。 java-oauth-server は、authlete-java-jaxrs のユーティリティークラス群によって構成される authlete-java-jaxrs API を使用して書かれています。

名前が示唆するように、authlete-java-jaxrs ライブラリは JAX-RS 2.0 API に依存しています。 JAX-RS は The Java API for RESTful Web Services の略称です。 JAX-RS 2.0 API は JSR 339 で標準化され、Java EE 7 に含まれています。

次の図は、これまでに言及したコンポーネント群の関係を示したものです。

+-------------------------------+
|          java-oauth-server    |
+----+--------------------------+
|    |     authlete-java-jaxrs  |
|    +---+----------------------+          +----------+
| JAX-RS | authlete-java-common | <------> | Authlete |
+--------+----------------------+          +----------+

認可エンドポイント

認可エンドポイントの実装は AuthorizationEndpoint.java 内にあります。 OAuth 2.0 に加えて OpenID Connect もサポートしているにもかかわらず、実装は信じられないほど短いです。 このファイルを変更する必要はほとんどないでしょう。

実装では、AuthorizationRequestHandler クラスを使い、認可リクエストを処理する作業をそのクラスの handle() メソッドに委譲しています。 クラスの詳細については authlete-java-jaxrs ライブラリの README ファイルに書かれています。 ここで重要なのは、このクラスのコンストラクタが AuthorizationRequestHandlerSpi インターフェースの実装を必要とし、その実装はあなたが提供しなければならないという点です。 別の言い方をすると、AuthorizationRequestHandlerSpi インターフェースのメソッド群がカスタマイズポイントです。

当該インターフェースには、次のようなメソッド群が定義されています。 これらのメソッド群の要求事項の詳細については authlete-java-jaxrs API の JavaDoc を参照してください。

  1. boolean isUserAuthenticated()
  2. long getUserAuthenticatedAt()
  3. String getUserSubject()
  4. String getAcr()
  5. Response generateAuthorizationPage(AuthorizationResponse)

これらの中で最も重要なメソッドは generateAuthorizationPage() です。 このメソッドは認可ページを生成するために呼ばれます。 対照的に、他のメソッド群は、認可リクエストが prompt=none という特別なリクエストパラメーターを含んでいる場合しか呼ばれないので、それほど重要ではありません。 もしも prompt=none をサポートする気がないのであれば、それらのメソッド群の実装は空でかまいません。 prompt=none の詳細については OpenID Connect Core 1.03.1.2.1. Authorization Request に記述されています。

java-oauth-server における AuthorizationRequestHandlerSpi インターフェースの実装は AuthorizationRequestHandlerSpiImpl.java です。 ファイル内の AuthorizationRequestHandlerSpiImpl という実装クラスは、AuthorizationRequestHandlerSpi インターフェースの空実装である AuthorizationRequestHandlerSpiAdapter クラスを拡張し、generateAuthorizationPage() メソッドのみをオーバーライドしています。 下記のコードは、実装のおおまかな構造を示してます。

class AuthorizationRequestHandlerSpiImpl extends AuthorizationRequestHandlerSpiAdapter
{
    ......

    @Override
    public Response generateAuthorizationPage(AuthorizationResponse info)
    {
        ......
    }
}

認可ページ

既に述べたとおり、AuthorizationRequestHandlerSpi インターフェースの generateAuthorizationPage() メソッドは認可ページを生成するために呼ばれます。 java-oauth-server の現在の実装では、(Authlete の /api/auth/authorization API からの応答を表す AuthorizationResponse クラスのインスタンスである) 引数からデータを取り出し、そのデータを authorization.jsp という HTML テンプレートに埋め込みます。 これをおこなうため、実装では Viewable というクラスを使用しています。 このクラスは Jersey (JAX-RS のレファレンス実装) に含まれていますが、JAX-RS 2.0 API の一部ではありません。

認可ページをカスタマイズしたい場合は、generateAuthorizationPage() メソッドと認可ページのテンプレート (authorization.jsp) のどちらか、もしくは両方を変更してください。 AuthorizationResponse クラスの詳細については authlete-java-common ライブラリの JavaDoc を参照してください。

国際化

認可ページの国際化に際して、認可リクエストに含まれる ui_locales パラメーターを考慮に入れてもよいでしょう。 これは OpenID Connect Core 1.0 で新たに定義されたリクエストパラメーターです。 下記は、このパラメータに関する説明を仕様から抜粋したものです。

OPTIONAL. End-User's preferred languages and scripts for the user interface, represented as a space-separated list of BCP47 [RFC5646] language tag values, ordered by preference. For instance, the value "fr-CA fr en" represents a preference for French as spoken in Canada, then French (without a region designation), followed by English (without a region designation). An error SHOULD NOT result if some or all of the requested locales are not supported by the OpenID Provider.

AuthorizationResponse インスタンスの getUiLocales() メソッドを呼ぶことで、ui_locales リクエストパラメーターの値を String の配列として取得することができます。 ただし、getUiLocales() メソッドはサポートされている UI ロケールしか返さないので、 管理コーンソール (Service Owner Console) を使って明示的に UI ロケールを指定する必要があることに注意してください。 別の言い方をすると、ui_locales リクエストパラメーターがどのような値であろうとも、getUiLocales() が返す配列にはサポートしている UI ロケールしか含まれていないことが保証されています。

ui_locales パラメーターを尊重するか否かはあなたの自由です。 もちろん、認可ページの国際化は好きな方法でおこなうことができます。

表示モード

認可リクエストには認可ページの表示方法を指定するための display パラメーターが含まれることがあります。 これは OpenID Connect Core 1.0 で定義された新しいパラメーターです。 このリクエストパラメーターが取りうる定義済みの値は次のとおりです。 表中の説明は仕様からの抜粋です。

説明
page The Authorization Server SHOULD display the authentication and consent UI consistent with a full User Agent page view. If the display parameter is not specified, this is the default display mode.
popup The Authorization Server SHOULD display the authentication and consent UI consistent with a popup User Agent window. The popup User Agent window should be of an appropriate size for a login-focused dialog and should not obscure the entire window that it is popping up over.
touch The Authorization Server SHOULD display the authentication and consent UI consistent with a device that leverages a touch interface.
wap The Authorization Server SHOULD display the authentication and consent UI consistent with a "feature phone" type display.

AuthorizationResponse インスタンスの getDisplay() メソッドで、display リクエストパラメーターの値を列挙型 Display のインスタンスとして取得することができます。 デフォルトでは、管理コンソール (Service Owner Console) では全ての表示タイプがチェックされており、サポートしていることを示していますが、 チェックをはずすことでサポートしないと宣言することもできます。 サポートしていない値が display リクエストパラメーターに指定された場合、 その認可リクエストを出したクライアントアプリケーションには invalid_request エラーが返されることになります。

TBW

認可決定エンドポイント

認可ページでエンドユーザーは、認可リクエストをおこなったクライアントアプリケーションに権限を与えるか、 もしくは認可リクエストを拒否するか、どちらかを選択します。 認可サーバはその決定を受け取り、それに従ってクライアントアプリケーションに適切な応答を返せなければなりません。

java-oauth-server の現在の実装は、エンドユーザーの決定を /api/authorization/decision で受け取ります。 この文書では、当該エンドポイントを認可決定エンドポイントと呼びます。 java-oauth-server では、認可決定エンドポイントの実装は AuthorizationDecisionEndpoint.java 内にあります。

実装では、AuthorizationDecisionHandler クラスを使い、エンドユーザーの決定を処理する作業をそのクラスの handle() メソッドに委譲しています。 クラスの詳細については authlete-java-jaxrs ライブラリの README ファイルに書かれています。 ここで重要なのは、このクラスのコンストラクタが AuthorizationDecisionHandlerSpi インターフェースの実装を必要とし、その実装はあなたが提供しなければならないという点です。 別の言い方をすると、AuthorizationDecisionHandlerSpi インターフェースのメソッド群がカスタマイズポイントです。

当該インターフェースには、次のようなメソッド群が定義されています。 これらのメソッド群の要求事項の詳細については authlete-java-jaxrs API の JavaDoc を参照してください。

  1. boolean isClientAuthorized()
  2. long getUserAuthenticatedAt()
  3. String getUserSubject()
  4. String getAcr()
  5. getUserClaim(String claimName, String languageTag)

java-oauth-server における AuthorizationDecisionHandlerSpi インターフェースの実装は AuthorizationDecisionHandlerSpiImpl.java です。 ファイル内の AuthorizationDecisionHandlerSpiImpl という実装クラスは、AuthorizationDecisionHandlerSpi インターフェースの空実装である AuthorizationDecisionHandlerSpiAdapter クラスを拡張し、getAcr() 以外のメソッド群を全てをオーバーライドしています。 下記のコードは、実装のおおまかな構造を示してます。

class AuthorizationDecisionHandlerSpiImpl extends AuthorizationDecisionHandlerSpiAdapter
{
    ......

    @Override
    public boolean isClientAuthorized()
    {
        ......
    }

    @Override
    public long getUserAuthenticatedAt()
    {
        ......
    }

    @Override
    public String getUserSubject()
    {
        ......
    }

    @Override
    public Object getUserClaim(String claimName, String languageTag)
    {
        ......
    }
}

エンドユーザー認証

エンドユーザーをどのように認証するかについては、Authlete は全く気にしません。 その代わりに、Authlete は認証されたエンドユーザーのサブジェクトを要求します。

「サブジェクト」はアイデンティティー関連分野の専門用語で、一意識別子のことを意味します。 典型的には、エンドユーザーのサブジェクトは、 ユーザーデータベース内のプライマリーキーカラムもしくは他のユニークカラムの値です。

エンドユーザーがクライアントアプリケーションに権限を与えたときは、そのエンドユーザーのサブジェクトを Authlete に伝える必要があります。 AuthorizationDecisionhandlerSpi インターフェースの文脈では、 次のように表現することができます: 「もしも isClientAuthorized()true を返すのであれば、そのときは getUserSubject() はエンドユーザーのサブジェクトを返さなければならない。」

エンドユーザー認証のため、java-oauth-server には UserDao クラスと UserEntity クラスがあります。この二つのクラスでダミーのユーザーデータベースを構成しています。 もちろん、実際のユーザーデータベースを参照するためには、これらをあなたの実装で置き換える必要があります。

トークンエンドポイント

トークンエンドポイントの実装は TokenEndpoint.java 内にあります。 実装は信じられないほど短く、ファイルの内容を変更する必要はほとんどないでしょう。

実装では、TokenRequestHandler クラスを使い、トークンリクエストを処理する作業をそのクラスの handle() メソッドに委譲しています。 クラスの詳細については authlete-java-jaxrs ライブラリの README ファイルに書かれています。 ここで重要なのは、このクラスのコンストラクタが TokenRequestHandlerSpi インターフェースの実装を必要とし、その実装はあなたが提供しなければならないという点です。 別の言い方をすると、TokenRequestHandlerSpi インターフェースのメソッド群がカスタマイズポイントです。

当該インターフェースの現在の定義には、authenticateUser というメソッドが一つだけ含まれています。 このメソッドは、エンドユーザーを認証するのに使用されます。 しかし、このメソッドが呼ばれるのはトークンリクエストの認可タイプが Resource Owner Password Credentials の場合のみです。 そのため、この認可タイプをサポートする気が無いのであれば、メソッドの実装は空でかまいません。

java-oauth-server における TokenRequestHandlerSpi インターフェースの実装は TokenRequestHandlerSpiImpl.java です。 ファイル内の TokenRequestHandlerSpiImpl という実装クラスは、TokenRequestHandlerSpi インターフェースの空実装である TokenRequestHandlerSpiAdapter クラスを拡張し、authenticateUser() メソッドをオーバーライドしています。 下記のコードは、実装のおおまかな構造を示してます。

class TokenRequestHandlerSpiImpl extends TokenRequestHandlerSpiAdapter
{
    ......

    @Override
    public String authenticateUser(String username, String password)
    {
        ......
    }
}

イントロスペクションエンドポイント

イントロスペクションエンドポイントの実装は IntrospectionEndpoint.java 内にあります。

RFC 7662 (OAuth 2.0 Token Introspection) は、イントロスペクションエンドポイントを何らかの方法で保護することを要求しています。 IntrospectionEndpoint.java 内の保護の実装はデモンストレーション用のものであり、商用利用には向かないので、適宜変更してください。

その他の情報

コンタクト

目的 メールアドレス
一般 info@authlete.com
営業 sales@authlete.com
広報 pr@authlete.com
技術 support@authlete.com