コアモデル / コンポーネント

RegisteredClient

RegisteredClient は、認可サーバーに登録 [IETF] (英語) されているクライアントの表現です。authorization_code や client_credentials などの認可付与フローを開始する前に、クライアントを認可サーバーに登録する必要があります。

クライアントの登録時に、クライアントには一意のクライアント識別子 [IETF] (英語) 、(オプションで) クライアントシークレット ( クライアント型 [IETF] (英語) に応じて)、および一意のクライアント識別子に関連付けられたメタデータが割り当てられます。クライアントのメタデータは、人間向けの表示文字列 (クライアント名など) から、プロトコルフローに固有の項目 (有効なリダイレクト URI のリストなど) までさまざまです。

Spring Security の OAuth2 クライアントサポートで対応するクライアント登録モデルは ClientRegistration です。

クライアントの主な目的は、保護されたリソースへのアクセスをリクエストすることです。クライアントはまず、認可サーバーで認証し、認可付与を提示することで、アクセストークンをリクエストします。認可サーバーは、クライアントと認可付与を認証し、有効であればアクセストークンを発行します。クライアントは、アクセストークンを提示することで、リソースサーバーから保護されたリソースをリクエストできるようになりました。

次の例は、authorization_code グラント [IETF] (英語) フローを実行してアクセストークンをリクエストすることを認可されている RegisteredClient を構成する方法を示しています。

RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
	.clientId("client-a")
	.clientSecret("{noop}secret")   (1)
	.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
	.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
	.redirectUri("http://127.0.0.1:8080/authorized")
	.scope("scope-a")
	.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
	.build();
1{noop} は、Spring Security の NoOpPasswordEncoder の PasswordEncoder ID を表します。

Spring Security の OAuth2 クライアントのサポートの対応する構成は次のとおりです。

spring:
  security:
    oauth2:
      client:
        registration:
          client-a:
            provider: spring
            client-id: client-a
            client-secret: secret
            authorization-grant-type: authorization_code
            redirect-uri: "http://127.0.0.1:8080/authorized"
            scope: scope-a
        provider:
          spring:
            issuer-uri: http://localhost:9000

RegisteredClient には、一意のクライアント識別子に関連付けられたメタデータ (属性) があり、次のように定義されます。

public class RegisteredClient implements Serializable {
	private String id;  (1)
	private String clientId;    (2)
	private Instant clientIdIssuedAt;   (3)
	private String clientSecret;    (4)
	private Instant clientSecretExpiresAt;  (5)
	private String clientName;  (6)
	private Set<ClientAuthenticationMethod> clientAuthenticationMethods;    (7)
	private Set<AuthorizationGrantType> authorizationGrantTypes;    (8)
	private Set<String> redirectUris;   (9)
	private Set<String> postLogoutRedirectUris; (10)
	private Set<String> scopes; (11)
	private ClientSettings clientSettings;  (12)
	private TokenSettings tokenSettings;    (13)

	...

}
1idRegisteredClient を一意に識別する ID。
2clientId: クライアント識別子。
3clientIdIssuedAt: クライアント識別子が発行された時刻。
4clientSecret: クライアントのシークレット。値は、Spring Security の PasswordEncoder を使用してエンコードする必要があります。
5clientSecretExpiresAt: クライアントシークレットの有効期限が切れる時刻。
6clientName: クライアントに使用されるわかりやすい名前。この名前は、同意ページにクライアント名を表示する場合など、特定のシナリオで使用される場合があります。
7clientAuthenticationMethods: クライアントが使用できる認証方法。サポートされている値は、client_secret_basicclient_secret_postprivate_key_jwt [IETF] (英語) client_secret_jwtnone (パブリッククライアント) [IETF] (英語) です。
8authorizationGrantTypes: クライアントが使用できる認可付与型 [IETF] (英語) 。サポートされている値は authorization_codeclient_credentialsrefresh_tokenurn:ietf:params:oauth:grant-type:device_codeurn:ietf:params:oauth:grant-type:token-exchange です。
9redirectUris: クライアントがリダイレクトベースのフローで使用できる登録済みのリダイレクト URI [IETF] (英語) (authorization_code グラントなど)。
10postLogoutRedirectUris: クライアントがログアウトに使用できるログアウト後のリダイレクト URI。
11scopes: クライアントがリクエストできるスコープ。
12clientSettings: クライアントのカスタム設定 – たとえば、PKCE [IETF] (英語) を要求する、認可の同意を要求するなど。
13tokenSettings: クライアントに発行される OAuth2 トークンのカスタム設定 - たとえば、アクセス / リフレッシュトークンの有効期限、リフレッシュトークンの再利用など。

RegisteredClientRepository

RegisteredClientRepository は、新しいクライアントを登録したり、既存のクライアントを照会したりできる中心的なコンポーネントです。これは、クライアント認証、認可付与処理、トークンイントロスペクション、動的クライアント登録などの特定のプロトコルフローに従うときに、他のコンポーネントによって使用されます。

提供されている RegisteredClientRepository の実装は InMemoryRegisteredClientRepository と JdbcRegisteredClientRepository です。InMemoryRegisteredClientRepository 実装では RegisteredClient インスタンスがメモリ内に保存され、開発およびテスト中に ONLY を使用することが推奨されます。JdbcRegisteredClientRepository は、JdbcOperations を使用して RegisteredClient インスタンスを永続化する JDBC 実装です。

RegisteredClientRepository は REQUIRED コンポーネントです。

次の例は、RegisteredClientRepository@Bean を登録する方法を示しています。

@Bean
public RegisteredClientRepository registeredClientRepository() {
	List<RegisteredClient> registrations = ...
	return new InMemoryRegisteredClientRepository(registrations);
}

または、OAuth2AuthorizationServerConfigurer を介して RegisteredClientRepository を構成できます。

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);

	authorizationServerConfigurer
		.registeredClientRepository(registeredClientRepository);

	...

	return http.build();
}
OAuth2AuthorizationServerConfigurer は、複数の構成オプションを同時に適用する場合に便利です。

OAuth2Authorization

OAuth2Authorization は OAuth2 認可の表現であり、client_credentials 認可付与型の場合はリソース所有者またはそれ自体によってクライアントに付与された認可に関連する状態を保持します。

Spring Security の OAuth2 クライアントサポートで対応する認可モデルは OAuth2AuthorizedClient です。

認可付与フローが正常に完了すると、OAuth2Authorization が作成され、OAuth2AccessToken (Javadoc) 、(オプションの) OAuth2RefreshToken (Javadoc) 、および実行された認可付与型に固有の追加状態が関連付けられます。

OAuth2Authorization に関連付けられた OAuth2Token (Javadoc) インスタンスは、認可付与型によって異なります。

OAuth2 authorization_code grant [IETF] (英語) の場合、OAuth2AuthorizationCodeOAuth2AccessToken、(オプションの) OAuth2RefreshToken が関連付けられています。

OpenID Connect 1.0 authorization_code grant (英語) の場合、OAuth2AuthorizationCodeOidcIdToken (Javadoc) OAuth2AccessToken、(オプションの) OAuth2RefreshToken が関連付けられています。

OAuth2 client_credentials grant [IETF] (英語) の場合、OAuth2AccessToken のみが関連付けられます。

OAuth2Authorization とその属性は次のように定義されています。

public class OAuth2Authorization implements Serializable {
	private String id;  (1)
	private String registeredClientId;  (2)
	private String principalName;   (3)
	private AuthorizationGrantType authorizationGrantType;  (4)
	private Set<String> authorizedScopes;   (5)
	private Map<Class<? extends OAuth2Token>, Token<?>> tokens; (6)
	private Map<String, Object> attributes; (7)

	...

}
1idOAuth2Authorization を一意に識別する ID。
2registeredClientId: RegisteredClient を一意に識別する ID。
3principalName: リソース所有者 (またはクライアント) のプリンシパル名。
4authorizationGrantTypeAuthorizationGrantType を使用。
5authorizedScopes: クライアントに認可されたスコープの Set
6tokens: 実行された認可付与型に固有の OAuth2Token インスタンス (および関連するメタデータ)。
7attributes: 実行された認可付与型に固有の追加属性 – たとえば、認証された PrincipalOAuth2AuthorizationRequest など。

OAuth2Authorization とそれに関連付けられた OAuth2Token インスタンスには、設定された寿命があります。新しく発行された OAuth2Token はアクティブであり、有効期限が切れるか無効になる (取り消される) と非アクティブになります。関連するすべての OAuth2Token インスタンスが非アクティブの場合、OAuth2Authorization は (暗黙的に) 非アクティブです。各 OAuth2Token は、isExpired()isInvalidated()isActive() のアクセサーを提供する OAuth2Authorization.Token に保持されます。

OAuth2Authorization.Token は、OAuth2Token に関連付けられたクレーム (存在する場合) を返す getClaims() も提供します。

OAuth2AuthorizationService

OAuth2AuthorizationService は、新しい認可が格納され、既存の認可が照会される中心的なコンポーネントです。これは、特定のプロトコルフロー (クライアント認証、認可付与処理、トークンイントロスペクション、トークン取り消し、動的クライアント登録など) に従うときに、他のコンポーネントによって使用されます。

提供されている OAuth2AuthorizationService の実装は InMemoryOAuth2AuthorizationService と JdbcOAuth2AuthorizationService です。InMemoryOAuth2AuthorizationService 実装では OAuth2Authorization インスタンスがメモリ内に保存され、開発およびテスト中に ONLY を使用することが推奨されます。JdbcOAuth2AuthorizationService は、JdbcOperations を使用して OAuth2Authorization インスタンスを永続化する JDBC 実装です。

OAuth2AuthorizationService は OPTIONAL コンポーネントであり、デフォルトは InMemoryOAuth2AuthorizationService です。

次の例は、OAuth2AuthorizationService@Bean を登録する方法を示しています。

@Bean
public OAuth2AuthorizationService authorizationService() {
	return new InMemoryOAuth2AuthorizationService();
}

または、OAuth2AuthorizationServerConfigurer を介して OAuth2AuthorizationService を構成できます。

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);

	authorizationServerConfigurer
		.authorizationService(authorizationService);

	...

	return http.build();
}
OAuth2AuthorizationServerConfigurer は、複数の構成オプションを同時に適用する場合に便利です。

OAuth2AuthorizationConsent は、OAuth2 認可リクエストの流れ [IETF] (英語) からの認可「同意」(決定) の表現です。たとえば、リソース所有者によってクライアントに付与された権限を保持する authorization_code グラントです。

クライアントへのアクセスを認可する場合、リソース所有者は、クライアントがリクエストした権限のサブセットのみを付与できます。典型的な使用例は authorization_code 付与フローです。このフローでは、クライアントがスコープをリクエストし、リソース所有者がリクエストされたスコープへのアクセスを認可 (または拒否) します。

OAuth2 認可リクエストフローが完了すると、OAuth2AuthorizationConsent が作成 (または更新) され、付与された権限がクライアントおよびリソース所有者に関連付けられます。

OAuth2AuthorizationConsent とその属性は次のように定義されています。

public final class OAuth2AuthorizationConsent implements Serializable {
	private final String registeredClientId;    (1)
	private final String principalName; (2)
	private final Set<GrantedAuthority> authorities;    (3)

	...

}
1registeredClientId: RegisteredClient を一意に識別する ID。
2principalName: リソース所有者のプリンシパル名。
3authorities: リソース所有者によってクライアントに付与された権限。権限は、スコープ、クレーム、アクセス許可、ロールなどを表すことができます。

OAuth2AuthorizationConsentService は、新しい認可同意が格納され、既存の認可同意が照会される中心的なコンポーネントです。これは主に、OAuth2 認可リクエストフローを実装するコンポーネント (authorization_code 付与など) によって使用されます。

提供されている OAuth2AuthorizationConsentService の実装は InMemoryOAuth2AuthorizationConsentService と JdbcOAuth2AuthorizationConsentService です。InMemoryOAuth2AuthorizationConsentService 実装は OAuth2AuthorizationConsent インスタンスをメモリ内に格納し、開発とテストには ONLY をお勧めします。JdbcOAuth2AuthorizationConsentService は、JdbcOperations を使用して OAuth2AuthorizationConsent インスタンスを保持する JDBC 実装です。

OAuth2AuthorizationConsentService は OPTIONAL コンポーネントであり、デフォルトは InMemoryOAuth2AuthorizationConsentService です。

次の例は、OAuth2AuthorizationConsentService@Bean を登録する方法を示しています。

@Bean
public OAuth2AuthorizationConsentService authorizationConsentService() {
	return new InMemoryOAuth2AuthorizationConsentService();
}

または、OAuth2AuthorizationServerConfigurer を介して OAuth2AuthorizationConsentService を構成できます。

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);

	authorizationServerConfigurer
		.authorizationConsentService(authorizationConsentService);

	...

	return http.build();
}
OAuth2AuthorizationServerConfigurer は、複数の構成オプションを同時に適用する場合に便利です。

OAuth2TokenContext

OAuth2TokenContext は、OAuth2Token に関連付けられた情報を保持するコンテキストオブジェクトであり、OAuth2TokenGenerator および OAuth2TokenCustomizer によって使用されます。

OAuth2TokenContext は、次のアクセサーを提供します。

public interface OAuth2TokenContext extends Context {

	default RegisteredClient getRegisteredClient() ...  (1)

	default <T extends Authentication> T getPrincipal() ... (2)

	default AuthorizationServerContext getAuthorizationServerContext() ...    (3)

	@Nullable
	default OAuth2Authorization getAuthorization() ...  (4)

	default Set<String> getAuthorizedScopes() ...   (5)

	default OAuth2TokenType getTokenType() ...  (6)

	default AuthorizationGrantType getAuthorizationGrantType() ...  (7)

	default <T extends Authentication> T getAuthorizationGrant() ...    (8)

	...

}
1getRegisteredClient(): 認可付与に関連付けられた RegisteredClient
2getPrincipal(): リソース所有者 (またはクライアント) の Authentication インスタンス。
3getAuthorizationServerContext(): Authorization Server ランタイム環境の情報を保持する AuthorizationServerContext オブジェクト。
4getAuthorization(): 認可付与に関連付けられた OAuth2Authorization
5getAuthorizedScopes(): クライアントに対して承認されたスコープ。
6getTokenType(): 生成する OAuth2TokenType。サポートされている値は codeaccess_tokenrefresh_tokenid_token です。
7getAuthorizationGrantType(): 認可付与に関連付けられた AuthorizationGrantType
8getAuthorizationGrant(): 認可付与を処理する AuthenticationProvider によって使用される Authentication インスタンス。

OAuth2TokenGenerator

OAuth2TokenGenerator は、提供された OAuth2TokenContext に含まれる情報から OAuth2Token を生成する責任があります。

生成される OAuth2Token は、主に OAuth2TokenContext で指定された OAuth2TokenType の型に依存します。

例: OAuth2TokenType の value が次の場合:

  • code の場合、OAuth2AuthorizationCode が生成されます。

  • access_token の場合、OAuth2AccessToken が生成されます。

  • refresh_token の場合、OAuth2RefreshToken が生成されます。

  • id_token の場合、OidcIdToken が生成されます。

さらに、生成される OAuth2AccessToken の形式は、RegisteredClient 用に構成された TokenSettings.getAccessTokenFormat() によって異なります。フォーマットが OAuth2TokenFormat.SELF_CONTAINED (デフォルト) の場合、Jwt が生成されます。フォーマットが OAuth2TokenFormat.REFERENCE の場合、「不透明な」トークンが生成されます。

最後に、生成された OAuth2Token に一連のクレームがあり、ClaimAccessor を実装している場合、クレームは OAuth2Authorization.Token.getClaims() からアクセスできるようになります。

OAuth2TokenGenerator は主に、認可付与処理を実装するコンポーネント ( authorization_codeclient_credentialsrefresh_token など) によって使用されます。

提供される実装は OAuth2AccessTokenGeneratorOAuth2RefreshTokenGeneratorJwtGenerator です。OAuth2AccessTokenGenerator は「不透明な」(OAuth2TokenFormat.REFERENCE) アクセストークンを生成し、JwtGenerator は Jwt (OAuth2TokenFormat.SELF_CONTAINED) を生成します。

OAuth2TokenGenerator は OPTIONAL コンポーネントであり、デフォルトは OAuth2AccessTokenGenerator と OAuth2RefreshTokenGenerator で構成される DelegatingOAuth2TokenGenerator です。
JwtEncoder@Bean または JWKSource<SecurityContext>@Bean が登録されている場合、JwtGenerator が DelegatingOAuth2TokenGenerator に追加で構成されます。

OAuth2TokenGenerator は、access_token および refresh_token の任意のカスタムトークン形式をサポートできるため、優れた柔軟性を提供します。

次の例は、OAuth2TokenGenerator@Bean を登録する方法を示しています。

@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
	JwtEncoder jwtEncoder = ...
	JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
	OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
	OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
	return new DelegatingOAuth2TokenGenerator(
			jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}

または、OAuth2AuthorizationServerConfigurer を介して OAuth2TokenGenerator を構成できます。

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);

	authorizationServerConfigurer
		.tokenGenerator(tokenGenerator);

	...

	return http.build();
}
OAuth2AuthorizationServerConfigurer は、複数の構成オプションを同時に適用する場合に便利です。

OAuth2TokenCustomizer

OAuth2TokenCustomizer は、提供された OAuth2TokenContext でアクセス可能な OAuth2Token の属性をカスタマイズする機能を提供します。これは、OAuth2TokenGenerator が生成前に OAuth2Token の属性をカスタマイズできるようにするために使用されます。

ジェネリクス型の OAuth2TokenClaimsContext (implements OAuth2TokenContext) で宣言された OAuth2TokenCustomizer<OAuth2TokenClaimsContext> は、「不透明な」 OAuth2AccessToken のクレームをカスタマイズする機能を提供します。OAuth2TokenClaimsContext.getClaims() は OAuth2TokenClaimsSet.Builder へのアクセスを提供し、クレームを追加、置換、削除する機能を許可します。

次の例は、OAuth2TokenCustomizer<OAuth2TokenClaimsContext> を実装し、それを OAuth2AccessTokenGenerator で構成する方法を示しています。

@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
	JwtEncoder jwtEncoder = ...
	JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
	OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
	accessTokenGenerator.setAccessTokenCustomizer(accessTokenCustomizer());
	OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
	return new DelegatingOAuth2TokenGenerator(
			jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}

@Bean
public OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer() {
	return context -> {
		OAuth2TokenClaimsSet.Builder claims = context.getClaims();
		// Customize claims

	};
}
OAuth2TokenGenerator が @Bean として提供されていないか、OAuth2AuthorizationServerConfigurer を介して構成されていない場合、OAuth2TokenCustomizer<OAuth2TokenClaimsContext>@Bean は OAuth2AccessTokenGenerator で自動的に構成されます。

ジェネリクス型の JwtEncodingContext (implements OAuth2TokenContext) で宣言された OAuth2TokenCustomizer<JwtEncodingContext> は、Jwt のヘッダーとクレームをカスタマイズする機能を提供します。JwtEncodingContext.getJwsHeader() は JwsHeader.Builder へのアクセスを提供し、ヘッダーを追加、置換、削除する機能を許可します。JwtEncodingContext.getClaims() は JwtClaimsSet.Builder へのアクセスを提供し、クレームを追加、置換、削除する機能を許可します。

次の例は、OAuth2TokenCustomizer<JwtEncodingContext> を実装し、それを JwtGenerator で構成する方法を示しています。

@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
	JwtEncoder jwtEncoder = ...
	JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
	jwtGenerator.setJwtCustomizer(jwtCustomizer());
	OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
	OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
	return new DelegatingOAuth2TokenGenerator(
			jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}

@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
	return context -> {
		JwsHeader.Builder headers = context.getJwsHeader();
		JwtClaimsSet.Builder claims = context.getClaims();
		if (context.getTokenType().equals(OAuth2TokenType.ACCESS_TOKEN)) {
			// Customize headers/claims for access_token

		} else if (context.getTokenType().getValue().equals(OidcParameterNames.ID_TOKEN)) {
			// Customize headers/claims for id_token

		}
	};
}
OAuth2TokenGenerator が @Bean として提供されていないか、OAuth2AuthorizationServerConfigurer を介して構成されていない場合、OAuth2TokenCustomizer<JwtEncodingContext>@Bean は JwtGenerator で自動的に構成されます。

SessionRegistry

OpenID Connect 1.0 が有効な場合、認証されたセッションを追跡するために SessionRegistry インスタンスが使用されます。SessionRegistry は、新しい認証済みセッションを登録するために、OAuth2 認証エンドポイントに関連付けられた SessionAuthenticationStrategy のデフォルト実装によって使用されます。

SessionRegistry@Bean が登録されていない場合は、デフォルトの実装 SessionRegistryImpl が使用されます。
SessionRegistry@Bean が登録されており、SessionRegistryImpl のインスタンスである場合、HttpSessionEventPublisher@Bean SHOULD も登録されます。これは、SessionRegistryImpl にセッションライフサイクルイベント (たとえば、SessionDestroyedEvent) を通知して、SessionInformation インスタンスを削除する機能を提供するロールを担うためです。

エンドユーザーによってログアウトがリクエストされると、OpenID Connect 1.0 ログアウトエンドポイントは SessionRegistry を使用して、認証されたエンドユーザーに関連付けられた SessionInformation を検索し、ログアウトを実行します。

Spring Security の同時セッション制御機能が使用されている場合、SessionRegistry@Bean を登録して、Spring Security の同時セッション制御と Spring Authorization Server のログアウト機能の間で確実に共有されるようにするのは RECOMMENDED です。

次の例は、SessionRegistry@BeanHttpSessionEventPublisher@Bean ( SessionRegistryImpl で必要) を登録する方法を示しています。

@Bean
public SessionRegistry sessionRegistry() {
	return new SessionRegistryImpl();
}

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
	return new HttpSessionEventPublisher();
}