OAuth 2.0 リソースサーバーマルチテナンシー
マルチテナンシー
リソースサーバーは、何らかのテナント ID をキーとするベアラートークンを検証するための複数の戦略がある場合、マルチテナントと見なされます。
例: リソースサーバーは、2 つの異なる認可サーバーからベアラートークンを受け入れることができます。または、認可サーバーが複数の発行者を表すこともできます。
いずれの場合も、2 つのことを行う必要があり、トレードオフはそれらの実行方法に関連しています。
テナントを解決します。
テナントを伝播します。
クレームによるテナントの解決
テナントを区別する 1 つの方法は、発行者の主張によるものです。発行者の主張は署名された JWT に付随するため、JwtIssuerReactiveAuthenticationManagerResolver
を使用してこれを行うことができます。
Java
Kotlin
JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver = JwtIssuerReactiveAuthenticationManagerResolver
.fromTrustedIssuers("https://idp.example.org/issuerOne", "https://idp.example.org/issuerTwo");
http
.authorizeExchange(exchanges -> exchanges
.anyExchange().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.authenticationManagerResolver(authenticationManagerResolver)
);
val customAuthenticationManagerResolver = JwtIssuerReactiveAuthenticationManagerResolver
.fromTrustedIssuers("https://idp.example.org/issuerOne", "https://idp.example.org/issuerTwo")
return http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2ResourceServer {
authenticationManagerResolver = customAuthenticationManagerResolver
}
}
発行者エンドポイントが遅延ロードされるため、これは素晴らしいことです。実際、対応する JwtReactiveAuthenticationManager
は、対応する発行者との最初のリクエストが送信されたときにのみインスタンス化されます。これにより、アプリケーションが起動し、使用可能になっている認可サーバーとは無関係に起動できるようになります。
ダイナミックテナント
新しいテナントが追加されるたびにアプリケーションを再起動したくない場合があります。この場合、ReactiveAuthenticationManager
インスタンスのリポジトリを使用して JwtIssuerReactiveAuthenticationManagerResolver
を構成できます。これは、実行時に編集できます。
Java
Kotlin
private Mono<ReactiveAuthenticationManager> addManager(
Map<String, ReactiveAuthenticationManager> authenticationManagers, String issuer) {
return Mono.fromCallable(() -> ReactiveJwtDecoders.fromIssuerLocation(issuer))
.subscribeOn(Schedulers.boundedElastic())
.map(JwtReactiveAuthenticationManager::new)
.doOnNext(authenticationManager -> authenticationManagers.put(issuer, authenticationManager));
}
// ...
JwtIssuerReactiveAuthenticationManagerResolver authenticationManagerResolver =
new JwtIssuerReactiveAuthenticationManagerResolver(authenticationManagers::get);
http
.authorizeExchange(exchanges -> exchanges
.anyExchange().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2
.authenticationManagerResolver(authenticationManagerResolver)
);
private fun addManager(
authenticationManagers: MutableMap<String, ReactiveAuthenticationManager>, issuer: String): Mono<JwtReactiveAuthenticationManager> {
return Mono.fromCallable { ReactiveJwtDecoders.fromIssuerLocation(issuer) }
.subscribeOn(Schedulers.boundedElastic())
.map { jwtDecoder: ReactiveJwtDecoder -> JwtReactiveAuthenticationManager(jwtDecoder) }
.doOnNext { authenticationManager: JwtReactiveAuthenticationManager -> authenticationManagers[issuer] = authenticationManager }
}
// ...
var customAuthenticationManagerResolver = JwtIssuerReactiveAuthenticationManagerResolver(authenticationManagers::get)
return http {
authorizeExchange {
authorize(anyExchange, authenticated)
}
oauth2ResourceServer {
authenticationManagerResolver = customAuthenticationManagerResolver
}
}
この場合、発行者に与えられた ReactiveAuthenticationManager
を取得するための戦略を使用して JwtIssuerReactiveAuthenticationManagerResolver
を構築します。このアプローチにより、実行時にリポジトリ(前のスニペットでは Map
として示されている)に要素を追加および削除できます。
単に発行者を取得して、そこから |