KEYCLOAK-2726: Invalidate token upon failure

When a token managed by TokenManager is known to be invalid, it should no
longer be used. This commit adds a response listener to the only filter
using TokenManager, which causes, upon authentication failure, to
invalidate the token that was used.
This commit is contained in:
Guus der Kinderen 2016-03-30 14:45:19 +02:00
parent dfc4cf36a2
commit ad7a6c4854
2 changed files with 38 additions and 2 deletions

View file

@ -21,14 +21,18 @@ import org.keycloak.admin.client.token.TokenManager;
import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import java.io.IOException; import java.io.IOException;
import java.util.List;
/** /**
* @author rodrigo.sasaki@icarros.com.br * @author rodrigo.sasaki@icarros.com.br
*/ */
public class BearerAuthFilter implements ClientRequestFilter { public class BearerAuthFilter implements ClientRequestFilter, ClientResponseFilter {
public static final String AUTH_HEADER_PREFIX = "Bearer ";
private final String tokenString; private final String tokenString;
private final TokenManager tokenManager; private final TokenManager tokenManager;
@ -45,9 +49,27 @@ public class BearerAuthFilter implements ClientRequestFilter {
@Override @Override
public void filter(ClientRequestContext requestContext) throws IOException { public void filter(ClientRequestContext requestContext) throws IOException {
String authHeader = "Bearer " + (tokenManager != null ? tokenManager.getAccessTokenString() : tokenString); String authHeader = AUTH_HEADER_PREFIX + (tokenManager != null ? tokenManager.getAccessTokenString() : tokenString);
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader); requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
} }
@Override
public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException {
if (responseContext.getStatus() == 401 && tokenManager != null) {
List<Object> authHeaders = requestContext.getHeaders().get(HttpHeaders.AUTHORIZATION);
if (authHeaders == null) {
return;
}
for (Object authHeader : authHeaders) {
if (authHeader instanceof String) {
String headerValue = (String) authHeader;
if (headerValue.startsWith(AUTH_HEADER_PREFIX)) {
String token = headerValue.substring( AUTH_HEADER_PREFIX.length() );
tokenManager.invalidate( token );
}
}
}
}
}
} }

View file

@ -118,4 +118,18 @@ public class TokenManager {
return (Time.currentTime() + minTokenValidity) >= expirationTime; return (Time.currentTime() + minTokenValidity) >= expirationTime;
} }
/**
* Invalidates the current token, but only when it is equal to the token passed as an argument.
*
* @param token the token to invalidate (cannot be null).
*/
public void invalidate(String token) {
if (currentToken == null) {
return; // There's nothing to invalidate.
}
if (token.equals(currentToken.getToken())) {
// When used next, this cause a refresh attempt, that in turn will cause a grant attempt if refreshing fails.
expirationTime = -1;
}
}
} }