Google Login Urlを作る方法
前提
有名な Social Login Provider は Spring によって管理されているため元々は Login URL を作るとかの作業はいらないです。
ですが、今回作るアプリケーションではフロントエンドでは client_id
も client_secret
も何も管理していなく全部バックエンドで管理しています。
要件
- ユーザが
/a
,/abc
どちらにいてもログインボタンを押してログインモーダルが表示されてログインしたら、その後、元のページに戻る必要があります。 - 全てバックエンドで制御していますので
redirect
で元のページに戻す必要があります。
実装
フロントエンドから currentUr を貰って state にセットします。
package jp.co.kopher.backendkotlin.controller
import jakarta.servlet.http.HttpServletRequest
import jp.co.kopher.backendkotlin.response.AuthLoginResponse
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/v1")
class OAuth2Controller(
private val clientRegistrationRepository: ClientRegistrationRepository,
) {
@GetMapping("/login")
fun login(@RequestParam("google") currentUrl: String, request: HttpServletRequest): AuthLoginResponse {
val resolver = DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository,
DEFAULT_AUTHORIZATION_REQUEST_BASE_URI
)
val authRequest = resolver.resolve(request, "google").let {
OAuth2AuthorizationRequest.from(it)
.state(currentUrl) // JWTを生成してstateにセットするのをお勧めします。
.build()
}
return AuthLoginResponse(authRequest.authorizationRequestUri)
}
}
上でセットした state の値は google によって call back される時に query parameter としてセットされてきますのでそれを抽出します。
package jp.co.kopher.backendkotlin.controller
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.security.core.Authentication
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
import org.springframework.stereotype.Component
@Component
class OAuth2SuccessHandler : AuthenticationSuccessHandler {
override fun onAuthenticationSuccess(
request: HttpServletRequest?,
response: HttpServletResponse?,
authentication: Authentication?
) {
val currentUri = request?.getParameter("state") ?: "/"
response?.sendRedirect("http://localhost:3000/$currentUri")
}
}
Google 認証成功後呼ばれる Handler として OAuth2SuccessHandler を登録します。
package jp.co.kopher.backendkotlin.config
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
@Configuration
class SecurityConfig(
private val oauth2SuccessHandler: AuthenticationSuccessHandler,
) {
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
http.oauth2Login {
it.successHandler(oauth2SuccessHandler)
}
return http.build()
}
}
これで終わりです!