Refresh Token in tut-spring-security-and-angular-js/oauth2-vanilla/
lthomassin opened this issue · comments
Dear all,
I have question regarding the code of this tutorial tut-spring-security-and-angular-js/oauth2-vanilla/
If in the file application.properties of the project authserver I add these lines:
security.oauth2.client.accessTokenValiditySeconds: 10
security.oauth2.client.refreshTokenValiditySeconds: 60
security.oauth2.client.supportRefreshToken: true
After a normal login. I perform some browser refresh during 10 seconds. I have the normal "Hello World" message but after the token expiration, I have an HTTP 401 error. It's seems the refreshToken is not used by the zuul gateway to obtain a new access token.
If it's possible to do that direclty with the zuul gateway?
Thanks for your help.
This used to work. There was a change in Spring Boot (1.4 I think) where it stopped creating an OAuth2RestTemplate
bean by default. You have to create it yourself, i.e. in the UI app:
@Bean
protected OAuth2RestTemplate OAuth2RestTemplate(
OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
return new OAuth2RestTemplate(resource, context);
}
then it gets injected into the OAuth2TokenRelayFilter
and can be used to refresh tokens (until the refresh token expires).
@dsyer I can't solve the problem by adding above snippet. I'm currently using with spring-boot version 1.5.4.RELAEASE . The error log was ....
org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getRedirectForAuthorization(AuthorizationCodeAccessTokenProvider.java:359)
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:205)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:148)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:121)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:105)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:648)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:128)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:531)
at org.springframework.web.client.RestTemplate$$FastClassBySpringCGLIB$$aa4e9ed0.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
at org.springframework.cloud.netflix.metrics.RestTemplateUrlTemplateCapturingAspect.captureUrlTemplate(RestTemplateUrlTemplateCapturingAspect.java:33)
I'm working with JDBC TokenStore with @EnableZuulProxy
and @EnableOAuth2Sso
How didn't you test it? Where did the log come from?
I also recently tried the solution above that creates the OAuth2RestTemplate
bean. And I am having a similar issue with the UserRedirectRequiredException
exception. Basically it appears that it is trying to get a new access token; not refresh an existing one.
I'm not very familiar with the logic of Spring OAuth2, but I did debug down to AccessTokenProviderChain::obtainAccessToken
. There is a conditional where request.getExistingToken()
needs to be non-null to attempt to refresh. However, it is null.
We are using our own custom ResourceServerTokenServices
implementation and running Spring Boot 1.5.7.
@dsyer
I'm also experiencing
{"error":"invalid_token","error_description":"Invalid access token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJwZXRlckBob3RtYWlsLmNvbSIsInNjb3BlIjpbIm9wZW5pZCJdLCJleHAiOjE1MTYxNDg4MTYsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJST0xFX0FDVFVBVE9SIl0sImp0aSI6IjdmNTY3MDljLTM1ZTAtNGNjYy04NzdkLTcxNTkxYjE5NjRjNCIsInRlbmFudCI6W3sibmFtZSI6ImxpZGwiLCJjaGFubmVsIjoiaHliX2ZyX0JFIn0seyJuYW1lIjoibGlkbCIsImNoYW5uZWwiOiJoeWJfbmxfTkwifSx7Im5hbWUiOiJsaWRsIiwiY2hhbm5lbCI6Im1nbV9kZV9ERSJ9LHsibmFtZSI6ImxpZGwiLCJjaGFubmVsIjoiaHliX25sX0JFIn1dLCJjbGllbnRfaWQiOiJhcGktZ2F0ZXdheSJ9.VRsVIiw16aYnj78sFhgXPsqfkY1szmS-DVeog03Iolp0cAitYQkjbAIP83-qtSsJ0waQmyE2dGy9mW2JKPAMTWuAy3dh8YHgm7RzLfoo08NFOhkCc0R5m5l7rty5fD7L04uDwalI05j7oYI4Ly0J0BwP8mG6aSRqLwxt3zip-0W_DdkUdC7okbqKe-QF-CyZ4rmLSlweBQG5walPVwZC78l-21jnFEe-LuLLqFDkhgIy5uEH87h_pwQtC87IEefm78R74P7HWna8Ma7K2cbxdKUPHKqNo-jghw80aOcpss91KSRL5TXngyORIiNlbM6ZWUWJgsbFnrVlcICso3sqow"}
When restarting my Oatuh2 server on my development environment with H2 JDBCTokenStore.
How can I configure Zuul, so that it is obtaining a new token?
I'm running a SPA behind Zuul, where Zuul ist the SSOClient. On my SPA I only get the 401 response and I'm not able to clear the JSESSIONID as it's http only. So I need a way that Zuul is redirecting me to the login page or is obtaining a new token. I tried to add the Oauth2RestTemplate mentioned above, without success.
@HJK181 that's a JWT token so the JDBCTokenStore won't help you. Probably better to ask a question on Stack Overflow (this issue is closed and doesn't seem particularly relevant).
May I ask you one last question here? Isn't it possible to use a JDBCTokenStore with JWT? I have the following Oauth2 configuration:
@Bean
public JdbcTokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
final KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource(cxpProperties.getOauth2().getJksFile()),
cxpProperties.getOauth2().getJksPassword()
.toCharArray())
.getKeyPair(cxpProperties.getOauth2().getKeyPairAlias());
converter.setKeyPair(keyPair);
return converter;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(this.dataSource).passwordEncoder(passwordEncoder);
}
For me it seems to work fine, I also checked the OAUTH_ACCESS_TOKEN and OAUTH_REFRESH_TOKEN tables which contain proper tokens (I assume from the Zuul SSOClient?). However the exception is printing a JWT as you said. Do I mix something up?
Thanks in advance.
I suppose there's nothing stopping you from storing a JWT in a database. But why would you do that? Anyway, this is not the right forum to be discussing it.
@lthomassin Is this issue solved? If yes, how?