1. 概要

Spring Securityは、5.1.x GA以降、WebFluxのOAuthサポートを追加しました。

OAuth2ログインサポートを使用するようにWebFluxアプリケーションを構成する方法について説明します。 また、WebClientを使用してOAuth2で保護されたリソースにアクセスする方法についても説明します。

WebfluxのOAuthログイン構成は、標準のWebMVCアプリケーションの構成と似ています。 詳細については、SpringOAuth2Login要素に関する記事もご覧ください。

2. Maven構成

まず、単純なSpring Bootアプリケーションを作成し、これらの依存関係をpom.xmlに追加します。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>

spring-boot-starter-security spring-boot-starter-webflux 、およびspring-security-oauth2-clientの依存関係はMavenCentralで利用できます。

3. メインコントローラー

次に、ホームページにユーザー名を表示するための簡単なコントローラーを追加します。

@RestController
public class MainController {
    
    @GetMapping("/")
    public Mono<String> index(@AuthenticationPrincipal Mono<OAuth2User> oauth2User) {
       return oauth2User
        .map(OAuth2User::getName)
        .map(name -> String.format("Hi, %s", name));
    }
}

OAuth2クライアントのUserInfoエンドポイントから取得したユーザー名を表示することに注意してください。

4. Googleを使用してログインする

次に、Googleを使用したログインをサポートするようにアプリケーションを構成します。

まず、 Google DeveloperConsoleで新しいプロジェクトを作成する必要があります

次に、OAuth2資格情報を追加する必要があります([資格情報の作成]> [OAuthクライアントID])。

次に、これを「承認されたリダイレクトURI」に追加します。

http://localhost:8080/login/oauth2/code/google

次に、クライアントIDとシークレットを使用するようにapplication.ymlを構成する必要があります。

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: YOUR_APP_CLIENT_ID
            client-secret: YOUR_APP_CLIENT_SECRET

パスにspring-security-oauth2-clientがあるため、アプリケーションは保護されます。

ユーザーは、当社のホームページにアクセスする前に、Googleを使用してログインするようにリダイレクトされます。

5. 認証プロバイダーを使用してログインする

カスタム認証サーバーからログインするようにアプリケーションを構成することもできます。

次の例では、前の記事の認証サーバーを使用します。

今回は、ClientIDとClient Secretだけでなく、さらに多くのプロパティを構成する必要があります。

spring:
  security:
    oauth2:
      client:
        registration:
          custom:
            client-id: fooClientIdPassword
            client-secret: secret
            scopes: read,foo
            authorization-grant-type: authorization_code
            redirect-uri-template: http://localhost:8080/login/oauth2/code/custom
        provider:
          custom:
            authorization-uri: http://localhost:8081/spring-security-oauth-server/oauth/authorize
            token-uri: http://localhost:8081/spring-security-oauth-server/oauth/token
            user-info-uri: http://localhost:8088/spring-security-oauth-resource/users/extra
            user-name-attribute: user_name

この場合、OAuth2クライアントのスコープ、 付与タイプ、およびリダイレクトURIも指定する必要があります。 また、承認サーバーの承認およびトークンURIも提供します。

最後に、 UserInfo エンドポイントも構成して、ユーザー認証の詳細を取得できるようにする必要があります。

6. セキュリティ構成

デフォルトでは、SpringSecurityはすべてのパスを保護します。 したがって、OAuthクライアントが1つしかない場合は、このクライアントを承認してログインするようにリダイレクトされます。

複数のOAuthクライアントが登録されている場合は、ログイン方法を選択するためのログインページが自動的に作成されます。

必要に応じて変更でき、詳細なセキュリティ構成を提供します。

@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public SecurityWebFilterChain configure(ServerHttpSecurity http) throws Exception {
        return http.authorizeExchange()
          .pathMatchers("/about").permitAll()
          .anyExchange().authenticated()
          .and().oauth2Login()
          .and().build();
    }
}

この例では、「/about」を除くすべてのパスを保護しています。

7. WebClient

OAuth2を使用してユーザーを認証するだけではありません。 WebClientを使用して、OAuth2AuthorizedClientを使用してOAuth2で保護されたリソースにアクセスできます。

それでは、WebClientを構成しましょう。

@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrationRepo, 
  ServerOAuth2AuthorizedClientRepository authorizedClientRepo) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction filter = 
      new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepo, authorizedClientRepo);
    
    return WebClient.builder().filter(filter).build();
}

次に、OAuth2で保護されたリソースを取得できます。

@Autowired
private WebClient webClient;

@GetMapping("/foos/{id}")
public Mono<Foo> getFooResource(@RegisteredOAuth2AuthorizedClient("custom") 
  OAuth2AuthorizedClient client, @PathVariable final long id){
    return webClient
      .get()
      .uri("http://localhost:8088/spring-security-oauth-resource/foos/{id}", id)
      .attributes(oauth2AuthorizedClient(client))
      .retrieve()
      .bodyToMono(Foo.class); 
}

OAuth2AuthorizedClient。からAccessTokenを使用してリモートリソースFooを取得したことに注意してください。

8. 結論

このクイック記事では、OAuth2ログインサポートを使用するようにWebFluxアプリケーションを構成する方法と、WebClientを使用してOAuth2で保護されたリソースにアクセスする方法を学びました。

いつものように、完全なソースコードはGitHubから入手できます。