I have an app that connects to the Gmail API of its users. It authenticates by using the refreshToken to get an accessToken.
Libraries in use: Spring boot 3.4.1 -> Spring security 6.4.2
The refresh token is stored in the database and can be used for a long time, but is invalidated if password is changed for example. We need a way to get a new refresh token easily from an integration page, but cannot see how this can be done programatically with Spring security in a simple way.
Right now I have manually found the refreshToken by doing the following:
.oauth2Login(Customizer.withDefaults())
to the SecurityFilterChainclass: DefaultAuthorizationCodeTokenResponseClient
method: public OAuth2AccessTokenResponse getTokenResponse(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) {
In my properties file I have:
spring.security.oauth2.client.registration.google.client-id={....}
spring.security.oauth2.client.registration.google.client-secret=${GOOGLE_CLIENT_SECRET}
spring.security.oauth2.client.registration.google.scope=https://mail.google.com/,https://www.googleapis.com/auth/userinfo.profile,https://www.googleapis.com/auth/userinfo.email
spring.security.oauth2.client.provider.google.authorization-uri=https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&access_type=offline
So the question is simply Is there any Spring security features that can simplify this process of getting the refreshToken?
Ideal flow:
private fun refreshAccessToken(refreshToken: String): Credential {
val credential = GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setClientSecrets(CLIENT_ID, CLIENT_SECRET)
.build()
credential.refreshToken = refreshToken
credential.refreshToken()
return credential
}
Set up in Google Cloud Console:
When a user needs to authenticate:
private fun buildOAuthUrl(): String {
val encodedRedirectUri = URLEncoder.encode(redirectUri, StandardCharsets.UTF_8.toString())
val encodedScope = scope.split(" ")
.map { URLEncoder.encode(it.trim(), StandardCharsets.UTF_8.toString()) }
.joinToString(" ")
return UriComponentsBuilder.fromUriString(oauthUrl)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", encodedRedirectUri)
.queryParam("response_type", "code")
.queryParam("scope", encodedScope)
.queryParam("access_type", "offline")
.queryParam("prompt", "consent")
.build()
.toUriString()
}
After getting auth code:
val response = GoogleAuthorizationCodeTokenRequest(
httpTransport,
jsonFactory,
clientId,
clientSecret,
authCode(We will get from the callback URL),
redirectUri
).setGrantType("authorization_code").execute()
val refreshToken = response.refreshToken
We are getting refresh token from the response.refreshToken
After We are update our DB table with new generated refresh token with current user email