このライブラリは、OAuth 2.0 および OpenID Connect をサポートする認可サーバーと、 リソースサーバーを実装するためのユーティリティークラス群を提供します。
このライブラリは、JAX-RS 2.0 API と authlete-java-common ライブラリを用いて書かれています。 JAX-RS は The Java API for RESTful Web Services です。 JAX-RS 2.0 API は JSR 339 で標準化され、Java EE 7 に含まれています。 一方、authlete-java-common は Authlete が提供するもう一つのオープンソースライブラリで、Authlete Web API とやりとりするためのクラス群を含んでいます。
Authlete は OAuth 2.0 と OpenID Connect の実装を提供するクラウドサービスです (overview)。 認可データ (アクセストークン等) や認可サーバー自体の設定、クライアントアプリケーション群の設定はクラウド上の Authlete サーバーに保存されるため、Authlete を使うことで「DB レス」の認可サーバーを構築することができます。
java-oauth-server はこのライブラリを使用している認可サーバーの実装で、 認可エンドポイントやトークンエンドポイントに加え、JWK Set エンドポイント、 設定エンドポイント、取り消しエンドポイントの実装を含んでいます。 また、java-resource-server はこのライブラリを使用しているリソースサーバーの実装です。 OpenID Connect Core 1.0 で定義されているユーザー情報エンドポイント をサポートし、また、保護リソースエンドポイントの例を含んでいます。 あなたの認可サーバーおよびリソースサーバーの実装の開始点として、 これらのリファレンス実装を活用してください。
Apache License, Version 2.0
<dependency>
<groupId>com.authlete</groupId>
<artifactId>authlete-java-jaxrs</artifactId>
<version>${authlete-java-jaxrs.versin}</version>
</dependency>
${authlete-java-jaxrs.version}
の箇所に書き込む最新バージョンについては
CHANGES.ja.md ファイルを参照してください。
https://github.com/authlete/authlete-java-jaxrs
https://authlete.github.io/authlete-java-jaxrs
https://authlete.github.io/authlete-java-jaxrs/index.html?overview-summary.html
[FRAMES]
認可サーバーは次のエンドポイントを公開することが期待されています。
- 認可エンドポイント (RFC 6749, 3.1.)
- トークンエンドポイント (RFC 6749, 3.2)
このライブラリは、これらのエンドポイントを実装するためのユーティリティークラス群を提供します。 また、下記のエンドポイント用のユーティリティークラス群も含んでいます。
- JWK Set エンドポイント (OpenID Connect Core 1.0)
- 設定エンドポイント (OpenID Connect Discovery 1.0)
- 取り消しエンドポイント (RFC 7009)
- ユーザー情報エンドポイント (OpenID Connect Core 1.0)
- イントロスペクションエンドポイント (RFC 7662)
AuthorizationRequestHandler
はクライアントアプリケーションからの認可リクエストを処理するためのクラスです。
このクラスには、認可リクエストのリクエストパラメーター群を表す MultivaluedMap<String, String>
インスタンスを引数として取る handle()
というメソッドがあります。
public Response handle(MultivaluedMap<String, String> parameters)
throws WebApplicationException
認可エンドポイントの実装は、認可リクエストを処理するという作業をこの
handle()
メソッドに委譲することができます。
JAX-RS を使用しているのであれば、リクエストパラメーター群を含む
MultivaluedMap<String, String>
インスタンスを取得して handle()
メソッドを呼ぶことは簡単な作業です。 しかし、ポイントは他の場所にあります。
AuthorizationRequestHandlerSpi
インターフェースの実装を用意して
AuthorizationRequestHandler
のコンストラクタに渡す必要があるのです。
AuthorizationRequestHandlerSpi
は、AuthorizationRequestHandler
の
handle()
メソッドの動作を制御するための「サービス提供者インターフェース
(Service Provider Interface)」で、あなたが実装することになります。
まとめると、認可エンドポイント実装内のフローは次のようになります。
// 認可リクエストのリクエストパラメーター群
MultivaluedMap<String, String> parameters = ...;
// AuthleteApi インターフェースの実装。
// 詳細は https://github.com/authlete/authlete-java-common を参照のこと。
AuthleteApi api = ...;
// AuthorizationRequestHandlerSpi インターフェースの実装。
AuthorizationRequestHandlerSpi spi = ...;
// AuthoriationRequestHandler クラスのインスタンスを作成する。
AuthorizationRequestHandler handler =
new AuthorizationRequestHandler(api, spi);
// 認可リクエストを処理する作業をハンドラーに委譲する。
Response response = handler.handle(parameters);
// クライアントアプリケーションにレスポンスを返す。
return response;
AuthorizationRequestHandlerSpi
に定義されているメソッド群のうち、最も重要なメソッドは
generateAuthorizationPage()
です。 このメソッドは認可ページを生成するために呼ばれます。
このメソッドは、Authlete の /api/auth/authorization
Web API からの応答を表す
AuthorizationResponse
クラスのインスタンスを受け取ります。
そのインスタンスには、認可ページを生成するのに必要な情報が含まれています。
Response generateAuthorizationPage(AuthorizationResponse info);
詳細は JavaDoc 及びリファレンス実装 (java-oauth-server) を参照してください。
認可ページは、クライアントアプリケーションの名前や要求されている権限等の、認可リクエストに含まれる情報を表示します。 ユーザーはその情報を確認し、リクエストを認可するか拒否するかを決めます。 認可サーバーはその決定を受け取り、その決定に対応する応答を返します。 そのため、認可サーバーは、認可エンドポイントに加え、ユーザーによる決定を受け取るエンドポイントを用意しなければなりません。
AuthorizationDecisionHandler
はその決定を処理するためのクラスです。
このクラスには、AuthorizationRequestHandler
と同じように handle()
メソッドがあります。 また、このクラスのコンストラクターは、AuthorizationRequestHandler
のコンストラクターと同じように、AuthorizationDecisionHandlerSpi
インターフェースの実装を要求します。
TokenRequestHandler
はクライアントアプリケーションからのトークンリクエストを処理するためのクラスです。
このクラスには、MultivaluedMap<String, String>
と String
の二つの引数を取る
handle()
メソッドがあります。 MultivaluedMap
引数はリクエストパラメーター群を表します。
一方の String
引数はトークンリクエストに含まれる Authorization
ヘッダーの値です。
public Response handle(
MultivaluedMap<String, String> parameters, String authorization)
throws WebApplicationException
トークンエンドポイントの実装は、トークンリクエストを処理する作業を
handle()
メソッドに委譲することができます。
TokenRequestHandler
のコンストラクターは、AuthorizationRequestHandler
のコンストラクターと同じように、TokenRequestHandlerSpi
インターフェースの実装を要求します。
まとめると、トークンエンドポイント実装内のフローは次のようになります。
// トークンリクエストのリクエストパラメーター群
MultivaluedMap<String, String> parameters = ...;
// Authorization ヘッダーの値
String authorization = ...;
// AuthleteApi インターフェースの実装。
// 詳細は https://github.com/authlete/authlete-java-common を参照のこと。
AuthleteApi api = ...;
// TokenRequestHandlerSpi インターフェースの実装。
TokenRequestHandlerSpi spi = ...;
// TokenRequestHandler クラスのインスタンスを生成する。
TokenRequestHandler handler = new TokenRequestHandler(api, spi);
// トークンリクエストを処理する作業をハンドラーに委譲する。
Response response = handler.handle(parameters, authorization);
// クライアントアプリケーションにレスポンスを返す。
return response;
OpenID プロバイダーは、クライアントアプリケーションが (1) OpenID プロバイダーの署名を検証できるように、また、(2) OpenID プロバイダーへのリクエストを暗号化できるように、JSON Web Key Set ドキュメント (JWK Set) を公開する必要があります。
JwksRequestHandler
はそのようなエンドポイントへのリクエストを処理するためのクラスです。
このクラスは SPI 実装を要求しないので、使い方は簡単です。
// AuthleteApi インターフェースの実装。
// 詳細は https://github.com/authlete/authlete-java-common を参照のこと。
AuthleteApi api = ...;
// JwksRequestHandler クラスのインスタンスを生成する。
JwksRequestHandler handler = new JwksRequestHandler(api);
// リクエストの処理をハンドラーに委譲する。
Response response = handler.handle();
// クライアントアプリケーションにレスポンスを返す。
return response;
さらに、BaseJwksEndpoint
クラスはこの作業を信じられないほど簡単にします。
下記は、JWK Set エンドポイントの完全な実装例です。 BaseJwksEndpoint
の
handle()
メソッドは内部で JwksRequestHandler
を使用しています。
@Path("/api/jwks")
public class JwksEndpoint extends BaseJwksEndpoint
{
@GET
public Response get()
{
// JWK Set リクエストを処理する。
return handle(AuthleteApiFactory.getDefaultApi());
}
}
OpenID Connect Discovery 1.0 をサポートする OpenID プロバイダーは、自身の設定情報を JSON フォーマットで返すエンドポイントを提供しなければなりません。フォーマットの詳細は OpenID Connect Discovery 1.0 の 3. OpenID Provider Metadata に記述されています。
ConfigurationRequestHandler
はそのような設定エンドポイントへのリクエストを処理するためのクラスです。
このクラスは SPI 実装を要求しないので、使い方は簡単です。
// AuthleteApi インターフェースの実装。
// 詳細は https://github.com/authlete/authlete-java-common を参照のこと。
AuthleteApi api = ...;
// ConfigurationRequestHandler クラスのインスタンスを作成する。
ConfigurationRequestHandler handler = new ConfigurationRequestHandler(api);
// リクエストの処理をハンドラーに委譲する。
Response response = handler.handle();
// クライアントアプリケーションにレスポンスを返す。
return response;
さらに、BaseConfigurationEndpoint
クラスはこの作業を信じられないほど簡単にします。
下記は、設定エンドポイントの完全な実装例です。 BaseConfigurationEndpoint
の
handle()
メソッドは内部で ConfigurationRequestHandler
を使用しています。
@Path("/.well-known/openid-configuration")
public class ConfigurationEndpoint extends BaseConfigurationEndpoint
{
@GET
public Response get()
{
// 設定リクエストを処理する。
return handle(AuthleteApiFactory.getDefaultApi());
}
}
設定エンドポイントの URI は OpenID Connct Discovery 1.0 の 4.1. OpenID Provider Configuration Request で定義されていることに注意してください。 手短に言うと、URI は次の通りでなければなりません。
発行者識別子 + /.well-known/openid-configuration
発行者識別子 は OpenID プロバイダーを識別するための URL です。
例えば https://example.com
となります。
発行者識別子の詳細については、3. OpenID Provider Meatadata
(OpenID Connect Discovery 1.0) の issuer
、および 2. ID Token
(OpenID Connect Core 1.0) の iss
を参照してください。
認可サーバーは、アクセストークンやリフレッシュトークンを取り消すエンドポイントを公開してもよいです。 RFC 7009 はそのような取り消しエンドポイントに関する仕様です。
RevocationRequestHandler
は取り消しリクエストを処理するためのクラスです。
このクラスには、MultivaluedMap<String, String>
と String
の二つの引数を取る
handle()
メソッドがあります。 MultivaluedMap
引数はリクエストパラメーター群を表します。
一方の String
引数は取り消しリクエストに含まれる Authorization
ヘッダーの値です。
public Response handle(
MultivaluedMap<String, String> parameters, String authorization)
throws WebApplicationException
取り消しエンドポイントの実装は、取り消しリクエストを処理する作業を
handle()
メソッドに委譲することができます。
// 取り消しリクエストのリクエストパラメーター群
MultivaluedMap<String, String> parameters = ...;
// Authorization ヘッダーの値
String authorization = ...;
// AuthleteApi インターフェースの実装。
// 詳細は https://github.com/authlete/authlete-java-common を参照のこと。
AuthleteApi api = ...;
// RevocationRequestHandler クラスのインスタンスを作成する。
RevocationRequestHandler handler = new RevocationRequestHandler(api);
// 取り消しリクエストの処理をハンドラーに委譲する。
Response response = handler.handle(parameters, authorization);
// クライアントアプリケーションにレスポンスを返す。
return response;
さらに、BaseRevocationEndpoint
クラスはこの作業を信じられないほど簡単にします。
下記は、取り消しエンドポイントの完全な実装例です。 BaseRevocationEndpoint
の
handle()
メソッドは内部で RevocationRequestHandler
を使用しています。
@Path("/api/revocation")
public class RevocationEndpoint extends BaseRevocationEndpoint
{
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(
@HeaderParam(HttpHeaders.AUTHORIZATION) String authorization,
MultivaluedMap<String, String> parameters)
{
// 取り消しリクエストを処理する。
return handle(AuthleteApiFactory.getDefaultApi(), parameters, authorization);
}
}
ユーザー情報エンドポイントは、ユーザー情報を JSON または JWT フォーマットで返す保護リソースエンドポイントです。 このエンドポイントの動作は OpenID Connect Core 1.0 の 5.3. UserInfo Endpoint に記述されています。
UserInfoRequestHandler
はユーザー情報リクエストを処理するためのクラスです。
このクラスには、アクセストークンを引数に取る handle(String)
というメソッドがあります。
ユーザー情報エンドポイントの実装では、ユーザー情報リクエストの処理をこの handle()
メソッドに委譲することができます。
UserInfoRequestHandler
クラスのコンストラクタは、実装固有の動作を制御するため、
UseInfoRequestHandlerSpi
の実装を要求します。 この SPI クラスの主な目的は、
ユーザー情報エンドポイントからの応答に埋め込むクレーム値を集めることです。
次のコードは UserInfoRequestHandler
の使い方を示すものです。
// AuthleteApi インターフェースの実装。
// 詳細は https://github.com/authlete/authlete-java-common を参照のこと。
AuthleteApi api = ...;
// UserInfoRequestHandlerSpi インターフェースの実装。
UserInfoRequestHandlerSpi spi = ...;
// UserInfoRequestHandler クラスのインスタンスを作成する。
UserInfoRequestHandler handler = new UserInfoRequestHandler(api, spi);
// ユーザー情報リクエストに含まれているアクセストークン。
String accessToken = ...;
// ユーザー情報リクエストの処理をハンドラーに委譲する。
Response response = handler.handle(accessToken);
// クライアントアプリケーションにレスポンスを返す。
return response;
さらに、BaseUserInfoEndpoint
クラスはこの作業を信じられないほど簡単にします。
下記は、ユーザー情報エンドポイントの実装例です。 BaseUserInfoEndpoint
の
handle()
メソッドは内部で UserInfoRequestHandler
を使用しています。
ユーザー情報エンドポイントはアクセストークンを Bearer Token (RFC 6750)
として受け取らなければならないことに注意してください。
@Path("/api/userinfo")
public class UserInfoEndpoint extends BaseUserInfoEndpoint
{
@GET
public Response get(
@HeaderParam(HttpHeaders.AUTHORIZATION) String authorization,
@QueryParam("access_token") String accessToken)
{
return handle(extractAccessToken(authorization, accessToken));
}
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(
@HeaderParam(HttpHeaders.AUTHORIZATION) String authorization,
@FormParam("access_token") String accessToken)
{
return handle(extractAccessToken(authorization, accessToken));
}
private Response handle(String accessToken)
{
return handle(AuthleteApiFactory.getDefaultApi(),
new UserInfoRequestHandlerSpiImpl(), accessToken);
}
}
認可サーバーは、アクセストークンやリフレッシュトークンの情報を取得するエンドポイントを公開してもよいです。 そのようなエンドポイントはイントロスペクションエンドポイントと呼ばれ、RFC 7662 で標準仕様が定義されています。
IntrospectionRequestHandler
はイントロスペクションリクエストを処理するためのクラスです。
このクラスには、MultivaluedMap<String, String>
型の引数を取る handle()
メソッドがあります。
この引数はリクエストパラメーター群を表します。
public Response handle(MultivaluedMap<String, String> parameters)
throws WebApplicationException
イントロスペクションエンドポイントの実装は、イントロスペクションリクエストを処理する作業を
handle()
メソッドに委譲することができます。
// イントロスペクションリクエストのリクエストパラメーター群
MultivaluedMap<String, String> parameters = ...;
// AuthleteApi インターフェースの実装。
// 詳細は https://github.com/authlete/authlete-java-common を参照のこと。
AuthleteApi api = ...;
// IntrospectionRequestHandler クラスのインスタンスを作成する。
IntrospectionRequestHandler handler = new IntrospectionRequestHandler(api);
// イントロスペクションリクエストの処理をハンドラーに委譲する。
Response response = handler.handle(parameters);
// クライアントアプリケーションにレスポンスを返す。
return response;
さらに、BaseIntrospectionEndpoint
クラスはこの作業を信じられないほど簡単にします。
下記は、イントロスペクションエンドポイントの実装例です。 BaseIntrospectionEndpoint
の
handle()
メソッドは内部で IntrospectionRequestHandler
を使用しています。
@Path("/api/introspection")
public class IntrospectionEndpoint extends BaseIntrospectionEndpoint
{
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(MultivaluedMap<String, String> parameters)
{
// RFC 7662 はイントロスペクションエンドポイントを保護することを
// 要求しています。ですので、handle() メソッドを呼ぶ前に、API
// 呼出し者が必要な権限を持っているか確認してください。
// イントロスペクションリクエストを処理する。
return handle(AuthleteApiFactory.getDefaultApi(), parameters);
}
}
RFC 7662 の 2.1. Introspection Request には "To prevent
token scanning attacks, the endpoint MUST also require some form of
authorization to access this endpoint"
(トークンスキャン攻撃を防ぐため、エンドポイントへのアクセスには何らかの権限を要求しなければならない)
という記述があるので注意してください。このため、イントロスペクションエンドポイントの実際の実装では
handle()
メソッドを呼ぶ前に API 呼出し者が必要な権限を持っていることを確認する必要があります。
authlete-java-common のバージョン 2.9 で追加された Settings
クラスの
setConnectionTimeout(int)
メソッドを使うことで、接続タイムアウトを設定することができます。
しかし、(Java EE 8 の一部である) JAX-RS API 2.1
策定前は、接続タイムアウトを設定する方法が標準化されていないため、JAX-RS クライアント
API の実装によっては、setConnectionTimeout(int)
による設定が反映されません。
本ライブラリの setConnectionTimeout(int)
の実装は、Jersey 等、幾つかの
JAX-RS クライアント実装をサポートしています。
具体的なサポート状況についてはソースコードを参照してください。
authlete-java-common のバージョン 2.10 で追加された setReadTimeout(int)
メソッドも setConnectionTimeout(int)
メソッドと同じ問題を抱えています。
このライブラリにより、OAuth 2.0 と OpenID Connect をサポートする認可サーバー、およびリソースサーバーの実装作業が簡単になります。 詳細は JavaDoc 及びリファレンス実装 (java-oauth-server および java-resource-server) を参照してください。
- Authlete - Authlete ホームページ
- java-oauth-server - 認可サーバーの実装
- java-resource-server - リソースサーバーの実装
- authlete-java-common - Java 用 Authlete 共通ライブラリ
目的 | メールアドレス |
---|---|
一般 | [email protected] |
営業 | [email protected] |
広報 | [email protected] |
技術 | [email protected] |