春季安全OAuth2(谷歌)网络应用程序在重定向循环 [英] Spring Security OAuth2 (google) web app in redirect loop
问题描述
我正在尝试构建Spring MVC应用程序,并使用Spring Security OAuth2来保护它,而提供者是Google。我能够在没有安全性和表单登录的情况下运行网络应用程序。不过,我无法使用谷歌的OAuth工作。谷歌应用程序设置是好的,因为我可以让回调等与非Spring安全应用程序一起工作。
我的安全配置如下
<?xml version =1.0encoding =UTF-8?>
< b:beans xmlns:sec =http://www.springframework.org/schema/security
xmlns:b =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation =http://www.springframework.org/schema/beans http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/弹簧security.xsd>
< sec:http-basic />
< sec:logout />
< sec:anonymous enabled =false/>
< sec:intercept-url pattern =/ **access =isFullyAuthenticated()/>
< sec:custom = filter ref =oauth2ClientContextFilterafter =EXCEPTION_TRANSLATION_FILTER/>
< sec:custom = filter ref =googleAuthenticationFilterbefore =FILTER_SECURITY_INTERCEPTOR/>
< / sec:http>
< b:bean id =clientAuthenticationEntryPointclass =org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint/>
< sec:认证提供者>
< sec:用户服务>
< sec:user name =userpassword =passwordauthorities =DOMAIN_USER/>
< / sec:用户服务>
< / sec:authentication-provider>
< / sec:authentication-manager>
< / b:beans>
受OAuth2保护的资源如下
@Configuration
@ EnableOAuth2Client
类ResourceConfiguration {
@Autowired
private环境env;
@Resource
@Qualifier(accessTokenRequest)
private AccessTokenRequest accessTokenRequest;
@Bean
public OAuth2ProtectedResourceDetails googleResource(){
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId(google-app);
details.setClientId(env.getProperty(google.client.id));
details.setClientSecret(env.getProperty(google.client.secret));
details.setAccessTokenUri(env.getProperty(google.accessTokenUri));
details.setUserAuthorizationUri(env.getProperty(google.userAuthorizationUri));
details.setTokenName(env.getProperty(google.authorization.code));
String commaSeparatedScopes = env.getProperty(google.auth.scope);
details.setScope(parseScopes(commaSeparatedScopes));
details.setPreEstablishedRedirectUri(env.getProperty(google.preestablished.redirect.url));
details.setUseCurrentUri(false);
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
返回细节;
}
私人列表< String> parseScopes(String commaSeparatedScopes){
List< String> scopes = newArrayList();
Collections.addAll(scopes,commaSeparatedScopes.split(,));
返回范围;
}
@Bean
public OAuth2RestTemplate googleRestTemplate(){
return new OAuth2RestTemplate(googleResource(),new DefaultOAuth2ClientContext(accessTokenRequest));
$ b @Bean
public AbstractAuthenticationProcessingFilter googleAuthenticationFilter(){
返回新的GoogleOAuthentication2Filter(新的GoogleAppsDomainAuthenticationManager(),googleRestTemplate(),https://accounts.google .com / o / oauth2 / auth,http:// localhost:9000);
我写的自定义验证过滤器抛出重定向异常获得OAuth2授权如下所示:
@Override
public Authentication attemptAuthentication(HttpServletRequest请求,HttpServletResponse响应) throws AuthenticationException,IOException,ServletException {
try {
logger.info(OAuth2 Filter Triggered !! for path {} {},request.getRequestURI(),request.getRequestURL()。toString() );
logger.info(OAuth2 Filter hashCode {} request hashCode {},this.hashCode(),request.hashCode());
String code = request.getParameter(code);
身份验证身份验证= SecurityContextHolder.getContext()。getAuthentication();
logger.info(Code is {} and authentication is {},code,authentication == null?null:authentication.isAuthenticated());
//未经过认证
if(requiresRedirectForAuthentication(code)){
URI authURI = new URI(googleAuthorizationUrl);
logger.info(发布到{}以触发auth重定向,authURI);
String url =https://www.googleapis.com/oauth2/v2/userinfo?access_token=+ oauth2RestTemplate.getAccessToken();
logger.info(从{}获取个人资料数据,url);
//应抛出RedirectRequiredException
oauth2RestTemplate.getForEntity(url,GoogleProfile.class);
//认证正在进行中
返回null;
} else {
logger.info(OAuth callback received);
//获取用户配置文件并准备身份验证令牌对象。
String url =https://www.googleapis.com/oauth2/v2/userinfo?access_token=+ oauth2RestTemplate.getAccessToken();
logger.info(从{}获取个人资料数据,url);
ResponseEntity< GoogleProfile> forEntity = oauth2RestTemplate.getForEntity(url,GoogleProfile.class);
GoogleProfile配置文件= forEntity.getBody();
CustomOAuth2AuthenticationToken authenticationToken = getOAuth2Token(profile.getEmail());
authenticationToken.setAuthenticated(false);
Authentication authenticate = getAuthenticationManager()。authenticate(authenticationToken);
logger.info(Final authentication is {},authenticate == null?null:authenticate.isAuthenticated());
return authenticate;
}
} catch(URISyntaxException e){
Throwables.propagate(e);
}
返回null;
}
Spring web应用程序的过滤器链序列如下所示
$ b $
osbceServletRegistrationBean - 映射servlet:'dispatcherServlet'到[/]
osbceFilterRegistrationBean - 映射过滤器:'metricFilter'到:[/ *]
osbceFilterRegistrationBean - 映射过滤器:'oauth2ClientContextFilter'至:[/ *]
osbceFilterRegistrationBean - 映射过滤器:'googleOAuthFilter'至:[/ *]
osbceFilterRegistrationBean - 映射过滤器: 'org.springframework.security.filterChainProxy'to:[/ *]
osbceFilterRegistrationBean - 映射过滤器:'org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0'到:[/ *]
osbceFilterRegistrationBean映射过滤器'hiddenHttpMethodFilter'到:[/ *]
osbceFilterRegistrationBean - 映射过滤器:'applicationContextIdFilter'到:[/ *]
osbceFilterRegistrationBean - Mapp ing过滤器:'webRequestLoggingFilter':[/ *]
重定向到Google工作正常,过滤器的回调和认证成功。然而之后,请求会产生重定向,并再次调用过滤器(请求相同,我已经检查过hasCode)。在第二次调用时,SecurityContext中的身份验证为空。作为第一次身份验证调用的一部分,身份验证对象已填充到安全上下文中,为何它会消失?
我正在和Spring Security第一次合作,所以可能会犯新手错误。
Spring Security配置和过滤器我终于能够得到这个工作。我必须做出几个重要的改变。我使用了一个标准的Spring OAuth2过滤器( org.springframework.security。)。 oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter
)而不是我正在使用的自定义过滤器。
/ googleLogin
并添加了一个认证入口点,该认证入口点在认证失败时重定向到此URL。 >整体流程如下: - 浏览器访问
/
和当上下文不匹配时,请求将通过OAuth2ClientContextFilter
和OAuth2ClientAuthenticationProcessingFilter
进行传递。配置的登录路径是/ googleLogin
- 安全拦截器
FilterSecurityInterceptor
检测到用户是匿名的并抛出一个拒绝访问的异常。 - Spring安全的
ExceptionTranslationFilter
捕获拒绝访问异常并询问配置身份验证入口点来处理它发出重定向到/ googleLogin
。 - 对于请求
/ googleLogin
,过滤器OAuth2AuthenticationProcessingFilter
会尝试访问Google受保护的资源,并抛出UserRedirectRequiredException
通过OAuth2ClientContextFilter
转换为Google的HTTP重定向(使用OAuth2详细信息)。 - 成功通过Google验证后,浏览器被重定向回到
/ googleLogin
与OAuth代码。过滤器OAuth2AuthenticationProcessingFilter
处理这个并创建一个认证
对象并更新SecurityContext
。 - 此时,用户完全通过身份验证,并由
OAuth2AuthenticationProcessingFilter
发出重定向。 -
FilterSecurityInterceptor
允许请求继续进行,因为SecurityContext
包含一个认证对象
,这是经过认证的。 最后,使用诸如
isFullyAuthenticated()
或类似表达式的表达式保护的应用程序页面被呈现。安全上下文xml如下:
< sec:http use-expressions =trueentry-point-ref =clientAuthenticationEntryPoint>
< sec:http-basic />
< sec:logout />
< sec:anonymous enabled =false/>
< sec:intercept-url pattern =/ **access =isFullyAuthenticated()/>
<! - 这是关键部分,接线非常重要 - >
<! -
这些过滤器执行的顺序非常重要。 oauth2ClientContextFilter必须在
之前被调用oAuth2AuthenticationProcessingFilter,这是因为当需要重定向到Google时,oAuth2AuthenticationProcessingFilter
抛出一个UserRedirectException,oauth2ClientContextFilter处理并生成一个重定向请求给Google。
随后,来自Google的响应由oAuth2AuthenticationProcessingFilter处理,以填充
Authentication对象并存储在SecurityContext
- >
< sec:custom = filter ref =oauth2ClientContextFilterafter =EXCEPTION_TRANSLATION_FILTER/>
< sec:custom = filter ref =oAuth2AuthenticationProcessingFilterbefore =FILTER_SECURITY_INTERCEPTOR/>
< / sec:http>
< b:bean id =oAuth2AuthenticationProcessingFilterclass =org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter>
< b:属性名称=restTemplateref =googleRestTemplate/>
< b:属性名称=tokenServicesref =tokenServices/>
< / b:bean>
<! - -
这些标记类大多是Spring类的一个克隆,但其结构已被修改,以便可以处理来自Google的响应
。
- >
< b:bean id =tokenServicesclass =com.rst.oauth2.google.security.GoogleTokenServices>
< b:属性名称=checkTokenEndpointUrlvalue =https://www.googleapis.com/oauth2/v1/tokeninfo/>
< b:property name =clientIdvalue =$ {google.client.id}/>
< b:属性名称=accessTokenConverter>
< b:bean class =com.rst.oauth2.google.security.GoogleAccessTokenConverter>
< b:属性名称=userTokenConverter>
< b:bean class =com.rst.oauth2.google.security.DefaultUserAuthenticationConverter/>
< / b:属性>
< / b:bean>
< / b:属性>
< / b:bean>
<! - -
此认证入口点用于将所有未经身份验证或未授权的会话定向到
/ googleLogin URL,然后由oAuth2AuthenticationProcessingFilter拦截从
Google触发认证。
- >
< b:bean id =clientAuthenticationEntryPointclass =org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint>
< b:属性名称=loginFormUrlvalue =/ googleLogin/>
< / b:bean>
另外,OAuth2资源的Java Config如下所示:
@Configuration
@ EnableOAuth2Client
class OAuth2SecurityConfiguration {
@Autowired
private Environment env;
@Resource
@Qualifier(accessTokenRequest)
private AccessTokenRequest accessTokenRequest;
@Bean
@Scope(session)
public OAuth2ProtectedResourceDetails googleResource(){
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId(google-oauth-client);
details.setClientId(env.getProperty(google.client.id));
details.setClientSecret(env.getProperty(google.client.secret));
details.setAccessTokenUri(env.getProperty(google.accessTokenUri));
details.setUserAuthorizationUri(env.getProperty(google.userAuthorizationUri));
details.setTokenName(env.getProperty(google.authorization.code));
String commaSeparatedScopes = env.getProperty(google.auth.scope);
details.setScope(parseScopes(commaSeparatedScopes));
details.setPreEstablishedRedirectUri(env.getProperty(google.preestablished.redirect.url));
details.setUseCurrentUri(false);
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
返回细节;
}
私人列表< String> parseScopes(String commaSeparatedScopes){
List< String> scopes = newArrayList();
Collections.addAll(scopes,commaSeparatedScopes.split(,));
返回范围;
$ b $Bean
@Scope(value =session,proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2RestTemplate googleRestTemplate(){
return new OAuth2RestTemplate(googleResource(),新的DefaultOAuth2ClientContext(accessTokenRequest));
$ / code>
我不得不重写一些Spring类,来自Google的令牌格式与Spring预期的格式不匹配。所以这里需要一些定制手工。
I am trying to build a Spring MVC application and securing it with Spring Security OAuth2 and the provider is Google. I was able to get the web app working without security and with form login. However I am not able to get OAuth with google to work. Google app setup is fine as I can get the call backs etc to work with a non Spring Security app.
My security config is as follows
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns:sec="http://www.springframework.org/schema/security"
xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<sec:http use-expressions="true" entry-point-ref="clientAuthenticationEntryPoint">
<sec:http-basic/>
<sec:logout/>
<sec:anonymous enabled="false"/>
<sec:intercept-url pattern="/**" access="isFullyAuthenticated()"/>
<sec:custom-filter ref="oauth2ClientContextFilter" after="EXCEPTION_TRANSLATION_FILTER"/>
<sec:custom-filter ref="googleAuthenticationFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
</sec:http>
<b:bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint"/>
<sec:authentication-manager alias="alternateAuthenticationManager">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="user" password="password" authorities="DOMAIN_USER"/>
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</b:beans>
The OAuth2 protected resource is as follows
@Configuration
@EnableOAuth2Client
class ResourceConfiguration {
@Autowired
private Environment env;
@Resource
@Qualifier("accessTokenRequest")
private AccessTokenRequest accessTokenRequest;
@Bean
public OAuth2ProtectedResourceDetails googleResource() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("google-app");
details.setClientId(env.getProperty("google.client.id"));
details.setClientSecret(env.getProperty("google.client.secret"));
details.setAccessTokenUri(env.getProperty("google.accessTokenUri"));
details.setUserAuthorizationUri(env.getProperty("google.userAuthorizationUri"));
details.setTokenName(env.getProperty("google.authorization.code"));
String commaSeparatedScopes = env.getProperty("google.auth.scope");
details.setScope(parseScopes(commaSeparatedScopes));
details.setPreEstablishedRedirectUri(env.getProperty("google.preestablished.redirect.url"));
details.setUseCurrentUri(false);
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
private List<String> parseScopes(String commaSeparatedScopes) {
List<String> scopes = newArrayList();
Collections.addAll(scopes, commaSeparatedScopes.split(","));
return scopes;
}
@Bean
public OAuth2RestTemplate googleRestTemplate() {
return new OAuth2RestTemplate(googleResource(), new DefaultOAuth2ClientContext(accessTokenRequest));
}
@Bean
public AbstractAuthenticationProcessingFilter googleAuthenticationFilter() {
return new GoogleOAuthentication2Filter(new GoogleAppsDomainAuthenticationManager(), googleRestTemplate(), "https://accounts.google.com/o/oauth2/auth", "http://localhost:9000");
}
}
The custom authentication filter which I have written to throw a Redirect exception to get the OAuth2 authorisation is as follows
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
try {
logger.info("OAuth2 Filter Triggered!! for path {} {}", request.getRequestURI(), request.getRequestURL().toString());
logger.info("OAuth2 Filter hashCode {} request hashCode {}", this.hashCode(), request.hashCode());
String code = request.getParameter("code");
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
logger.info("Code is {} and authentication is {}", code, authentication == null ? null : authentication.isAuthenticated());
// not authenticated
if (requiresRedirectForAuthentication(code)) {
URI authURI = new URI(googleAuthorizationUrl);
logger.info("Posting to {} to trigger auth redirect", authURI);
String url = "https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + oauth2RestTemplate.getAccessToken();
logger.info("Getting profile data from {}", url);
// Should throw RedirectRequiredException
oauth2RestTemplate.getForEntity(url, GoogleProfile.class);
// authentication in progress
return null;
} else {
logger.info("OAuth callback received");
// get user profile and prepare the authentication token object.
String url = "https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + oauth2RestTemplate.getAccessToken();
logger.info("Getting profile data from {}", url);
ResponseEntity<GoogleProfile> forEntity = oauth2RestTemplate.getForEntity(url, GoogleProfile.class);
GoogleProfile profile = forEntity.getBody();
CustomOAuth2AuthenticationToken authenticationToken = getOAuth2Token(profile.getEmail());
authenticationToken.setAuthenticated(false);
Authentication authenticate = getAuthenticationManager().authenticate(authenticationToken);
logger.info("Final authentication is {}", authenticate == null ? null : authenticate.isAuthenticated());
return authenticate;
}
} catch (URISyntaxException e) {
Throwables.propagate(e);
}
return null;
}
The filter chain sequence from the Spring web app is as follows
o.s.b.c.e.ServletRegistrationBean - Mapping servlet: 'dispatcherServlet' to [/]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'metricFilter' to: [/*]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'oauth2ClientContextFilter' to: [/*]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'googleOAuthFilter' to: [/*]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'org.springframework.security.filterChainProxy' to: [/*]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0' to: [/*]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'applicationContextIdFilter' to: [/*]
o.s.b.c.e.FilterRegistrationBean - Mapping filter: 'webRequestLoggingFilter' to: [/*]
The redirect to Google works fine and I get the callback to the filter and the authentication is successful. However after that, the request results in a redirect and it invokes the filter again (the request is the same, I have checked the hasCode). On the second call the authentication in the SecurityContext is null. As part of the first authentication call the Authentication object was populated in the security context, so why does it disappear? I am working with Spring Security for the first time so may have made newbie mistake.
After playing around with Spring Security configuration and the filters I was finally able to get this working. I had to make couple of important changes
- I used a standard Spring OAuth2 filter (
org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter
) instead of the custom filter I was using. - Change the intercept URL of the authentication filter to be
/googleLogin
and added an authentication entry point which redirects to this URL on authentication failure.
Overall the flow is as follows
- Browser accesses
/
and the request passes through theOAuth2ClientContextFilter
andOAuth2ClientAuthenticationProcessingFilter
as the context does not match. The configured context path for login is/googleLogin
- The security interceptor
FilterSecurityInterceptor
detects that the the user is anonymous and throws an access denied exception. - Spring security's
ExceptionTranslationFilter
catches the access denied exception and asks the configured authentication entry point to handle it which issues a redirect to/googleLogin
. - For the request
/googleLogin
, the filterOAuth2AuthenticationProcessingFilter
tries to access the Google protected resource and anUserRedirectRequiredException
is thrown which is translated into a HTTP redirect to Google (with the OAuth2 details) byOAuth2ClientContextFilter
. - On successful authentication from Google the browser is redirected back to
/googleLogin
with the OAuth code. The filterOAuth2AuthenticationProcessingFilter
handles this and creates anAuthentication
object and updates theSecurityContext
. - At this point the user is fully authenticated and redirect to / is issued by the
OAuth2AuthenticationProcessingFilter
. FilterSecurityInterceptor
allows the request to proceed as theSecurityContext
contains anAuthentication object
which is authenticated.- Finally the application page which is secured using an expression like
isFullyAuthenticated()
or similar is rendered.
The security context xml is as follows:
<sec:http use-expressions="true" entry-point-ref="clientAuthenticationEntryPoint">
<sec:http-basic/>
<sec:logout/>
<sec:anonymous enabled="false"/>
<sec:intercept-url pattern="/**" access="isFullyAuthenticated()"/>
<!-- This is the crucial part and the wiring is very important -->
<!--
The order in which these filters execute are very important. oauth2ClientContextFilter must be invoked before
oAuth2AuthenticationProcessingFilter, that's because when a redirect to Google is required, oAuth2AuthenticationProcessingFilter
throws a UserRedirectException which the oauth2ClientContextFilter handles and generates a redirect request to Google.
Subsequently the response from Google is handled by the oAuth2AuthenticationProcessingFilter to populate the
Authentication object and stored in the SecurityContext
-->
<sec:custom-filter ref="oauth2ClientContextFilter" after="EXCEPTION_TRANSLATION_FILTER"/>
<sec:custom-filter ref="oAuth2AuthenticationProcessingFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
</sec:http>
<b:bean id="oAuth2AuthenticationProcessingFilter" class="org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter">
<b:constructor-arg name="defaultFilterProcessesUrl" value="/googleLogin"/>
<b:property name="restTemplate" ref="googleRestTemplate"/>
<b:property name="tokenServices" ref="tokenServices"/>
</b:bean>
<!--
These token classes are mostly a clone of the Spring classes but have the structure modified so that the response
from Google can be handled.
-->
<b:bean id="tokenServices" class="com.rst.oauth2.google.security.GoogleTokenServices">
<b:property name="checkTokenEndpointUrl" value="https://www.googleapis.com/oauth2/v1/tokeninfo"/>
<b:property name="clientId" value="${google.client.id}"/>
<b:property name="clientSecret" value="${google.client.secret}"/>
<b:property name="accessTokenConverter">
<b:bean class="com.rst.oauth2.google.security.GoogleAccessTokenConverter">
<b:property name="userTokenConverter">
<b:bean class="com.rst.oauth2.google.security.DefaultUserAuthenticationConverter"/>
</b:property>
</b:bean>
</b:property>
</b:bean>
<!--
This authentication entry point is used for all the unauthenticated or unauthorised sessions to be directed to the
/googleLogin URL which is then intercepted by the oAuth2AuthenticationProcessingFilter to trigger authentication from
Google.
-->
<b:bean id="clientAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<b:property name="loginFormUrl" value="/googleLogin"/>
</b:bean>
Also the Java Config for the OAuth2 resources is as follows:
@Configuration
@EnableOAuth2Client
class OAuth2SecurityConfiguration {
@Autowired
private Environment env;
@Resource
@Qualifier("accessTokenRequest")
private AccessTokenRequest accessTokenRequest;
@Bean
@Scope("session")
public OAuth2ProtectedResourceDetails googleResource() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setId("google-oauth-client");
details.setClientId(env.getProperty("google.client.id"));
details.setClientSecret(env.getProperty("google.client.secret"));
details.setAccessTokenUri(env.getProperty("google.accessTokenUri"));
details.setUserAuthorizationUri(env.getProperty("google.userAuthorizationUri"));
details.setTokenName(env.getProperty("google.authorization.code"));
String commaSeparatedScopes = env.getProperty("google.auth.scope");
details.setScope(parseScopes(commaSeparatedScopes));
details.setPreEstablishedRedirectUri(env.getProperty("google.preestablished.redirect.url"));
details.setUseCurrentUri(false);
details.setAuthenticationScheme(AuthenticationScheme.query);
details.setClientAuthenticationScheme(AuthenticationScheme.form);
return details;
}
private List<String> parseScopes(String commaSeparatedScopes) {
List<String> scopes = newArrayList();
Collections.addAll(scopes, commaSeparatedScopes.split(","));
return scopes;
}
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public OAuth2RestTemplate googleRestTemplate() {
return new OAuth2RestTemplate(googleResource(), new DefaultOAuth2ClientContext(accessTokenRequest));
}
}
I had to override some of the Spring classes as the format of the token from Google and the one expected by Spring don't match. So there is some custom handiwork required there.
这篇关于春季安全OAuth2(谷歌)网络应用程序在重定向循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!