KEYCLOAK-18982 Token OIDC introspection endpoint should not update any of the timestamps
This commit is contained in:
parent
c49c7d0ffc
commit
b42f765c2a
4 changed files with 32 additions and 11 deletions
|
@ -18,7 +18,6 @@
|
|||
package org.keycloak.protocol.oidc;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.TokenVerifier;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.crypto.SignatureProvider;
|
||||
|
@ -32,7 +31,6 @@ import org.keycloak.util.JsonSerialization;
|
|||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
|
@ -80,7 +78,7 @@ public class AccessTokenIntrospectionProvider implements TokenIntrospectionProvi
|
|||
}
|
||||
}
|
||||
|
||||
protected AccessToken verifyAccessToken(String token) throws OAuthErrorException, IOException {
|
||||
protected AccessToken verifyAccessToken(String token) {
|
||||
AccessToken accessToken;
|
||||
|
||||
try {
|
||||
|
@ -97,7 +95,7 @@ public class AccessTokenIntrospectionProvider implements TokenIntrospectionProvi
|
|||
|
||||
RealmModel realm = this.session.getContext().getRealm();
|
||||
|
||||
return tokenManager.checkTokenValidForIntrospection(session, realm, accessToken) ? accessToken : null;
|
||||
return tokenManager.checkTokenValidForIntrospection(session, realm, accessToken, false) ? accessToken : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -67,7 +67,6 @@ import org.keycloak.representations.RefreshToken;
|
|||
import org.keycloak.services.ErrorResponseException;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.AuthenticationSessionManager;
|
||||
import org.keycloak.services.managers.ResourceAdminManager;
|
||||
import org.keycloak.services.managers.UserSessionCrossDCManager;
|
||||
import org.keycloak.services.managers.UserSessionManager;
|
||||
import org.keycloak.services.resources.IdentityBrokerService;
|
||||
|
@ -218,16 +217,16 @@ public class TokenManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Checks if the token is valid. Optionally the session last refresh and client session timestamp
|
||||
* are 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
|
||||
* @param updateTimestamps
|
||||
* @return
|
||||
* @throws OAuthErrorException
|
||||
*/
|
||||
public boolean checkTokenValidForIntrospection(KeycloakSession session, RealmModel realm, AccessToken token) throws OAuthErrorException {
|
||||
public boolean checkTokenValidForIntrospection(KeycloakSession session, RealmModel realm, AccessToken token, boolean updateTimestamps) {
|
||||
ClientModel client = realm.getClientByClientId(token.getIssuedFor());
|
||||
if (client == null || !client.isEnabled()) {
|
||||
return false;
|
||||
|
@ -283,7 +282,7 @@ public class TokenManager {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
if (updateTimestamps && valid) {
|
||||
int currentTime = Time.currentTime();
|
||||
userSession.setLastSessionRefresh(currentTime);
|
||||
if (clientSession != null) {
|
||||
|
|
|
@ -105,7 +105,7 @@ public class OpenShiftTokenReviewEndpoint implements OIDCExtProvider, Environmen
|
|||
error(401, Errors.INVALID_TOKEN, "Token verification failure");
|
||||
}
|
||||
|
||||
if (!tokenManager.checkTokenValidForIntrospection(session, realm, token)) {
|
||||
if (!tokenManager.checkTokenValidForIntrospection(session, realm, token, true)) {
|
||||
error(401, Errors.INVALID_TOKEN, "Token verification failure");
|
||||
}
|
||||
|
||||
|
|
|
@ -314,6 +314,8 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
|
|||
AbstractOIDCScopeTest.assertScopes("openid email profile", rep.getScope());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testIntrospectAccessTokenES256() throws Exception {
|
||||
testIntrospectAccessToken(Algorithm.ES256);
|
||||
|
@ -398,6 +400,28 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
|
|||
assertEquals("test-app", rep.getClientId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntrospectDoesntExtendTokenLifespan() throws Exception {
|
||||
oauth.doLogin("test-user@localhost", "password");
|
||||
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
|
||||
AccessTokenResponse accessTokenResponse = oauth.doAccessTokenRequest(code, "password");
|
||||
accessTokenResponse = oauth.doRefreshTokenRequest(accessTokenResponse.getRefreshToken(), "password");
|
||||
|
||||
setTimeOffset(1200);
|
||||
|
||||
String tokenResponse = oauth.introspectRefreshTokenWithClientCredential("confidential-cli", "secret1", accessTokenResponse.getRefreshToken());
|
||||
TokenMetadataRepresentation rep = JsonSerialization.readValue(tokenResponse, TokenMetadataRepresentation.class);
|
||||
|
||||
assertTrue(rep.isActive());
|
||||
assertEquals("test-user@localhost", rep.getUserName());
|
||||
assertEquals("test-app", rep.getClientId());
|
||||
|
||||
setTimeOffset(1200 + 1200);
|
||||
|
||||
accessTokenResponse = oauth.doRefreshTokenRequest(accessTokenResponse.getRefreshToken(), "password");
|
||||
assertEquals(400, accessTokenResponse.getStatusCode());
|
||||
assertEquals("Token is not active", accessTokenResponse.getErrorDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntrospectAccessTokenUserDisabled() throws Exception {
|
||||
|
|
Loading…
Reference in a new issue