使用 Spring 安全 OAuth2 刷新令牌为空
refresh token is null using Spring Security OAuth2
我正在尝试使用 Spring 安全性来集成 Google OAuth 2。一切正常,但 refresh_token 为空。
这是我的配置:
@Bean
public OAuth2ProtectedResourceDetails googleOAuth2Details() {
AuthorizationCodeResourceDetails googleOAuth2Details = new AuthorizationCodeResourceDetails();
googleOAuth2Details.setAuthenticationScheme(form);
googleOAuth2Details.setClientAuthenticationScheme(form);
googleOAuth2Details.setClientId(googleClientId);
googleOAuth2Details.setClientSecret(googleClientSecret);
googleOAuth2Details.setUserAuthorizationUri(googleOAuthUri);
googleOAuth2Details.setAccessTokenUri(googleTokenUrl);
googleOAuth2Details.setScope(asList("openid","email"));
return googleOAuth2Details;
}
我读到要获得 refresh_token,access_type 必须是 "offline"。但是在Spring里面怎么设置呢?
恐怕 'access_type' 参数不在 OAUTH2 Authorization (RFC 6749) 的范围内并且 Spring 没有它默认,需要手动添加。不幸的是,我现在不知道正确的方法,但我认为“OAuth2RestTemplate#getAccessToken”是开始调查的好地方。
此外 this post 可能对您有用。
试试这个:您可以将参数 "hard-configured" 添加到 googleOAuthUri
,因此:
googleOAuthUri = googleOAuthUri + "?access_type=offline";
googleOAuth2Details.setUserAuthorizationUri(googleOAuthUri);
希望 Spring 在添加其他参数时做正确的事。
另请注意,refresh_token
仅在用户首次授予您的客户端访问权限时返回。后续授权请求不会产生新的 refresh_token
,因为假定您的客户端已存储第一个请求中的内容。
您可以创建 OAuth2AuthorizationRequestResolver
的自定义实现并添加 additionalParameters(..)
和 "access_type"="offline"
,如 Spring security documentation 所述。
@EnableWebSecurity
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
private final ClientRegistrationRepository clientRegistrationRepository;
public OAuth2LoginSecurityConfig(ClientRegistrationRepository clientRegistrationRepository) {
this.clientRegistrationRepository = clientRegistrationRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.authorizationEndpoint()
.authorizationRequestResolver(
new CustomAuthorizationRequestResolver(
this.clientRegistrationRepository));
}
}
public class CustomAuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
private final OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver;
public CustomAuthorizationRequestResolver(ClientRegistrationRepository clientRegistrationRepository) {
this.defaultAuthorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
final OAuth2AuthorizationRequest authorizationRequest = this.defaultAuthorizationRequestResolver.resolve(request);
return authorizationRequest != null ? customAuthorizationRequest(authorizationRequest) : null;
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId) {
final OAuth2AuthorizationRequest authorizationRequest = this.defaultAuthorizationRequestResolver.resolve(request, clientRegistrationId);
return authorizationRequest != null ? customAuthorizationRequest(authorizationRequest) : null;
}
private OAuth2AuthorizationRequest customAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {
Map<String, Object> additionalParameters = new LinkedHashMap<>(authorizationRequest.getAdditionalParameters());
additionalParameters.put("access_type", "offline");
return OAuth2AuthorizationRequest.from(authorizationRequest)
.additionalParameters(additionalParameters)
.build();
}
}
我正在尝试使用 Spring 安全性来集成 Google OAuth 2。一切正常,但 refresh_token 为空。
这是我的配置:
@Bean public OAuth2ProtectedResourceDetails googleOAuth2Details() { AuthorizationCodeResourceDetails googleOAuth2Details = new AuthorizationCodeResourceDetails(); googleOAuth2Details.setAuthenticationScheme(form); googleOAuth2Details.setClientAuthenticationScheme(form); googleOAuth2Details.setClientId(googleClientId); googleOAuth2Details.setClientSecret(googleClientSecret); googleOAuth2Details.setUserAuthorizationUri(googleOAuthUri); googleOAuth2Details.setAccessTokenUri(googleTokenUrl); googleOAuth2Details.setScope(asList("openid","email")); return googleOAuth2Details; }
我读到要获得 refresh_token,access_type 必须是 "offline"。但是在Spring里面怎么设置呢?
恐怕 'access_type' 参数不在 OAUTH2 Authorization (RFC 6749) 的范围内并且 Spring 没有它默认,需要手动添加。不幸的是,我现在不知道正确的方法,但我认为“OAuth2RestTemplate#getAccessToken”是开始调查的好地方。
此外 this post 可能对您有用。
试试这个:您可以将参数 "hard-configured" 添加到 googleOAuthUri
,因此:
googleOAuthUri = googleOAuthUri + "?access_type=offline";
googleOAuth2Details.setUserAuthorizationUri(googleOAuthUri);
希望 Spring 在添加其他参数时做正确的事。
另请注意,refresh_token
仅在用户首次授予您的客户端访问权限时返回。后续授权请求不会产生新的 refresh_token
,因为假定您的客户端已存储第一个请求中的内容。
您可以创建 OAuth2AuthorizationRequestResolver
的自定义实现并添加 additionalParameters(..)
和 "access_type"="offline"
,如 Spring security documentation 所述。
@EnableWebSecurity
public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
private final ClientRegistrationRepository clientRegistrationRepository;
public OAuth2LoginSecurityConfig(ClientRegistrationRepository clientRegistrationRepository) {
this.clientRegistrationRepository = clientRegistrationRepository;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.authorizationEndpoint()
.authorizationRequestResolver(
new CustomAuthorizationRequestResolver(
this.clientRegistrationRepository));
}
}
public class CustomAuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
private final OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver;
public CustomAuthorizationRequestResolver(ClientRegistrationRepository clientRegistrationRepository) {
this.defaultAuthorizationRequestResolver = new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
final OAuth2AuthorizationRequest authorizationRequest = this.defaultAuthorizationRequestResolver.resolve(request);
return authorizationRequest != null ? customAuthorizationRequest(authorizationRequest) : null;
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId) {
final OAuth2AuthorizationRequest authorizationRequest = this.defaultAuthorizationRequestResolver.resolve(request, clientRegistrationId);
return authorizationRequest != null ? customAuthorizationRequest(authorizationRequest) : null;
}
private OAuth2AuthorizationRequest customAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {
Map<String, Object> additionalParameters = new LinkedHashMap<>(authorizationRequest.getAdditionalParameters());
additionalParameters.put("access_type", "offline");
return OAuth2AuthorizationRequest.from(authorizationRequest)
.additionalParameters(additionalParameters)
.build();
}
}