OAuth 2.0登录功能为应用程序提供了使用OAuth 2.0提供程序(例如GitHub)或OpenID Connect 1.0提供程序(例如Google)上的现有帐户登录应用程序的功能。 OAuth 2.0 Login实现了用例:“使用Google登录”或“使用GitHub登录”。
OAuth 2.0登录是使用授权代码授予实现的,如OAuth
2.0授权框架和OpenID Connect Core 1.0中所指定。
Spring Boot 2.x为OAuth 2.0登录带来了完整的自动配置功能。
本部分介绍如何使用Google作为身份验证提供程序配置OAuth 2.0登录示例,并介绍以下主题:
要使用Google的OAuth 2.0身份验证系统进行登录,您必须在Google API控制台中设置项目以获取OAuth 2.0凭据。
Google的OAuth 2.0身份验证实现符合OpenID
Connect1.0规范,并通过OpenID认证
按照OpenID Connect页面上的说明操作,从“设置OAuth 2.0”部分开始。
完成“获取OAuth 2.0凭据”说明后,您应该拥有一个新的OAuth客户端,其凭据包含客户端ID和客户端密钥。
重定向URI是应用程序中的路径,最终用户的用户代理在通过Google进行身份验证并在“同意”页面上授予了对OAuth客户端(在上一步中创建)的访问权限后重定向回的路径。
在“设置重定向URI”子部分中,确保将“授权重定向URI”字段设置为
http://localhost:8080/login/oauth2/code/google
默认重定向URI模板是{baseUrl}/login/oauth2/code/{registrationId}。
registrationId是ClientRegistration的唯一标识符。
既然您有一个新的OAuth客户端与Google,您需要配置应用程序以使用OAuth客户端进行身份验证流程
1.转到application.yml并设置以下配置
spring:
security:
oauth2:
client:
registration: 1
google: 2
client-id: google-client-id
client-secret: google-client-secret
Example 6.1. OAuth Client properties
例6.1 OAuth客户端属性
启动Spring Boot 2.x示例并转到http://localhost:8080 然后,您将被重定向到默认的自动生成的登录页面,该页面显示Google的链接。
点击Google链接,然后您将重定向到Google进行身份验证。
使用您的Google帐户凭据进行身份验证后,显示给您的下一页是“同意”屏幕。 “同意”屏幕会要求您允许或拒绝访问您之前创建的OAuth客户端。 单击“允许”以授权OAuth客户端访问您的电子邮件地址和基本配置文件信息。
此时,OAuth客户端从UserInfo端点检索您的电子邮件地址和基本配置文件信息,并建立经过身份验证的会话。
下表概述了Spring Boot 2.x OAuth客户端属性到ClientRegistration
属性的映射:
Spring Boot 2.x | ClientRegistration |
---|---|
spring.security.oauth2.client.registration.[registrationId] | registrationId |
spring.security.oauth2.client.registration.[registrationId].client-id | clientId |
spring.security.oauth2.client.registration.[registrationId].client-secret | clientSecret |
spring.security.oauth2.client.registration.[registrationId].client-authentication-method | clientAuthenticationMethod |
spring.security.oauth2.client.registration.[registrationId].authorization-grant-type | authorizationGrantType |
spring.security.oauth2.client.registration.[registrationId].redirect-uri | redirectUriTemplate |
spring.security.oauth2.client.registration.[registrationId].scope | scopes |
spring.security.oauth2.client.registration.[registrationId].client-name | clientName |
spring.security.oauth2.client.provider.[providerId].authorization-uri | providerDetails.authorizationUri |
spring.security.oauth2.client.provider.[providerId].token-uri | providerDetails.tokenUri |
spring.security.oauth2.client.provider.[providerId].jwk-set-uri | providerDetails.jwkSetUri |
spring.security.oauth2.client.provider.[providerId].user-info-uri | providerDetails.userInfoEndpoint.uri |
spring.security.oauth2.client.provider.[providerId].user-info-authentication-method | providerDetails.userInfoEndpoint.authenticationMethod |
spring.security.oauth2.client.provider.[providerId].userNameAttribute | providerDetails.userInfoEndpoint.userNameAttributeName |
CommonOAuth2Provider为众多知名提供商预定义了一组默认客户端属性:Google,GitHub,Facebook和Okta。
例如,authorization-uri,token-uri和user-info-uri对于Provider不会经常更改。 因此,提供默认值以减少所需配置是有意义的。
如前所述,当我们配置Google客户端时,只需要client-id和client-secret属性。
以下清单显示了一个示例:
spring:
security:
oauth2:
client:
registration:
google:
client-id: google-client-id
client-secret: google-client-secret
客户端属性的自动默认无缝地在这里工作,因为registrationId(google)与CommonOAuth2Provider中的GOOGLE枚举(不区分大小写)匹配。
对于您可能希望指定其他registrationId(例如google-login)的情况,您仍然可以通过配置provider属性来利用客户端属性的自动默认。
以下清单显示了一个示例:
spring:
security:
oauth2:
client:
registration:
google-login: 1
provider: google 2
client-id: google-client-id
client-secret: google-client-secret
- 1registrationId设置为google-login。
- 2provider属性设置为google,它将利用CommonOAuth2Provider.GOOGLE.getBuilder()中设置的客户端属性的自动默认。
有些OAuth 2.0提供程序支持多租户,这会导致每个租户(或子域)使用不同的协议端点。
例如,向Okta注册的OAuth客户端被分配给特定的子域并拥有自己的协议端点。
对于这些情况,Spring Boot 2.x提供了以下用于配置自定义提供程序属性的基本属性:
spring.security.oauth2.client.provider.[providerId]
以下清单显示了一个示例:
spring:
security:
oauth2:
client:
registration:
okta:
client-id: okta-client-id
client-secret: okta-client-secret
provider:
okta: 1
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
spring.security.oauth2.client.provider.okta
)允许自定义配置协议端点位置。OAuth客户端支持的Spring Boot 2.x自动配置类是OAuth2ClientAutoConfiguration。
它执行以下任务:
从配置的OAuth客户端属性注册由ClientRegistration组成的ClientRegistrationRepository @Bean。
提供WebSecurityConfigurerAdapter @Configuration并通过httpSecurity.oauth2Login()启用OAuth 2.0登录。
如果您需要根据具体要求覆盖自动配置,可以通过以下方式执行此操作:
以下示例显示如何注册ClientRegistrationRepository @Bean:
@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.BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate("{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();
}
}
以下示例说明如何使用@EnableWebSecurity提供WebSecurityConfigurerAdapter并通过httpSecurity.oauth2Login()启用OAuth 2.0登录:
@EnableWebSecurity
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
以下示例说明如何通过注册ClientRegistrationRepository @Bean并提供WebSecurityConfigurerAdapter来完全覆盖自动配置。
@Configuration
public class OAuth2LoginConfig {
@EnableWebSecurity
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
@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.BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUriTemplate("{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();
}
}
如果您无法使用Spring Boot 2.x并且想要在CommonOAuth2Provider中配置一个预定义的提供程序(例如,Google),请应用以下配置:
@Configuration
public class OAuth2LoginConfig {
@EnableWebSecurity
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
@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();
}
}
以下附加资源描述了高级配置选项: