123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- = 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();
- }
- }
- ----
|