Skip to content

Instantly share code, notes, and snippets.

@michmzr
Created October 24, 2019 13:41
Show Gist options
  • Save michmzr/5726648b0cc81a1dee89ecf5f5c4c94b to your computer and use it in GitHub Desktop.
Save michmzr/5726648b0cc81a1dee89ecf5f5c4c94b to your computer and use it in GitHub Desktop.
Reauthentificate oauth2 token when refresh token is expired, access token revoked. Implementation for Feign Client plugin
@Slf4j
public class CustomErrorDecoder implements ErrorDecoder {
@Autowired
FeignRequestInterceptor feignRequestInterceptor;
@Override
public Exception decode(String methodKey, Response response) {
log.debug("Catched Feign client error {}, {}", methodKey, response);
FeignException exception = errorStatus(methodKey, response);
switch (response.status()) {
case 401:
log.debug("Clearing access token and retrying last reques ");
feignRequestInterceptor.cleanAccessToken();
return new RetryableException(exception.getMessage(), new Date());
case 404:
return new NotFoundException(response.reason());
default:
return new exception;
}
}
}
@Configuration
public class FeignClientConfiguration {
@Value("${oauth.accessTokenUri}")
private String accessTokenUri;
@Value("${oauth.clientId}")
private String clientId;
@Value("${oauth.clientSecret}")
private String clientSecret;
@Value("${oauth.client.scope}")
private String scope;
@Value("${oauth.client.user}")
private String user;
@Value("${oauth.client.password}")
private String password;
@Value("${oauth.grantType}")
private String grantType = "password";
@Bean
FeignRequestInterceptor oauth2FeignRequestInterceptor() {
return new FeignRequestInterceptor(new DefaultOAuth2ClientContext(), resource());
}
private OAuth2ProtectedResourceDetails resource() {
ResourceOwnerPasswordResourceDetails resourceDetails = new ResourceOwnerPasswordResourceDetails();
resourceDetails.setUsername(user);
resourceDetails.setPassword(password);
resourceDetails.setAccessTokenUri(accessTokenUri);
resourceDetails.setClientId(clientId);
resourceDetails.setClientSecret(clientSecret);
resourceDetails.setGrantType(grantType);
resourceDetails.setScope(Arrays.asList(scope));
return resourceDetails;
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}
@Bean
public Retryer feignRetryer() {
return new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1), 2); // this will retry once
}
}
@Log4j
public class FeignRequestInterceptor extends OAuth2FeignRequestInterceptor {
private OAuth2ClientContext clientContext;
public FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, OAuth2ProtectedResourceDetails resource) {
super(oAuth2ClientContext, resource);
clientContext = oAuth2ClientContext;
}
@Override
public OAuth2AccessToken getToken() {
OAuth2AccessToken accessToken = clientContext.getAccessToken();
if (accessToken == null || accessToken.isExpired()) {
try {
accessToken = acquireAccessToken();
}catch (InvalidGrantException e) {
log.error("Catched invalid grant exception: ", e);
cleanAccessToken();
accessToken = acquireAccessToken();
}catch (HttpClientErrorException e) {
log.error("Catched oauth http exception: ", e);
if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {
log.debug("Acquiring access token...");
cleanAccessToken();
accessToken = acquireAccessToken();
} else {
throw e;
}
} catch (UserRedirectRequiredException e) {
clientContext.setAccessToken(null);
String stateKey = e.getStateKey();
if (stateKey != null) {
Object stateToPreserve = e.getStateToPreserve();
if (stateToPreserve == null) {
stateToPreserve = "NONE";
}
clientContext.setPreservedState(stateKey, stateToPreserve);
}
throw e;
}
}
return accessToken;
}
public void cleanAccessToken() {
log.debug("Reset access token");
clientContext.setAccessToken(null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment