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:
parent
dfc4cf36a2
commit
ad7a6c4854
2 changed files with 38 additions and 2 deletions
|
@ -21,14 +21,18 @@ import org.keycloak.admin.client.token.TokenManager;
|
|||
|
||||
import javax.ws.rs.client.ClientRequestContext;
|
||||
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 java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @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 TokenManager tokenManager;
|
||||
|
||||
|
@ -45,9 +49,27 @@ public class BearerAuthFilter implements ClientRequestFilter {
|
|||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,4 +118,18 @@ public class TokenManager {
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue