JWTでの自前認証を実装した次のステップとして、外部のGoogleアカウントでログインできるようにしたいですよね。Spring Security OAuth2 Clientを使えば、驚くほど少ないコードでGoogleソーシャルログインが実現できます。
この記事では、Google Cloud ConsoleでのOAuth2クライアント作成から、application.ymlの設定、SecurityFilterChainの構成、ユーザー情報の取得まで、ローカル環境で動かしながら解説します。
OAuth2認可コードフローの全体像
実装に入る前に、認可コードフローの流れを把握しておきましょう。
1. ブラウザ → Spring Boot: /oauth2/authorization/google にアクセス
2. Spring Boot → ブラウザ: Googleの認可エンドポイントへリダイレクト
3. ブラウザ → Google: ユーザーがログインして権限を許可
4. Google → Spring Boot: 認可コード(code)をリダイレクトURIに返す
5. Spring Boot → Google: code をアクセストークンに交換(バックチャンネル)
6. Spring Boot → Google: UserInfoエンドポイントでユーザー情報を取得
7. Spring Boot: セッションにユーザー情報を保存してログイン完了
JWTの自前発行と大きく違うのは、 ステップ5〜7をSpring Securityがほぼ自動で処理してくれる 点です。自分でトークン交換のリクエストを書く必要はありません。
Google Cloud ConsoleでOAuth2クライアントを作成する
まず client-id と client-secret を取得します。
- Google Cloud Console でプロジェクトを作成
- 「APIとサービス」→「OAuth同意画面」を設定(テスト用途なら「外部」でOK)
- 「認証情報」→「OAuthクライアントID」を作成
- アプリケーションの種類は「ウェブアプリケーション」を選択
- 承認済みリダイレクトURIに
http://localhost:8080/login/oauth2/code/googleを追加
- 表示された
client-idとclient-secretをメモ
リダイレクトURIのパス /login/oauth2/code/google はSpring Security OAuth2 Clientのデフォルト値です。最初はこのまま使うのが楽です。
プロジェクトのセットアップ
spring-boot-starter-oauth2-client を依存関係に追加します。
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
}
このスターターには spring-security-oauth2-client と spring-security-oauth2-jose(IDトークン検証用)が含まれています。
application.ymlにOAuth2設定を記述する
application.yml に以下を追加します。
spring:
security:
oauth2:
client:
registration:
google:
client-id: ${GOOGLE_CLIENT_ID}
client-secret: ${GOOGLE_CLIENT_SECRET}
scope:
- openid
- email
- profile
scope に openid を含めることで、レスポンスが OidcUser として扱われ、メールアドレスや名前を簡単に取り出せます。provider の定義は不要です。Spring BootがGoogleの認証エンドポイントを自動で解決してくれます。
client-id と client-secret は必ず環境変数にしましょう。ソースコードに直書きしてGitにプッシュしてしまう事故が起きやすいので要注意です。
SecurityFilterChainでoauth2Login()を有効化する
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/login").permitAll()
.anyRequest().authenticated()
)
.oauth2Login(oauth2 -> oauth2
.defaultSuccessUrl("/dashboard", true)
);
return http.build();
}
}
oauth2Login() を呼ぶだけでGoogleログインが有効になります。defaultSuccessUrl でログイン後のリダイレクト先を指定できます。
CSRFはデフォルトで有効のままにしておきましょう。OAuth2フローにはstateパラメータによるCSRF対策が組み込まれており、Spring Securityが自動で処理してくれます。
ログイン後のユーザー情報を取得する
コントローラーで @AuthenticationPrincipal を使ってユーザー情報を受け取ります。
@RestController
public class UserController {
@GetMapping("/dashboard")
public Map<String, Object> dashboard(@AuthenticationPrincipal OidcUser user) {
return Map.of(
"name", user.getAttribute("name"),
"email", user.getAttribute("email"),
"picture", user.getAttribute("picture")
);
}
}
openid スコープを含めているので OidcUser としてキャストできます。openid を外した場合は OAuth2User になります。サービス層など @AuthenticationPrincipal が使えない場所では SecurityContextHolder.getContext().getAuthentication() から取得できます。
ログイン成功後の処理をカスタマイズする
初回ログイン時にユーザー情報をDBに保存したいケースは多いですよね。その場合は AuthenticationSuccessHandler を実装します。
@Component
public class OAuth2LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final UserService userService;
public OAuth2LoginSuccessHandler(UserService userService) {
super("/dashboard");
this.userService = userService;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
OidcUser oidcUser = (OidcUser) authentication.getPrincipal();
userService.saveOrUpdate(oidcUser.getEmail(), oidcUser.getAttribute("name"));
super.onAuthenticationSuccess(request, response, authentication);
}
}
SecurityConfig 側では .oauth2Login(oauth2 -> oauth2.successHandler(successHandler)) で登録します。
セッションベース認証とJWTとの違い
今回の実装は セッションベース です。Spring Security OAuth2 ClientはデフォルトでOAuth2AuthorizedClientをHttpSessionに保存します。
複数サーバーにスケールアウトする場合はセッション共有(Redisなど)が必要になります。StatelessなAPIにしたい場合は、認可コードフロー完了後に自前のJWTを発行するアーキテクチャが一般的です。そちらは Spring Security + JWTでステートレス認証を実装する方法 を参照してください。
動作確認
アプリを起動して http://localhost:8080 にアクセスすると、Spring Securityのデフォルトログインページが表示されます。「Sign in with Google」リンクをクリックするとGoogleの認証画面に遷移し、ログイン後に /dashboard に戻ってきます。
redirect_uri_mismatch が出た場合は、Google Cloud ConsoleのリダイレクトURIが http://localhost:8080/login/oauth2/code/google になっているか確認しましょう。403エラーが出る場合は SecurityFilterChain の permitAll() 設定を見直してみてください。
他プロバイダへの対応も簡単です。registration に github キーを追加するだけで動きます。Spring BootはGitHub・Facebook・Oktaなどをデフォルトでサポートしています。
まとめ
Spring Security OAuth2 Clientを使ったGoogleログインは、依存追加と application.yml の設定、oauth2Login() の一行でほぼ動きます。フローの複雑さと比べると、コード量の少なさが際立ちますよね。
Basic認証やJWTとの比較は Spring BootでBasic認証を実装する方法 や JWTでステートレス認証を実装する方法 も合わせて読んでみてください。フロントエンドと組み合わせる際は Spring BootのCORS設定ガイド も参考になります。