mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 16:52:13 +00:00
246 lines
9.3 KiB
Plaintext
246 lines
9.3 KiB
Plaintext
[[webflux-oauth2-login]]
|
|
= OAuth 2.0 Login
|
|
|
|
The OAuth 2.0 Login feature provides an application with the capability to have users log in to the application by using their existing account at an OAuth 2.0 Provider (e.g.
|
|
GitHub) or OpenID Connect 1.0 Provider (such as Google).
|
|
OAuth 2.0 Login implements the use cases: "Login with Google" or "Login with GitHub".
|
|
|
|
NOTE: OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework] and https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect Core 1.0].
|
|
|
|
[[webflux-oauth2-login-sample]]
|
|
== Spring Boot 2.0 Sample
|
|
|
|
Spring Boot 2.0 brings full auto-configuration capabilities for OAuth 2.0 Login.
|
|
|
|
This section shows how to configure the {gh-samples-url}/reactive/webflux/java/oauth2/login[*OAuth 2.0 Login WebFlux sample*] using _Google_ as the _Authentication Provider_ and covers the following topics:
|
|
|
|
* <<webflux-oauth2-login-sample-setup,Initial setup>>
|
|
* <<webflux-oauth2-login-sample-redirect,Setting the redirect URI>>
|
|
* <<webflux-oauth2-login-sample-config,Configure `application.yml`>>
|
|
* <<webflux-oauth2-login-sample-start,Boot up the application>>
|
|
|
|
|
|
[[webflux-oauth2-login-sample-setup]]
|
|
=== Initial setup
|
|
|
|
To use Google's OAuth 2.0 authentication system for login, you must set up a project in the Google API Console to obtain OAuth 2.0 credentials.
|
|
|
|
NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID Certified].
|
|
|
|
Follow the instructions on the https://developers.google.com/identity/protocols/OpenIDConnect[OpenID Connect] page, starting in the section, "Setting up OAuth 2.0".
|
|
|
|
After completing the "Obtain OAuth 2.0 credentials" instructions, you should have a new OAuth Client with credentials consisting of a Client ID and a Client Secret.
|
|
|
|
[[webflux-oauth2-login-sample-redirect]]
|
|
=== Setting the redirect URI
|
|
|
|
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google and have granted access to the OAuth Client _(<<webflux-oauth2-login-sample-setup,created in the previous step>>)_ on the Consent page.
|
|
|
|
In the "Set a redirect URI" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`.
|
|
|
|
TIP: The default redirect URI template is `+{baseUrl}/login/oauth2/code/{registrationId}+`.
|
|
The *_registrationId_* is a unique identifier for the xref:servlet/oauth2/client/core.adoc#oauth2Client-client-registration[ClientRegistration].
|
|
For our example, the `registrationId` is `google`.
|
|
|
|
IMPORTANT: If the OAuth Client is running behind a proxy server, it is recommended to check xref:features/exploits/http.adoc#http-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured.
|
|
Also, see the supported xref:servlet/oauth2/client/authorization-grants.adoc#oauth2Client-auth-code-redirect-uri[ `URI` template variables] for `redirect-uri`.
|
|
|
|
[[webflux-oauth2-login-sample-config]]
|
|
=== Configure `application.yml`
|
|
|
|
Now that you have a new OAuth Client with Google, you need to configure the application to use the OAuth Client for the _authentication flow_.
|
|
To do so:
|
|
|
|
. Go to `application.yml` and set the following configuration:
|
|
+
|
|
[source,yaml]
|
|
----
|
|
spring:
|
|
security:
|
|
oauth2:
|
|
client:
|
|
registration: <1>
|
|
google: <2>
|
|
client-id: google-client-id
|
|
client-secret: google-client-secret
|
|
----
|
|
+
|
|
.OAuth Client properties
|
|
====
|
|
<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties.
|
|
<2> Following the base property prefix is the ID for the xref:servlet/oauth2/client/index.adoc#oauth2Client-client-registration[`ClientRegistration`], such as google.
|
|
====
|
|
|
|
. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier.
|
|
|
|
|
|
[[webflux-oauth2-login-sample-start]]
|
|
=== Boot up the application
|
|
|
|
Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`.
|
|
You are then redirected to the default _auto-generated_ login page, which displays a link for Google.
|
|
|
|
Click on the Google link, and you are then redirected to Google for authentication.
|
|
|
|
After authenticating with your Google account credentials, the next page presented to you is the Consent screen.
|
|
The Consent screen asks you to either allow or deny access to the OAuth Client you created earlier.
|
|
Click *Allow* to authorize the OAuth Client to access your email address and basic profile information.
|
|
|
|
At this point, the OAuth Client retrieves your email address and basic profile information from the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint] and establishes an authenticated session.
|
|
|
|
[[webflux-oauth2-login-openid-provider-configuration]]
|
|
== Using OpenID Provider Configuration
|
|
|
|
For well known providers, Spring Security provides the necessary defaults for the OAuth Authorization Provider's configuration.
|
|
If you are working with your own Authorization Provider that supports https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[OpenID Provider Configuration] or https://tools.ietf.org/html/rfc8414#section-3[Authorization Server Metadata], the https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse[OpenID Provider Configuration Response]'s `issuer-uri` can be used to configure the application.
|
|
|
|
[source,yml]
|
|
----
|
|
spring:
|
|
security:
|
|
oauth2:
|
|
client:
|
|
provider:
|
|
keycloak:
|
|
issuer-uri: https://idp.example.com/auth/realms/demo
|
|
registration:
|
|
keycloak:
|
|
client-id: spring-security
|
|
client-secret: 6cea952f-10d0-4d00-ac79-cc865820dc2c
|
|
----
|
|
|
|
The `issuer-uri` instructs Spring Security to query in series the endpoints `https://idp.example.com/auth/realms/demo/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/auth/realms/demo`, or `https://idp.example.com/.well-known/oauth-authorization-server/auth/realms/demo` to discover the configuration.
|
|
|
|
[NOTE]
|
|
Spring Security will query the endpoints one at a time, stopping at the first that gives a 200 response.
|
|
|
|
The `client-id` and `client-secret` are linked to the provider because `keycloak` is used for both the provider and the registration.
|
|
|
|
|
|
[[webflux-oauth2-login-explicit]]
|
|
== Explicit OAuth2 Login Configuration
|
|
|
|
A minimal OAuth2 Login configuration is shown below:
|
|
|
|
.Minimal OAuth2 Login
|
|
====
|
|
.Java
|
|
[source,java,role="primary"]
|
|
----
|
|
@Bean
|
|
ReactiveClientRegistrationRepository clientRegistrations() {
|
|
ClientRegistration clientRegistration = ClientRegistrations
|
|
.fromIssuerLocation("https://idp.example.com/auth/realms/demo")
|
|
.clientId("spring-security")
|
|
.clientSecret("6cea952f-10d0-4d00-ac79-cc865820dc2c")
|
|
.build();
|
|
return new InMemoryReactiveClientRegistrationRepository(clientRegistration);
|
|
}
|
|
|
|
@Bean
|
|
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
|
http
|
|
// ...
|
|
.oauth2Login(withDefaults());
|
|
return http.build();
|
|
}
|
|
----
|
|
|
|
.Kotlin
|
|
[source,kotlin,role="secondary"]
|
|
----
|
|
@Bean
|
|
fun clientRegistrations(): ReactiveClientRegistrationRepository {
|
|
val clientRegistration: ClientRegistration = ClientRegistrations
|
|
.fromIssuerLocation("https://idp.example.com/auth/realms/demo")
|
|
.clientId("spring-security")
|
|
.clientSecret("6cea952f-10d0-4d00-ac79-cc865820dc2c")
|
|
.build()
|
|
return InMemoryReactiveClientRegistrationRepository(clientRegistration)
|
|
}
|
|
|
|
@Bean
|
|
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
|
return http {
|
|
oauth2Login { }
|
|
}
|
|
}
|
|
----
|
|
====
|
|
|
|
Additional configuration options can be seen below:
|
|
|
|
.Advanced OAuth2 Login
|
|
====
|
|
.Java
|
|
[source,java,role="primary"]
|
|
----
|
|
@Bean
|
|
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
|
http
|
|
// ...
|
|
.oauth2Login(oauth2 -> oauth2
|
|
.authenticationConverter(converter)
|
|
.authenticationManager(manager)
|
|
.authorizedClientRepository(authorizedClients)
|
|
.clientRegistrationRepository(clientRegistrations)
|
|
);
|
|
return http.build();
|
|
}
|
|
----
|
|
|
|
.Kotlin
|
|
[source,kotlin,role="secondary"]
|
|
----
|
|
@Bean
|
|
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
|
return http {
|
|
oauth2Login {
|
|
authenticationConverter = converter
|
|
authenticationManager = manager
|
|
authorizedClientRepository = authorizedClients
|
|
clientRegistrationRepository = clientRegistration
|
|
}
|
|
}
|
|
}
|
|
----
|
|
====
|
|
|
|
You may register a `GrantedAuthoritiesMapper` `@Bean` to have it automatically applied to the default configuration, as shown in the following example:
|
|
|
|
.GrantedAuthoritiesMapper Bean
|
|
====
|
|
.Java
|
|
[source,java,role="primary"]
|
|
----
|
|
@Bean
|
|
public GrantedAuthoritiesMapper userAuthoritiesMapper() {
|
|
...
|
|
}
|
|
|
|
@Bean
|
|
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
|
|
http
|
|
// ...
|
|
.oauth2Login(withDefaults());
|
|
return http.build();
|
|
}
|
|
----
|
|
|
|
.Kotlin
|
|
[source,kotlin,role="secondary"]
|
|
----
|
|
@Bean
|
|
fun userAuthoritiesMapper(): GrantedAuthoritiesMapper {
|
|
// ...
|
|
}
|
|
|
|
@Bean
|
|
fun webFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
|
|
return http {
|
|
oauth2Login { }
|
|
}
|
|
}
|
|
----
|
|
====
|