Spring Security OAuth2による簡単なシングルサインオン

Spring Security OAuth2を使用したシンプルなシングルサインオン

1. 概要

このチュートリアルでは、Spring SecurityOAuthとSpringBootを使用してSSO(シングルサインオン)を実装する方法について説明します。

3つの別々のアプリケーションを使用します。

  • 承認サーバー-中央認証メカニズム

  • 2つのクライアントアプリケーション:SSOを使用するアプリケーション

非常に簡単に言えば、ユーザーがクライアントアプリで保護されたページにアクセスしようとすると、認証サーバーを介して最初に認証するようにリダイレクトされます。

そして、OAuth2からAuthorization Code付与タイプを使用して、認証の委任を駆動します。

参考文献:

Spring Security 5 – OAuth2ログイン

Spring Security 5のOAuth2を使用して、Facebook、Google、またはその他の資格情報でユーザーを認証する方法を学びます。

Spring Security OAuth2の新機能–クレームの検証

Spring Security OAuthの新しいクレーム検証サポートの簡単で実用的な紹介。

Spring SocialでのセカンダリFacebookログイン

Facebookによる認証を標準のフォームログインSpringアプリの横に実装する方法の概要。

 

始める前に-1つの重要な注意事項。 the Spring Security core team is in the process of implementing a new OAuth2 stack –いくつかの側面はすでに出ており、いくつかはまだ進行中であることに注意してください。

これは、その取り組みに関するコンテキストを提供する簡単なビデオです。

 

さて、すぐに飛び込みましょう。

2. クライアントアプリ

クライアントアプリケーションから始めましょう。もちろん、SpringBootを使用して構成を最小限に抑えます。

2.1. Mavenの依存関係

まず、pom.xmlに次の依存関係が必要になります。


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.boot
    spring-boot-starter-security


    org.springframework.security.oauth.boot
    spring-security-oauth2-autoconfigure
    2.0.1.RELEASE


    org.springframework.boot
    spring-boot-starter-thymeleaf


    org.thymeleaf.extras
    thymeleaf-extras-springsecurity4

2.2. セキュリティ構成

次に、最も重要な部分であるクライアントアプリケーションのセキュリティ構成:

@Configuration
@EnableOAuth2Sso
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
          .authorizeRequests()
          .antMatchers("/", "/login**")
          .permitAll()
          .anyRequest()
          .authenticated();
    }
}

もちろん、この構成の中核部分は、シングルサインオンを有効にするために使用している@EnableOAuth2Ssoアノテーションです。

WebSecurityConfigurerAdapterを拡張する必要があることに注意してください。拡張しないと、すべてのパスが保護されるため、ユーザーが任意のページにアクセスしようとすると、ログインにリダイレクトされます。 ここでのケースでは、インデックスページとログインページのみが、認証なしでアクセスできるページです。

最後に、リクエストスコープを処理するためのRequestContextListenerBeanも定義しました。

そしてapplication.yml

server:
    port: 8082
    servlet:
        context-path: /ui
    session:
      cookie:
        name: UISESSION
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId
      clientSecret: secret
      accessTokenUri: http://localhost:8081/auth/oauth/token
      userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8081/auth/user/me
spring:
  thymeleaf:
    cache: false

いくつかの簡単なメモ:

  • デフォルトの基本認証を無効にしました

  • accessTokenUriは、アクセストークンを取得するためのURIです。

  • userAuthorizationUriは、ユーザーがリダイレクトされる認証URIです。

  • userInfoUri現在のユーザーの詳細を取得するためのユーザーエンドポイントのURI

また、ここの例では、承認サーバーを展開しましたが、もちろん、FacebookやGitHubなどの他のサードパーティプロバイダーを使用することもできます。

2.3. フロントエンド

それでは、クライアントアプリケーションのフロントエンド構成を見てみましょう。 主にalready covered in on the siteであるため、ここではこれに焦点を当てません。

ここでのクライアントアプリケーションには、非常にシンプルなフロントエンドがあります。これがindex.htmlです:

Spring Security SSO

Login

そしてsecuredPage.html

Secured Page

Welcome, Name

securedPage.htmlページでは、ユーザーを認証する必要がありました。 認証されていないユーザーがsecuredPage.htmlにアクセスしようとすると、最初にログインページにリダイレクトされます。

3. 認証サーバー

ここで、承認サーバーについて説明しましょう。

3.1. Mavenの依存関係

まず、pom.xmlで依存関係を定義する必要があります。


    org.springframework.boot
    spring-boot-starter-web


    org.springframework.security.oauth
    spring-security-oauth2
    2.3.3.RELEASE

3.2. OAuth構成

ここでは、承認サーバーとリソースサーバーを単一のデプロイ可能なユニットとして一緒に実行することを理解することが重要です。

リソースサーバーの構成から始めましょう。これは、プライマリブートアプリケーションを兼ねています。

@SpringBootApplication
@EnableResourceServer
public class AuthorizationServerApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(AuthorizationServerApplication.class, args);
    }
}

次に、承認サーバーを構成します。

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public void configure(
      AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()")
          .checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
          .withClient("SampleClientId")
          .secret(passwordEncoder.encode("secret"))
          .authorizedGrantTypes("authorization_code")
          .scopes("user_info")
          .autoApprove(true)
          .redirectUris(
            "http://localhost:8082/ui/login","http://localhost:8083/ui2/login");
    }
}

authorization_code付与タイプを使用して単純なクライアントのみを有効にしていることに注意してください。

また、autoApproveがtrueに設定されているため、スコープが手動で承認されるようにリダイレクトおよび昇格されないことに注意してください。

3.3. セキュリティ構成

まず、application.propertiesを使用して、デフォルトの基本認証を無効にします。

server.port=8081
server.servlet.context-path=/auth

それでは、構成に移り、簡単なフォームログインメカニズムを定義しましょう。

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.requestMatchers()
          .antMatchers("/login", "/oauth/authorize")
          .and()
          .authorizeRequests()
          .anyRequest().authenticated()
          .and()
          .formLogin().permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("john")
            .password(passwordEncoder().encode("123"))
            .roles("USER");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

単純なメモリ内認証を使用しましたが、カスタムuserDetailsServiceに置き換えるだけでよいことに注意してください。

3.4. ユーザーエンドポイント

最後に、構成で以前に使用したユーザーエンドポイントを作成します。

@RestController
public class UserController {
    @GetMapping("/user/me")
    public Principal user(Principal principal) {
        return principal;
    }
}

当然、これはJSON表現でユーザーデータを返します。

4. 結論

このクイックチュートリアルでは、Spring Security Oauth2とSpring Bootを使用したシングルサインオンの実装に焦点を当てました。

いつものように、完全なソースコードはover on GitHubで見つけることができます。