7

I've got a client app configured with @EnableOAuth2Sso and @EnableZuulProxy, and a resource server (separate app) configured with @EnableOAuth2Resource. I can see that the client correctly authenticates to the resource server with Authorization: Bearer {access_token here}, but when once the access token expires, the proxied resource server request fails permanently.

[Edited]

I've modified my resource server by providing a custom RemoteTokenServices bean that uses OpenAM's /tokeninfo endpoint to decide whether an access_token remains valid. (The Spring-provided RemoteTokenServices bean attempts to POST, which gets a 405 from OpenAM). When I detect the access_token is invalid, I throw InvalidTokenException from my.spring.oauth2.OpenAMRemoteTokenServices#loadAuthentication. Now, my resource server is (I think correctly) sending HTTP 401 on the response to the client, in the case where the access_token has expired.

Still, the client is not attempting to refresh the token.

Maybe my mental model is wrong. I expect the client, in the case of expired access_token, to automatically use the refresh_token to obtain a new one. I don't know whether I think it should proactively refresh an access_token (within some epsilon before expiry time), or wait for a downstream request to fail and try refreshing then. But my client appears to be doing neither, and I can't tell why not.

Tommy Knowlton
  • 580
  • 1
  • 4
  • 15
  • I can see that `org.springframework.cloud.security.oauth2.resource.UserInfoTokenServices#getMap` (in the client) is setting (replacing) the access_token on the context with an access token that is less-informative. The replacement token contains only the opaque string token value, whereas the token that it is replacing contained an expiration and a refreshToken. Haven't yet figured out _why_ the token is getting replaced with a less-complete token containing the *same opaque string*. – Tommy Knowlton Jun 25 '15 at 00:07
  • Hi, this sounds like exactly the issue I'm having. I want to grant short-lived access tokens and have the zuul proxy use the refresh token for the duration of the users session. Did you ever make any progress? – Will Faithfull Sep 29 '16 at 14:40
  • @WillFaithfull sorry, no I never figured this out, and probably should by now have deleted the question. Sorry to be of no help to you. – Tommy Knowlton Oct 05 '16 at 16:40
  • 1
    I did actually get this working. There were two issues in my zuul proxy SSO application - I needed the `DefaultTokenServices` bean there to have `tokenServices.setSupportRefreshToken(true)`, and I needed to define an `OAuth2RestOperations` bean in the context so that it could actually make the requests. The issues from there onwards were to do with my authorization server. I'm not sure if this constitutes an answer to the question, or if it is even the same issue though. – Will Faithfull Oct 06 '16 at 08:08

1 Answers1

2

As stated in this git issue: https://github.com/spring-guides/tut-spring-security-and-angular-js/issues/140, the problem might be related to the fact that with versions 1.4 and above of spring boot the Zuul filter that handles the downstream of access tokens to services (org.springframework.cloud.security.oauth2.proxy.OAuth2TokenRelayFilter) is missing a bean of type OAuth2RestTemplate, which is used by the filter itself to automatically handle the refresh_token grant when access tokens expire.

I had the same issue and I solved it by adding in a configuration class the following bean:

@Configuration
public class ZuulConfiguration {
    @Bean
    protected OAuth2RestTemplate oauth2RestTemplate(OAuth2ProtectedResourceDetails resource, 
        OAuth2ClientContext context) {

        return new OAuth2RestTemplate(resource, context);
    }
}
Nicola
  • 2,876
  • 2
  • 18
  • 26