Example on Spring Boot 2.x
Spring Boot 2.x provides the ability to fully use auto-configuration to configure login via OAuth 2.0.
This section shows how to configure code example for OAuth login 2.0, using Google as the authentication provider, and the following topics are covered:
Initial setup
Configuring the URI for redirection
Configuring the application.yml file
-
Downloading the application
Initial setup
To use Google's OAuth 2.0 authentication system to log in, you must set up a project in the Google API Console to receive OAuth 2.0 credentials.
Follow the instructions at OpenID Connect, starting with the "Set up OAuth 2.0" section.
After completing the "Obtain OAuth 2.0 credentials" instructions, a new OAuth client should appear with the credentials consisting of a client ID and a client secret.
Configuring a redirect URI
The redirect URI is the path in the application to which the end user's user agent is redirected after authenticating with Google and granting access to OAuth client (created in the previous step) on the Consent page.
In the "Set redirect URI" section, make sure that the authorized
redirect URIs field is set to localhost:8080/login/oauth2/code/google
.
{baseUrl}/login
/oauth2/code/{registrationId}
. RegistrationId is a unique identifier for ClientRegistration
.
URI
template variables for redirect-uri
.
Configure the application.yml file
Now that you have a new one OAuth client via Google, you need to configure your application to use an OAuth client for the authentication flow. To do this:
Go to
application.yml
and set the following configuration:spring: security: oauth2: client: registration: google: client-id: google-client-id client-secret: google-client-secret
OAuth client propertiesspring.security.oauth2.client.registration
is the base property prefix for OAuth client properties.- The base property prefix is followed by identifier for
ClientRegistration
, for example google.
Replace the values in the
client-id
andclient-secret
properties to the OAuth 2.0 credentials that were created earlier.
Downloading the application
Run the Spring Boot 2.x example and go to localhost:8080
. You
will then be redirected to an automatically generated standard login page that displays a link for Google.
Click on the Google link and you will be redirected to Google to authenticate.
After authenticate with your Google account credentials, the Consent screen appears on the next page. The Consent screen will ask you to allow or deny access to the OAuth client that was created earlier. Click Allow to allow the OAuth client to access your email address and basic profile information.
At this point, the OAuth client receives your email address and basic profile information. profile from the UserInfo endpoint and establishes an authenticated session.
Property mappings in Spring Boot 2.x
The following table
describes the mapping of Spring Boot 2.x OAuth Client properties to ClientRegistration
properties.
Spring Boot 2.x | ClientRegistration |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ClientRegistration
can be initially configured using configuration endpoint of the OpenID Connect provider or Authorization server metadata
endpoint by setting the property spring.security.oauth2.client.provider.[providerId].issuer-uri
.
CommonOAuth2Provider
CommonOAuth2Provider
predefines a set of standard
client properties for a number of well-known providers: Google, GitHub, Facebook and Okta.
For example,
authorization-uri
, token-uri
and
user-info-uri
do not change frequently for any given provider. Therefore, it makes sense to provide
default values to reduce the required configuration.
As we showed earlier when we configured the Google client, only the client-id
and client-secret
properties are required.
The following listing is an example:
spring:
security:
oauth2:
client:
registration:
google:
client-id: google-client-id
client-secret: google-client-secret
registrationId
(google
) matches enum
GOOGLE
(case
insensitive) in CommonOAuth2Provider
.
For cases where you need to set a different registrationId
,
for example google-login
, you can still use automatic detection of default client properties by
configuring the propertyprovider
.
The following listing is an example:
spring:
security:
oauth2:
client:
registration:
google-login:
provider: google
client-id: google-client-id
client-secret: google-client-secret
- The
registrationId
is set togoogle-login
. - The
provider
property is set togoogle
, which will allow the automatic detection of default client properties set inCommonOAuth2Provider.GOOGLE.getBuilder()
.
Configuring custom provider properties
Some OAuth 2.0 providers support shared tenancy, which results in the creation of different endpoints protocols for each tenant (or subdomain).
For example, an OAuth client registered with Okta is assigned to a specific subdomain and has its own protocol endpoints.
For such cases, Spring Boot 2 .x provides the following basic property for configuring custom provider
properties: spring.security.oauth2.client.provider.[providerId]
.
The following listing is an example:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
provider:
okta:
authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize
token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token
user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo
user-name-attribute: sub
jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys
- Base property
(spring.security.oauth2.client.provider.okta
) allows you to custom configure the location of protocol endpoints.
Spring Boot 2.x autoconfiguration override
Spring Boot 2.x autoconfiguration class for OAuth client support – OAuth2ClientAutoConfiguration
.
It performs the following tasks:
Registers
@Bean
forClientRegistrationRepository
consisting ofClientRegistration
instance(s) of configured OAuth client properties.Registers a
@Bean
forSecurityFilterChain
and activates authorization in OAuth 2.0 viahttpSecurity.oauth2Login()
.
If you need to override auto-configuration for specific needs , then you can do this in the following ways:
Register @Bean for ClientRegistrationRepository
Register @Bean for SecurityFilterChain
Full auto-config override
Registering @Bean for ClientRegistrationRepository
The following example shows how to register @Bean
for ClientRegistrationRepository
:
@Configuration
public class OAuth2LoginConfig {
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
@Configuration
class OAuth2LoginConfig {
@Bean
fun clientRegistrationRepository(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(googleClientRegistration())
}
private fun googleClientRegistration(): ClientRegistration {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build()
}
}
Registering @Bean for SecurityFilterChain
The following example shows how to register @Bean
for SecurityFilterChain
using the
@EnableWebSecurity
annotation and enable authorization in OAuth 2.0 via httpSecurity.oauth2Login()
:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
}
@EnableWebSecurity
class OAuth2LoginSecurityConfig {
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
return http.build()
}
}
Full auto-configuration override
The following example shows how to completely override
autoconfiguration by registering @Bean
for ClientRegistrationRepository
and
@Bean
for SecurityFilterChain
.
@Configuration
public class OAuth2LoginConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
private ClientRegistration googleClientRegistration() {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build();
}
}
@Configuration
class OAuth2LoginConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
return http.build()
}
@Bean
fun clientRegistrationRepository(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(googleClientRegistration())
}
private fun googleClientRegistration(): ClientRegistration {
return ClientRegistration.withRegistrationId("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("{baseUrl}/login/oauth2/code/{registrationId}")
.scope("openid", "profile", "email", "address", "phone")
.authorizationUri("https://accounts.google.com/o/oauth2/v2/auth")
.tokenUri("https://www.googleapis.com/oauth2/v4/token")
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.jwkSetUri("https://www.googleapis.com/oauth2/v3/certs")
.clientName("Google")
.build()
}
}
Java-based configuration without Spring Boot 2.x
If using Spring Boot 2.x is not possible, but you need to configure one of the predefined providers in CommonOAuth2Provider
(eg Google), apply the following configuration:
@EnableWebSecurity
public class OAuth2LoginConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.oauth2Login(withDefaults());
return http.build();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.googleClientRegistration());
}
@Bean
public OAuth2AuthorizedClientService authorizedClientService(
ClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public OAuth2AuthorizedClientRepository authorizedClientRepository(
OAuth2AuthorizedClientService authorizedClientService) {
return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
}
private ClientRegistration googleClientRegistration() {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build();
}
}
@EnableWebSecurity
open class OAuth2LoginConfig {
@Bean
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2Login { }
}
return http.build()
}
@Bean
open fun clientRegistrationRepository(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(googleClientRegistration())
}
@Bean
open fun authorizedClientService(
clientRegistrationRepository: ClientRegistrationRepository?
): OAuth2AuthorizedClientService {
return InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository)
}
@Bean
open fun authorizedClientRepository(
authorizedClientService: OAuth2AuthorizedClientService?
): OAuth2AuthorizedClientRepository {
return AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService)
}
private fun googleClientRegistration(): ClientRegistration {
return CommonOAuth2Provider.GOOGLE.getBuilder("google")
.clientId("google-client-id")
.clientSecret("google-client-secret")
.build()
}
}
<http auto-config="true">
<intercept-url pattern="/**" access="authenticated"/>
<oauth2-login authorized-client-repository-ref="authorizedClientRepository"/>
</http>
<client-registrations>
<client-registration registration-id="google"
client-id="google-client-id"
client-secret="google-client-secret"
provider-id="google"/>
</client-registrations>
<b:bean id="authorizedClientService"
class="org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService"
autowire="constructor"/>
<b:bean id="authorizedClientRepository"
class="org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository">
<b:constructor-arg ref="authorizedClientService"/>
</b:bean>