KeycloakをIdPにしてSpring Security OAuth 2.0 Login/Client を試してみる
   5 min read

はじめに

Spring Boot で Spring Security OAuth 2.0 Login / Client を利用する手順をまとめます。

また、認可サーバ(IdP)にはローカルで立てたKeycloakを用いますのでそちらのセットアップ手順も記載します。

補足事項: Keycloakは クライアントライブラリも提供しており(Spring系のもので言うと、Spring Securityを利用しないもの、Spring Securityを利用するもの、の2種があるようです。詳細は 実装サンプルにあります)、Keycloakを利用するのであればそちらを使うのが良さそうです。 ただし、今回は、最終的にKeycloakをIdPとして使うわけではなく、仮に利用しているだけなので、それらは用いず、Spring Securityの汎用機能 Spring Security OAuth 2.0 Client を利用します。

Keycloakセットアップ

ダウンロードと展開

https://www.keycloak.org/downloads からスタンドアロンサーバをダウンロードして展開します(これはWildFlyベースのサーバのようです)。本エントリ記載時点では https://downloads.jboss.org/keycloak/10.0.2/keycloak-10.0.2.tar.gz です。

Keycloak起動

続いて、Keycloakを起動します(この起動方法がまさにWildFlyですね)。

./bin/standalone.sh -Djboss.socket.binding.port-offset=1

admin ユーザ作成

adminユーザ未作成状態で http://localhost:8081/auth/ へアクセスすると、adminユーザのユーザ名とパスワード入力を促されます。

ここではユーザ名、パスワードとも admin とすることにします。

Username

admin

Password

admin

Create ボタンを押すと上記で入力したadminユーザが作成されます。

Administration Console リンクを押して次の画面に進みます。

realm作成

Administration Console を開くと、左上に "Master" というプルダウンメニューのようなものがあると思います。

ここにマウスカーソルを合わせると "Add realm" というボタンが表れるのでそれを押します。そうすると http://localhost:8081/auth/admin/master/console/#/create/realm へ遷移します。

Nameに myrealm と入力kし、 Create ボタンを押します。

Name

myrealm

作成が完了すると Administration Console 画面に戻ります。 このとき、左上のrealm名画先ほど作成した "Myrealm" になっていると思います。

続いてこの画面からユーザを作成します。

ユーザ作成

画面左のメニュー Users を選択し、 "Add user" ボタンを押します。

Usernameに myuser を、それ以外の項目も適当に埋め "Save" ボタンを押します。

Username

myuser

Email

myuser@example.com

First Name

my-firstname

Last Name

my-lastname

ユーザ作成が完了したら、続いてパスワード設定を行います。 画面上部の "Credentials" タブをクリックして開き、パスワードを設定します。ここではユーザ名と同じ myuser としました。 また、"Temporary"を OFF にしておきます(ONだと初回ログイン時パスワード変更を求められます)。

Password

myuser

Password Confirmation

myuser

Temporary

OFF

そして、 "Set Password" ボタンを押しパスワード設定完了です。

クライアント登録

ここでいう "クライアント" というのはOAuth2.0でいうところの認可クライアント、OIDCでいうところのRPです。

画面左のメニュー Clients をクリックします。

続いて画面右の Createボタンを押します。

この画面で次のように入力して、 "Save" ボタンを押します。

Client ID

myclient

Client Protocol

openid-connect (デフォルトのまま)

Root URL

(空のままでOK)

クライアント作成が完了したら続いてこのクライアント設定画面で 次の通り設定変更し "Save" ボタンを押します。

( myspring というのは、後でSpring Bootに設定する registration-id です。詳細は Spring Security リファレンスを "/login/oauth2/code" で検索してみてください)

Access Type

confidential

Valid Redirect URL

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

上記の通り Access Type を confidential に設定すると、この画面上部に "Credentials" タブが表示されます。 このタブで client-secret を確認できます。

これで認可サーバであるKeycloak側の設定は終了です。

続いて、この認可サーバを利用するクライアントをSpring Bootで作っていきます。

クライアント(Spring Boot)設定

コードはこちらになります。

はじめに、で記載した通り、 Spring Securityの機能を利用します。

Spring Boot では、 https://start.spring.io/ で "OAuth 2.0 Client" を選ぶことで追加される spring-boot-starter-oauth2-client を用いることになります。

余談ですが(&結構何回も書いてきていますが)、 spring-security-auth2 と、今回利用する spring-security-oauth2-client は名前が似ているだけで別系統のライブラリです(そして前者はdeprecatedです)。

spring-boot-starter-oauth2-client 依存関係追加

Spring Boot で auto-configuration を効かせてOAuth 2.0 Login/Clientを利用するには spring-boot-starter-oauth2-client を用います。

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

security config 設定

Spring Security OAuth 2.0 Client の auto-configuration で記載した通り、 OAuth2WebSecurityConfiguration で次のような自動設定が為されていますので、 特に何も行う必要はありません

class OAuth2WebSecurityConfiguration {

	@Bean
	@ConditionalOnMissingBean
	OAuth2AuthorizedClientService authorizedClientService(ClientRegistrationRepository clientRegistrationRepository) {
		return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
	}

	@Bean
	@ConditionalOnMissingBean
	OAuth2AuthorizedClientRepository authorizedClientRepository(OAuth2AuthorizedClientService authorizedClientService) {
		return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class)
	static class OAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

		@Override
		protected void configure(HttpSecurity http) throws Exception {
			http.authorizeRequests((requests) -> requests.anyRequest().authenticated());
			http.oauth2Login(Customizer.withDefaults());
			http.oauth2Client();
		}

	}

}

プロパティ

spring:
  security:
    oauth2:
      client:
        provider:
          mykeycloak:
            # https://www.keycloak.org/docs/latest/securing_apps/index.html#endpoints-2
            # http://localhost:8081/auth/realms/myrealm/.well-known/openid-configuration
            issuer-uri: http://localhost:8081/auth/realms/myrealm
            # https://www.keycloak.org/docs/11.0/securing_apps/index.html
            user-name-attribute: preferred_username
        registration:
          myspring:
            authorization-grant-type: authorization_code
            # 上で定義しているprovider名
            provider: mykeycloak
            # keycloakに登録したidと対応するsecret
            # http://localhost:8081/auth/admin/master/console/#/realms/myrealm/clients
            client-id: myclient
            client-secret: e3b8886b-5b6e-49a7-91c2-c28caadf0a2b
  • client-secret は、実際にはKeycloakの設定画面で表示されているもので差し替える必要があります。

  • いくつかのサンプルと見ているとエンドポイント(authorization-uri など)をそれぞれ設定していましたが、 issuer-uri だけ設定すれば後はそこから自動設定できるようです。

  • user-name-attribute は、リファレンスの "principal-attibute" からそれっぽいものを選びました。

コントローラを作成してアクセスしてみる

適当にコントローラを作成して http://localhost:8080/ へアクセスしてみます。

Keycloakのログイン画面へリダイレクトされるので、事前に作成したユーザのid, password(myuser, myuser)を入力すれば、コントローラが結果を返してくれます。