10 changed files with 339 additions and 0 deletions
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
/* |
||||
* Copyright 2020-2022 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.socialLogin; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.core.annotation.Order; |
||||
import org.springframework.http.MediaType; |
||||
import org.springframework.security.config.Customizer; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; |
||||
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer; |
||||
import org.springframework.security.web.SecurityFilterChain; |
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; |
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher; |
||||
|
||||
@Configuration |
||||
@EnableWebSecurity |
||||
public class SecurityConfig { |
||||
|
||||
@Bean // <1>
|
||||
@Order(1) |
||||
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) |
||||
throws Exception { |
||||
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); |
||||
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class) |
||||
.oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
|
||||
// @formatter:off
|
||||
http |
||||
// Redirect to the OAuth 2.0 Login endpoint when not authenticated
|
||||
// from the authorization endpoint
|
||||
.exceptionHandling((exceptions) -> exceptions |
||||
.defaultAuthenticationEntryPointFor( // <2>
|
||||
new LoginUrlAuthenticationEntryPoint("/oauth2/authorization/my-client"), |
||||
new MediaTypeRequestMatcher(MediaType.TEXT_HTML) |
||||
) |
||||
) |
||||
// Accept access tokens for User Info and/or Client Registration
|
||||
.oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults())); |
||||
// @formatter:on
|
||||
|
||||
return http.build(); |
||||
} |
||||
|
||||
@Bean // <3>
|
||||
@Order(2) |
||||
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) |
||||
throws Exception { |
||||
// @formatter:off
|
||||
http |
||||
.authorizeHttpRequests((authorize) -> authorize |
||||
.anyRequest().authenticated() |
||||
) |
||||
// OAuth2 Login handles the redirect to the OAuth 2.0 Login endpoint
|
||||
// from the authorization server filter chain
|
||||
.oauth2Login(Customizer.withDefaults()); // <4>
|
||||
// @formatter:on
|
||||
|
||||
return http.build(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
okta: |
||||
base-url: ${OKTA_BASE_URL} |
||||
|
||||
spring: |
||||
security: |
||||
oauth2: |
||||
client: |
||||
registration: |
||||
my-client: |
||||
provider: okta |
||||
client-id: ${OKTA_CLIENT_ID} |
||||
client-secret: ${OKTA_CLIENT_SECRET} |
||||
scope: |
||||
- openid |
||||
- profile |
||||
- email |
||||
provider: |
||||
okta: |
||||
authorization-uri: ${okta.base-url}/oauth2/v1/authorize |
||||
token-uri: ${okta.base-url}/oauth2/v1/token |
||||
user-info-uri: ${okta.base-url}/oauth2/v1/userinfo |
||||
jwk-set-uri: ${okta.base-url}/oauth2/v1/keys |
||||
user-name-attribute: sub |
||||
@ -0,0 +1,217 @@
@@ -0,0 +1,217 @@
|
||||
[[how-to-social-login]] |
||||
= How-to: Authenticate using Social Login |
||||
:index-link: ../how-to.html |
||||
:docs-dir: .. |
||||
:examples-dir: {docs-dir}/examples |
||||
:samples-dir: {docs-dir}/../../../../samples |
||||
:github-ref: main |
||||
:github-base-url: https://github.com/spring-projects/spring-authorization-server/blob/{github-ref} |
||||
|
||||
This guide shows how to configure xref:{docs-dir}/index.adoc#top[Spring Authorization Server] with a social login provider (such as Google, GitHub, etc.) for {spring-security-reference-base-url}/servlet/authentication/index.html[authentication]. |
||||
The purpose of this guide is to demonstrate how to replace {spring-security-reference-base-url}/servlet/authentication/passwords/form.html[Form Login] with {spring-security-reference-base-url}/servlet/oauth2/login/index.html[OAuth 2.0 Login]. |
||||
|
||||
NOTE: Spring Authorization Server is built on {spring-security-reference-base-url}/index.html[Spring Security] and we will be using Spring Security concepts throughout this guide. |
||||
|
||||
* <<register-social-login-provider>> |
||||
* <<configure-oauth2-login>> |
||||
* <<advanced-use-cases>> |
||||
|
||||
[[register-social-login-provider]] |
||||
== Register with Social Login Provider |
||||
|
||||
To get started, you will need to set up an application with your chosen social login provider. |
||||
Common providers include: |
||||
|
||||
* https://developers.google.com/identity/openid-connect/openid-connect#appsetup[Google] |
||||
* https://github.com/settings/developers[GitHub] |
||||
* https://developers.facebook.com/apps[Facebook] |
||||
* https://www.okta.com/developer/signup[Okta] |
||||
|
||||
Follow the steps for your provider until you are asked to specify a Redirect URI. |
||||
To set up a Redirect URI, choose a `registrationId` (such as `google`, `my-client` or any other unique identifier you wish) which you will use to configure both Spring Security **and** your provider. |
||||
|
||||
NOTE: The `registrationId` is a unique identifier for the `ClientRegistration` in Spring Security. The default Redirect URI template is `\{baseUrl\}/login/oauth2/code/\{registrationId\}`. See {spring-security-reference-base-url}/servlet/oauth2/login/core.html#oauth2login-sample-redirect-uri[Setting the Redirect URI] in the Spring Security reference for more information. |
||||
|
||||
TIP: For example, testing locally on port `9000` with a `registrationId` of `google`, your Redirect URI would be `http://localhost:9000/login/oauth2/code/google`. Enter this value as the Redirect URI when setting up the application with your provider. |
||||
|
||||
Once you've completed the set-up process with your social login provider, you should have obtained credentials (a Client ID and Client Secret). |
||||
In addition, you will need to reference the provider's documentation and take note of the following values: |
||||
|
||||
* **Authorization URI**: The endpoint that is used to initiate the `authorization_code` flow at the provider. |
||||
* **Token URI**: The endpoint that is used to exchange an `authorization_code` for an `access_token` and optionally an `id_token`. |
||||
* **JWK Set URI**: The endpoint that is used to obtain keys for verifying the signature of a JWT, which is required when an `id_token` is available. |
||||
* **User Info URI**: The endpoint that is used to obtain user information, which is required when an `id_token` is not available. |
||||
* **User Name Attribute**: The claim in either the `id_token` or the User Info Response containing the username of the user. |
||||
|
||||
[[configure-oauth2-login]] |
||||
== Configure OAuth 2.0 Login |
||||
|
||||
Once you've <<register-social-login-provider,registered>> with a social login provider, you can proceed to configuring Spring Security for {spring-security-reference-base-url}/servlet/oauth2/login/index.html[OAuth 2.0 Login]. |
||||
|
||||
* <<configure-oauth2-login-dependency>> |
||||
* <<configure-oauth2-login-client-registration>> |
||||
* <<configure-oauth2-login-authentication>> |
||||
|
||||
[[configure-oauth2-login-dependency]] |
||||
=== Add OAuth2 Client Dependency |
||||
|
||||
First, add the following dependency: |
||||
|
||||
[[configure-oauth2-login-maven-dependency]] |
||||
.Maven |
||||
[source,xml,role="primary",subs="attributes,verbatim"] |
||||
---- |
||||
<dependency> |
||||
<groupId>org.springframework.boot</groupId> |
||||
<artifactId>spring-boot-starter-oauth2-client</artifactId> |
||||
</dependency> |
||||
---- |
||||
|
||||
[[configure-oauth2-login-gradle-dependency]] |
||||
.Gradle |
||||
[source,gradle,role="secondary",subs="attributes,verbatim"] |
||||
---- |
||||
implementation "org.springframework.boot:spring-boot-starter-oauth2-client" |
||||
---- |
||||
|
||||
[[configure-oauth2-login-client-registration]] |
||||
=== Register a Client |
||||
|
||||
Next, configure the `ClientRegistration` with the values obtained <<register-social-login-provider,earlier>>. |
||||
Using Okta as an example, configure the following properties: |
||||
|
||||
[[configure-oauth2-login-okta-example]] |
||||
.application.yml |
||||
[source,yaml] |
||||
---- |
||||
include::{examples-dir}/src/main/java/sample/socialLogin/application.yml[] |
||||
---- |
||||
|
||||
NOTE: The `registrationId` in the above example is `my-client`. |
||||
|
||||
TIP: The above example demonstrates the *recommended* way to set the Provider URL, Client ID and Client Secret using environment variables (`OKTA_BASE_URL`, `OKTA_CLIENT_ID` and `OKTA_CLIENT_SECRET`). See {spring-boot-reference-base-url}/features.html#features.external-config[Externalized Configuration] in the Spring Boot reference for more information. |
||||
|
||||
This simple example demonstrates a typical configuration, but some providers will require additional configuration. |
||||
For more information about configuring the `ClientRegistration`, see {spring-security-reference-base-url}/servlet/oauth2/login/core.html#oauth2login-boot-property-mappings[Spring Boot Property Mappings] in the Spring Security reference. |
||||
|
||||
[[configure-oauth2-login-authentication]] |
||||
=== Configure Authentication |
||||
|
||||
Finally, to configure Spring Authorization Server to use a social login provider for authentication, you can use `oauth2Login()` instead of `formLogin()`. |
||||
You can also automatically redirect an unauthenticated user to the provider by configuring `exceptionHandling()` with an `AuthenticationEntryPoint`. |
||||
|
||||
Continuing our <<configure-oauth2-login-okta-example,earlier example>>, configure Spring Security using a `@Configuration` as in the following example: |
||||
|
||||
.Configure OAuth 2.0 Login |
||||
[source,java] |
||||
---- |
||||
include::{examples-dir}/src/main/java/sample/socialLogin/SecurityConfig.java[] |
||||
---- |
||||
|
||||
<1> A Spring Security filter chain for the xref:protocol-endpoints.adoc[Protocol Endpoints]. |
||||
<2> Configure an `AuthenticationEntryPoint` for redirecting to the {spring-security-reference-base-url}/servlet/oauth2/login/advanced.html#oauth2login-advanced-login-page[OAuth 2.0 Login endpoint]. |
||||
<3> A Spring Security filter chain for https://docs.spring.io/spring-security/reference/servlet/authentication/index.html[authentication]. |
||||
<4> Configure {spring-security-reference-base-url}/servlet/oauth2/login/index.html[OAuth 2.0 Login] for authentication. |
||||
|
||||
If you configured a `UserDetailsService` when xref:{docs-dir}/getting-started.adoc#developing-your-first-application[getting started], you can remove it now. |
||||
|
||||
[[advanced-use-cases]] |
||||
== Advanced Use Cases |
||||
|
||||
The https://github.com/spring-projects/spring-authorization-server/tree/{github-ref}/samples#demo-sample[demo authorization server sample^] demonstrates advanced configuration options for federating identity providers. |
||||
Select from the following use cases to see an example of each: |
||||
|
||||
* I want to <<advanced-use-cases-automatically-redirect>> |
||||
* I want to <<advanced-use-cases-capture-users>> |
||||
* I want to <<advanced-use-cases-map-claims>> |
||||
* I want to <<advanced-use-cases-configurer>> |
||||
|
||||
[[advanced-use-cases-automatically-redirect]] |
||||
=== Automatically Redirect to a Provider |
||||
|
||||
The following example `AuthenticationEntryPoint` uses a query parameter as a hint from the client to indicate which provider to automatically redirect to for authentication. |
||||
For example, assuming Google is configured as a social login provider with a `registrationId` of `google`, a request to `/oauth2/authorize?idp=google&...` will redirect an unauthenticated user to `/oauth2/authorization/google` which will initiate logging in with Google: |
||||
|
||||
.`FederatedIdentityAuthenticationEntryPoint` |
||||
[source,java] |
||||
---- |
||||
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/FederatedIdentityAuthenticationEntryPoint.java[] |
||||
---- |
||||
|
||||
[[advanced-use-cases-capture-users]] |
||||
=== Capture Users in a Database |
||||
|
||||
The following example `AuthenticationSuccessHandler` uses a custom component to capture users in a local database when they first log in: |
||||
|
||||
.`FederatedIdentityAuthenticationSuccessHandler` |
||||
[source,java] |
||||
---- |
||||
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/FederatedIdentityAuthenticationSuccessHandler.java[] |
||||
---- |
||||
|
||||
Using the `AuthenticationSuccessHandler` above, you can plug in your own `Consumer<OAuth2User>` that can capture users in a database or other data store for concepts like Federated Account Linking or JIT Account Provisioning. |
||||
Here is an example that simply stores users in-memory: |
||||
|
||||
.`UserRepositoryOAuth2UserHandler` |
||||
[source,java] |
||||
---- |
||||
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/UserRepositoryOAuth2UserHandler.java[] |
||||
---- |
||||
|
||||
[[advanced-use-cases-map-claims]] |
||||
=== Map Claims to an ID Token |
||||
|
||||
The following example `OAuth2TokenCustomizer` maps a user's claims from an authentication provider to the `id_token` produced by Spring Authorization Server: |
||||
|
||||
.`FederatedIdentityIdTokenCustomizer` |
||||
[source,java] |
||||
---- |
||||
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/FederatedIdentityIdTokenCustomizer.java[] |
||||
---- |
||||
|
||||
You can configure Spring Authorization Server to use this customizer by publishing it as a `@Bean` as in the following example: |
||||
|
||||
.Configure `FederatedIdentityIdTokenCustomizer` |
||||
[source,java] |
||||
---- |
||||
@Bean |
||||
public OAuth2TokenCustomizer<JwtEncodingContext> idTokenCustomizer() { |
||||
return new FederatedIdentityIdTokenCustomizer(); |
||||
} |
||||
---- |
||||
|
||||
[[advanced-use-cases-configurer]] |
||||
=== Create My Own Configurer |
||||
|
||||
The following example `SecurityConfigurer` combines configuration for all of the above examples into a single reusable component: |
||||
|
||||
.`FederatedIdentityConfigurer` |
||||
[source,java] |
||||
---- |
||||
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/FederatedIdentityConfigurer.java[] |
||||
---- |
||||
|
||||
The configurer can be applied using the Spring Security DSL as in the following example: |
||||
|
||||
.Apply Configurer |
||||
[source,java] |
||||
---- |
||||
http.apply(new FederatedIdentityConfigurer()); |
||||
---- |
||||
|
||||
The configurer also has its own DSL to customize the defaults. |
||||
Here's a full example: |
||||
|
||||
.Customize using Configurer |
||||
[source,java] |
||||
---- |
||||
http.apply(new FederatedIdentityConfigurer()) |
||||
.loginPageUrl("/social/login") |
||||
.authorizationRequestUri("/social/login/{registrationId}") |
||||
.oauth2UserHandler((oauth2User) -> { |
||||
// TODO: Handle login of an OAuth2 user... |
||||
}) |
||||
.oidcUserHandler((oidcUser) -> { |
||||
// TODO: Handle login of an OIDC user... |
||||
}); |
||||
---- |
||||
Loading…
Reference in new issue