KEYCLOAK-8264 Update OpenShift Token Review endpoint to support additional algorithms and to update session last refresh on token introspection
This commit is contained in:
1 parent
12f3d2115d
commit
0bb2ff9e8a
4 files changed
+121
-27
No files matched your search
+1
-1
@@ -86,7 +86,7 @@ public class AccessTokenIntrospectionProvider implements TokenIntrospectionProvi
|
||||
|
||||
RealmModel realm = this.session.getContext().getRealm();
|
||||
|
||||
return tokenManager.isTokenValid(session, realm, accessToken) ? accessToken : null;
|
||||
return tokenManager.checkTokenValidForIntrospection(session, realm, accessToken) ? accessToken : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -202,7 +202,17 @@ public class TokenManager {
|
||||
return new TokenValidation(user, userSession, clientSessionCtx, newToken);
|
||||
}
|
||||
|
||||
public boolean isTokenValid(KeycloakSession session, RealmModel realm, AccessToken token) throws OAuthErrorException {
|
||||
/**
|
||||
* Checks if the token is valid. Intended usage is for token introspection endpoints as the session last refresh
|
||||
* is updated if the token was valid. This is used to keep the session alive when long lived tokens are used.
|
||||
*
|
||||
* @param session
|
||||
* @param realm
|
||||
* @param token
|
||||
* @return
|
||||
* @throws OAuthErrorException
|
||||
*/
|
||||
public boolean checkTokenValidForIntrospection(KeycloakSession session, RealmModel realm, AccessToken token) throws OAuthErrorException {
|
||||
if (!token.isActive()) {
|
||||
return false;
|
||||
}
|
||||
@@ -216,17 +226,24 @@ public class TokenManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean valid = false;
|
||||
|
||||
UserSessionModel userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), false, client.getId());
|
||||
|
||||
if (AuthenticationManager.isSessionValid(realm, userSession)) {
|
||||
return isUserValid(session, realm, token, userSession);
|
||||
valid = isUserValid(session, realm, token, userSession);
|
||||
} else {
|
||||
userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), true, client.getId());
|
||||
if (AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
|
||||
valid = isUserValid(session, realm, token, userSession);
|
||||
}
|
||||
}
|
||||
|
||||
userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), true, client.getId());
|
||||
if (AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
|
||||
return isUserValid(session, realm, token, userSession);
|
||||
if (valid) {
|
||||
userSession.setLastSessionRefresh(Time.currentTime());
|
||||
}
|
||||
|
||||
return false;
|
||||
return valid;
|
||||
}
|
||||
|
||||
private boolean isUserValid(KeycloakSession session, RealmModel realm, AccessToken token, UserSessionModel userSession) {
|
||||
|
||||
+10
-12
@@ -16,8 +16,10 @@
|
||||
*/
|
||||
package org.keycloak.protocol.openshift;
|
||||
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.TokenVerifier;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.crypto.SignatureProvider;
|
||||
import org.keycloak.crypto.SignatureVerifierContext;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
@@ -39,7 +41,6 @@ import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.security.PublicKey;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -89,22 +90,19 @@ public class OpenShiftTokenReviewEndpoint implements OIDCExtProvider {
|
||||
|
||||
AccessToken token = null;
|
||||
try {
|
||||
RSATokenVerifier verifier = RSATokenVerifier.create(reviewRequest.getSpec().getToken())
|
||||
TokenVerifier<AccessToken> verifier = TokenVerifier.create(reviewRequest.getSpec().getToken(), AccessToken.class)
|
||||
.realmUrl(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
|
||||
|
||||
PublicKey publicKey = session.keys().getRsaPublicKey(realm, verifier.getHeader().getKeyId());
|
||||
if (publicKey == null) {
|
||||
error(401, Errors.INVALID_TOKEN, "Invalid public key");
|
||||
} else {
|
||||
verifier.publicKey(publicKey);
|
||||
verifier.verify();
|
||||
token = verifier.getToken();
|
||||
}
|
||||
SignatureVerifierContext verifierContext = session.getProvider(SignatureProvider.class, verifier.getHeader().getAlgorithm().name()).verifier(verifier.getHeader().getKeyId());
|
||||
verifier.verifierContext(verifierContext);
|
||||
|
||||
verifier.verify();
|
||||
token = verifier.getToken();
|
||||
} catch (VerificationException e) {
|
||||
error(401, Errors.INVALID_TOKEN, "Token verification failure");
|
||||
}
|
||||
|
||||
if (!tokenManager.isTokenValid(session, realm, token)) {
|
||||
if (!tokenManager.checkTokenValidForIntrospection(session, realm, token)) {
|
||||
error(401, Errors.INVALID_TOKEN, "Token verification failure");
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user