mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 09:12:14 +00:00
343 lines
19 KiB
Plaintext
343 lines
19 KiB
Plaintext
= OAuth 2.0 Login Sample
|
|
Joe Grandja
|
|
:toc:
|
|
:security-site-url: https://projects.spring.io/spring-security/
|
|
|
|
[.lead]
|
|
This guide will walk you through the steps for setting up the sample application with OAuth 2.0 Login using an external _OAuth 2.0_ or _OpenID Connect 1.0_ Provider.
|
|
The sample application is built with *Spring Boot 1.5* and the *spring-security-oauth2-client* module that is new in {security-site-url}[Spring Security 5.0].
|
|
|
|
The following sections outline detailed steps for setting up OAuth 2.0 Login with these Providers:
|
|
|
|
* <<google-login, Google>>
|
|
* <<github-login, GitHub>>
|
|
* <<facebook-login, Facebook>>
|
|
* <<okta-login, Okta>>
|
|
|
|
NOTE: The _"authentication flow"_ is realized using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework].
|
|
|
|
[[sample-app-content]]
|
|
== Sample application content
|
|
|
|
The sample application contains the following package structure and artifacts:
|
|
|
|
*org.springframework.security.samples*
|
|
|
|
[circle]
|
|
* _OAuth2LoginApplication_ - the main class for the _Spring application_.
|
|
** *user*
|
|
*** _GitHubOAuth2User_ - a custom _UserInfo_ type for <<github-login, GitHub Login>>.
|
|
** *web*
|
|
*** _MainController_ - the root controller that displays user information after a successful login.
|
|
|
|
*org.springframework.boot.autoconfigure.security.oauth2.client*
|
|
|
|
[circle]
|
|
* <<client-registration-auto-configuration-class, _ClientRegistrationAutoConfiguration_>> - a Spring Boot auto-configuration class
|
|
that automatically registers a _ClientRegistrationRepository_ bean in the _ApplicationContext_.
|
|
* <<oauth2-login-auto-configuration-class, _OAuth2LoginAutoConfiguration_>> - a Spring Boot auto-configuration class that automatically enables OAuth 2.0 Login.
|
|
|
|
WARNING: The Spring Boot auto-configuration classes (and dependent resources) will eventually _live_ in the *Spring Boot Security Starter*.
|
|
|
|
NOTE: See <<oauth2-login-auto-configuration, OAuth 2.0 Login auto-configuration>> for a detailed overview of the auto-configuration classes.
|
|
|
|
[[google-login]]
|
|
== Setting up *_Login with Google_*
|
|
|
|
The goal for this section of the guide is to setup login using Google as the _Authentication Provider_.
|
|
|
|
NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the
|
|
http://openid.net/connect/[OpenID Connect] specification and is http://openid.net/certification/[OpenID Certified].
|
|
|
|
[[google-login-register-credentials]]
|
|
=== Register OAuth 2.0 credentials
|
|
|
|
In order 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.
|
|
|
|
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 sub-section, *_"Obtain OAuth 2.0 credentials"_*, you should have created a new *OAuth Client* with credentials consisting of a *Client ID* and *Client Secret*.
|
|
|
|
[[google-login-redirect-uri]]
|
|
=== Setting the redirect URI
|
|
|
|
The redirect URI is the path in the sample 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 _(created from the <<google-login-register-credentials, previous step>>)_ on the *Consent screen* page.
|
|
|
|
For the sub-section, *_"Set a redirect URI"_*, ensure the *Authorised redirect URIs* is set to *http://localhost:8080/oauth2/authorize/code/google*
|
|
|
|
TIP: The default redirect URI is *_"{scheme}://{serverName}:{serverPort}/oauth2/authorize/code/{clientAlias}"_*.
|
|
See <<oauth2-client-properties, OAuth client properties>> for more details on this default.
|
|
|
|
[[google-login-configure-application-yml]]
|
|
=== Configuring application.yml
|
|
|
|
Now that we have created a new OAuth Client with Google, we need to configure the sample application to use this OAuth Client for the _authentication flow_.
|
|
|
|
Go to *_src/main/resources_* and edit *application.yml*. Add the following configuration:
|
|
|
|
[source,yaml]
|
|
----
|
|
security:
|
|
oauth2:
|
|
client:
|
|
google:
|
|
client-id: ${client-id}
|
|
client-secret: ${client-secret}
|
|
----
|
|
|
|
Replace *${client-id}* and *${client-secret}* with the OAuth 2.0 credentials created in the previous section <<google-login-register-credentials, Register OAuth 2.0 credentials>>.
|
|
|
|
[TIP]
|
|
.OAuth client properties
|
|
====
|
|
. *security.oauth2.client* is the *_base property prefix_* for OAuth client properties.
|
|
. Just below the *_base property prefix_* is the *_client property key_*, for example *security.oauth2.client.google*.
|
|
. At the base of the *_client property key_* are the properties for specifying the configuration for an OAuth Client.
|
|
A list of these properties are detailed in <<oauth2-client-properties, OAuth client properties>>.
|
|
====
|
|
|
|
[[google-login-run-sample]]
|
|
=== Running the sample
|
|
|
|
Launch the Spring Boot application by running *_org.springframework.security.samples.OAuth2LoginApplication_*.
|
|
|
|
After the application successfully starts up, go to http://localhost:8080. You will be redirected to http://localhost:8080/login, which will display an _auto-generated login page_ with an anchor link for *Google*.
|
|
|
|
Click through on the Google link and you'll be redirected to Google for authentication.
|
|
|
|
After you authenticate using your Google credentials, the next page presented to you will be the *Consent screen*.
|
|
The Consent screen will ask you to either *_Allow_* or *_Deny_* access to the OAuth Client you created in the previous step <<google-login-register-credentials, Register OAuth 2.0 credentials>>.
|
|
Click *_Allow_* to authorize the OAuth Client to access your _email address_ and _basic profile_ information.
|
|
|
|
At this point, the OAuth Client will retrieve your email address and basic profile information from the http://openid.net/specs/openid-connect-core-1_0.html#UserInfo[*UserInfo Endpoint*] and establish an _authenticated session_.
|
|
The home page will then be displayed showing the user attributes retrieved from the *UserInfo Endpoint*, for example, name, email, profile, sub, etc.
|
|
|
|
[[oauth2-login-auto-configuration]]
|
|
== OAuth 2.0 Login auto-configuration
|
|
|
|
As you worked through this guide and setup OAuth 2.0 Login with one of the Providers,
|
|
we hope you noticed the ease in configuration and setup required in getting the sample up and running?
|
|
And you may be asking, how does this all work? Thanks to some Spring Boot auto-configuration _magic_,
|
|
we were able to automatically register the OAuth Client(s) configured in the `Environment`,
|
|
as well, provide a minimal security configuration for OAuth 2.0 Login for these registered OAuth Client(s).
|
|
|
|
The following provides an overview of the Spring Boot auto-configuration classes:
|
|
|
|
[[client-registration-auto-configuration-class]]
|
|
*_org.springframework.boot.autoconfigure.security.oauth2.client.ClientRegistrationAutoConfiguration_*::
|
|
`ClientRegistrationAutoConfiguration` is responsible for registering a `ClientRegistrationRepository` _bean_ with the `ApplicationContext`.
|
|
The `ClientRegistrationRepository` is composed of one or more `ClientRegistration` instances, which are created from the OAuth client properties
|
|
configured in the `Environment` that are prefixed with `security.oauth2.client.[client-alias]`, for example, `security.oauth2.client.google`.
|
|
|
|
NOTE: `ClientRegistrationAutoConfiguration` also loads a _resource_ named *oauth2-clients-defaults.yml*,
|
|
which provides a set of default client property values for a number of _well-known_ Providers.
|
|
More on this in the later section <<oauth2-default-client-properties, Default client property values>>.
|
|
|
|
[[oauth2-login-auto-configuration-class]]
|
|
*_org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2LoginAutoConfiguration_*::
|
|
`OAuth2LoginAutoConfiguration` is responsible for enabling OAuth 2.0 Login,
|
|
only if there is a `ClientRegistrationRepository` _bean_ available in the `ApplicationContext`.
|
|
|
|
WARNING: The auto-configuration classes (and dependent resources) will eventually _live_ in the *Spring Boot Security Starter*.
|
|
|
|
[[oauth2-client-properties]]
|
|
=== OAuth client properties
|
|
|
|
The following specifies the common set of properties available for configuring an OAuth Client.
|
|
|
|
[TIP]
|
|
====
|
|
- *security.oauth2.client* is the *_base property prefix_* for OAuth client properties.
|
|
- Just below the *_base property prefix_* is the *_client property key_*, for example *security.oauth2.client.google*.
|
|
- At the base of the *_client property key_* are the properties for specifying the configuration for an OAuth Client.
|
|
====
|
|
|
|
- *client-authentication-method* - the method used to authenticate the _Client_ with the _Provider_. Supported values are *header* and *form*.
|
|
- *authorized-grant-type* - the OAuth 2.0 Authorization Framework defines the https://tools.ietf.org/html/rfc6749#section-1.3.1[Authorization Code] grant type,
|
|
which is used to realize the _"authentication flow"_. Currently, this is the only supported grant type.
|
|
- *redirect-uri* - this is the client's _registered_ redirect URI that the _Authorization Server_ redirects the end-user's user-agent
|
|
to after the end-user has authenticated and authorized access for the client.
|
|
|
|
NOTE: The default redirect URI is _"{scheme}://{serverName}:{serverPort}/oauth2/authorize/code/{clientAlias}"_, which leverages *URI template variables*.
|
|
|
|
- *scopes* - a comma-delimited string of scope(s) requested during the _Authorization Request_ flow, for example: _openid, email, profile_
|
|
|
|
NOTE: _OpenID Connect 1.0_ defines these http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims[standard scopes]: _profile, email, address, phone_
|
|
|
|
NOTE: Non-standard scopes may be defined by a standard _OAuth 2.0 Provider_. Please consult the Provider's OAuth API documentation to learn which scopes are supported.
|
|
|
|
- *authorization-uri* - the URI used by the client to redirect the end-user's user-agent to the _Authorization Server_ in order to obtain authorization from the end-user (the _Resource Owner_).
|
|
- *token-uri* - the URI used by the client when exchanging an _Authorization Grant_ (for example, Authorization Code) for an _Access Token_ at the _Authorization Server_.
|
|
- *user-info-uri* - the URI used by the client to access the protected resource *UserInfo Endpoint*, in order to obtain attributes of the end-user.
|
|
- *user-info-converter* - the `Converter` implementation class used to convert the *UserInfo Response* to a `UserInfo` (_OpenID Connect 1.0 Provider_) or `OAuth2User` instance (_Standard OAuth 2.0 Provider_).
|
|
|
|
TIP: The `Converter` implementation class for an _OpenID Connect 1.0 Provider_ is *org.springframework.security.oauth2.client.user.converter.UserInfoConverter*
|
|
and for a standard _OAuth 2.0 Provider_ it's *org.springframework.security.oauth2.client.user.converter.OAuth2UserConverter*.
|
|
|
|
- *user-info-name-attribute-key* - the _key_ used to retrieve the *Name* of the end-user from the `Map` of available attributes in `UserInfo` or `OAuth2User`.
|
|
|
|
NOTE: _OpenID Connect 1.0_ defines the http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims[*"name"* Claim], which is the end-user's full name and is the default used for `UserInfo`.
|
|
|
|
IMPORTANT: Standard _OAuth 2.0 Provider's_ may vary the naming of their *Name* attribute. Please consult the Provider's *UserInfo* API documentation.
|
|
This is a *_required_* property when *user-info-converter* is set to `OAuth2UserConverter`.
|
|
|
|
- *client-name* - this is a descriptive name used for the client. The name may be used in certain scenarios, for example, when displaying the name of the client in the _auto-generated login page_.
|
|
- *client-alias* - an _alias_ which uniquely identifies the client. It *must be* unique within a `ClientRegistrationRepository`.
|
|
|
|
[[oauth2-default-client-properties]]
|
|
=== Default client property values
|
|
|
|
As noted previously, <<client-registration-auto-configuration-class, `ClientRegistrationAutoConfiguration`>> loads a _resource_ named *oauth2-clients-defaults.yml*,
|
|
which provides a set of default client property values for a number of _well-known_ Providers.
|
|
|
|
For example, the *authorization-uri*, *token-uri*, *user-info-uri* rarely change for a Provider and therefore it makes sense to
|
|
provide a set of defaults in order to reduce the configuration required by the user.
|
|
|
|
Below are the current set of default client property values:
|
|
|
|
.oauth2-clients-defaults.yml
|
|
[source,yaml]
|
|
----
|
|
security:
|
|
oauth2:
|
|
client:
|
|
google:
|
|
client-authentication-method: header
|
|
authorized-grant-type: authorization_code
|
|
redirect-uri: "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}"
|
|
scopes: openid, email, profile
|
|
authorization-uri: "https://accounts.google.com/o/oauth2/auth"
|
|
token-uri: "https://accounts.google.com/o/oauth2/token"
|
|
user-info-uri: "https://www.googleapis.com/oauth2/v3/userinfo"
|
|
user-info-converter: "org.springframework.security.oauth2.client.user.converter.UserInfoConverter"
|
|
client-name: Google
|
|
client-alias: google
|
|
github:
|
|
client-authentication-method: header
|
|
authorized-grant-type: authorization_code
|
|
redirect-uri: "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}"
|
|
scopes: user
|
|
authorization-uri: "https://github.com/login/oauth/authorize"
|
|
token-uri: "https://github.com/login/oauth/access_token"
|
|
user-info-uri: "https://api.github.com/user"
|
|
user-info-converter: "org.springframework.security.oauth2.client.user.converter.OAuth2UserConverter"
|
|
client-name: GitHub
|
|
client-alias: github
|
|
facebook:
|
|
client-authentication-method: form
|
|
authorized-grant-type: authorization_code
|
|
redirect-uri: "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}"
|
|
scopes: public_profile, email
|
|
authorization-uri: "https://www.facebook.com/v2.8/dialog/oauth"
|
|
token-uri: "https://graph.facebook.com/v2.8/oauth/access_token"
|
|
user-info-uri: "https://graph.facebook.com/me"
|
|
user-info-converter: "org.springframework.security.oauth2.client.user.converter.OAuth2UserConverter"
|
|
client-name: Facebook
|
|
client-alias: facebook
|
|
okta:
|
|
client-authentication-method: header
|
|
authorized-grant-type: authorization_code
|
|
redirect-uri: "{scheme}://{serverName}:{serverPort}{baseAuthorizeUri}/{clientAlias}"
|
|
scopes: openid, email, profile
|
|
user-info-converter: "org.springframework.security.oauth2.client.user.converter.UserInfoConverter"
|
|
client-name: Okta
|
|
client-alias: okta
|
|
----
|
|
|
|
= Appendix
|
|
'''
|
|
|
|
[[configure-non-spring-boot-app]]
|
|
== Configuring a _Non-Spring-Boot_ application
|
|
|
|
If you are not using Spring Boot for your application, you will not be able to leverage the auto-configuration features for OAuth 2.0 Login.
|
|
You will be required to provide your own _security configuration_ in order to enable OAuth 2.0 Login.
|
|
|
|
The following sample code demonstrates a minimal security configuration for enabling OAuth 2.0 Login.
|
|
|
|
Assuming we have a _properties file_ named *oauth2-clients.properties* on the _classpath_ and it specifies all the _required_ properties for an OAuth Client, specifically _"Google"_:
|
|
|
|
.oauth2-clients.properties
|
|
[source,properties]
|
|
----
|
|
security.oauth2.client.google.client-id=${client-id}
|
|
security.oauth2.client.google.client-secret=${client-secret}
|
|
security.oauth2.client.google.client-authentication-method=header
|
|
security.oauth2.client.google.authorized-grant-type=authorization_code
|
|
security.oauth2.client.google.redirect-uri=http://localhost:8080/oauth2/authorize/code/google
|
|
security.oauth2.client.google.scopes=openid,email,profile
|
|
security.oauth2.client.google.authorization-uri=https://accounts.google.com/o/oauth2/auth
|
|
security.oauth2.client.google.token-uri=https://accounts.google.com/o/oauth2/token
|
|
security.oauth2.client.google.user-info-uri=https://www.googleapis.com/oauth2/v3/userinfo
|
|
security.oauth2.client.google.user-info-converter=org.springframework.security.oauth2.client.user.converter.UserInfoConverter
|
|
security.oauth2.client.google.client-name=Google
|
|
security.oauth2.client.google.client-alias=google
|
|
----
|
|
|
|
The following _security configuration_ will enable OAuth 2.0 Login using _"Google"_ as the _Authentication Provider_:
|
|
|
|
[source,java]
|
|
----
|
|
@EnableWebSecurity
|
|
@PropertySource("classpath:oauth2-clients.properties")
|
|
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|
private Environment environment;
|
|
|
|
public SecurityConfig(Environment environment) {
|
|
this.environment = environment;
|
|
}
|
|
|
|
@Override
|
|
protected void configure(HttpSecurity http) throws Exception {
|
|
http
|
|
.authorizeRequests()
|
|
.anyRequest().authenticated()
|
|
.and()
|
|
.oauth2Login()
|
|
.clients(clientRegistrationRepository())
|
|
.userInfoEndpoint()
|
|
.userInfoTypeConverter(
|
|
new UserInfoConverter(),
|
|
new URI("https://www.googleapis.com/oauth2/v3/userinfo"));
|
|
}
|
|
|
|
@Bean
|
|
public ClientRegistrationRepository clientRegistrationRepository() {
|
|
List<ClientRegistration> clientRegistrations = Collections.singletonList(
|
|
clientRegistration("security.oauth2.client.google."));
|
|
|
|
return new InMemoryClientRegistrationRepository(clientRegistrations);
|
|
}
|
|
|
|
private ClientRegistration clientRegistration(String clientPropertyKey) {
|
|
String clientId = this.environment.getProperty(clientPropertyKey + "client-id");
|
|
String clientSecret = this.environment.getProperty(clientPropertyKey + "client-secret");
|
|
ClientAuthenticationMethod clientAuthenticationMethod = ClientAuthenticationMethod.valueOf(
|
|
this.environment.getProperty(clientPropertyKey + "client-authentication-method").toUpperCase());
|
|
AuthorizationGrantType authorizationGrantType = AuthorizationGrantType.valueOf(
|
|
this.environment.getProperty(clientPropertyKey + "authorized-grant-type").toUpperCase());
|
|
String redirectUri = this.environment.getProperty(clientPropertyKey + "redirect-uri");
|
|
String[] scopes = this.environment.getProperty(clientPropertyKey + "scopes").split(",");
|
|
String authorizationUri = this.environment.getProperty(clientPropertyKey + "authorization-uri");
|
|
String tokenUri = this.environment.getProperty(clientPropertyKey + "token-uri");
|
|
String userInfoUri = this.environment.getProperty(clientPropertyKey + "user-info-uri");
|
|
String clientName = this.environment.getProperty(clientPropertyKey + "client-name");
|
|
String clientAlias = this.environment.getProperty(clientPropertyKey + "client-alias");
|
|
|
|
return new ClientRegistration.Builder(clientId)
|
|
.clientSecret(clientSecret)
|
|
.clientAuthenticationMethod(clientAuthenticationMethod)
|
|
.authorizedGrantType(authorizationGrantType)
|
|
.redirectUri(redirectUri)
|
|
.scopes(scopes)
|
|
.authorizationUri(authorizationUri)
|
|
.tokenUri(tokenUri)
|
|
.userInfoUri(userInfoUri)
|
|
.clientName(clientName)
|
|
.clientAlias(clientAlias)
|
|
.build();
|
|
}
|
|
}
|
|
----
|