NPE in checkAndBindMtlsHoKToken on Token Refresh when using SuppressRefreshTokenRotationExecutor and Certificate Bound Token
closes #25022 Signed-off-by: Takashi Norimatsu <takashi.norimatsu.ws@hitachi.com>
This commit is contained in:
parent
a5ce7c4661
commit
1f5ee9bf80
2 changed files with 63 additions and 3 deletions
|
@ -566,11 +566,11 @@ public class TokenEndpoint {
|
|||
// KEYCLOAK-6771 Certificate Bound Token
|
||||
TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.refreshAccessToken(session, session.getContext().getUri(), clientConnection, realm, client, refreshToken, event, headers, request);
|
||||
|
||||
session.clientPolicy().triggerOnEvent(new TokenRefreshResponseContext(formParams, responseBuilder));
|
||||
|
||||
checkAndBindMtlsHoKToken(responseBuilder, clientConfig.isUseRefreshToken());
|
||||
checkAndBindDPoPToken(responseBuilder, clientConfig.isUseRefreshToken() && (client.isPublicClient() || client.isBearerOnly()), Profile.isFeatureEnabled(Profile.Feature.DPOP));
|
||||
|
||||
session.clientPolicy().triggerOnEvent(new TokenRefreshResponseContext(formParams, responseBuilder));
|
||||
|
||||
res = responseBuilder.build();
|
||||
|
||||
if (!responseBuilder.isOfflineToken()) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.hamcrest.Matchers.is;
|
|||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
|
||||
|
@ -44,6 +45,7 @@ import static org.keycloak.testsuite.util.ClientPoliciesUtil.createSecureClientA
|
|||
import static org.keycloak.testsuite.util.ClientPoliciesUtil.createSecureSigningAlgorithmForSignedJwtEnforceExecutorConfig;
|
||||
import static org.keycloak.testsuite.util.ClientPoliciesUtil.createTestRaiseExeptionConditionConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -53,7 +55,7 @@ import java.util.Map;
|
|||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
|
@ -111,11 +113,13 @@ import org.keycloak.services.clientpolicy.executor.RejectResourceOwnerPasswordCr
|
|||
import org.keycloak.services.clientpolicy.executor.SecureClientAuthenticatorExecutorFactory;
|
||||
import org.keycloak.services.clientpolicy.executor.SecureSessionEnforceExecutorFactory;
|
||||
import org.keycloak.services.clientpolicy.executor.SecureSigningAlgorithmForSignedJwtExecutorFactory;
|
||||
import org.keycloak.services.clientpolicy.executor.SuppressRefreshTokenRotationExecutorFactory;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.client.resources.TestApplicationResourceUrls;
|
||||
import org.keycloak.testsuite.services.clientpolicy.condition.TestRaiseExceptionConditionFactory;
|
||||
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
|
||||
import org.keycloak.testsuite.util.ClientBuilder;
|
||||
import org.keycloak.testsuite.util.MutualTLSUtils;
|
||||
import org.keycloak.testsuite.util.ClientPoliciesUtil.ClientPoliciesBuilder;
|
||||
import org.keycloak.testsuite.util.ClientPoliciesUtil.ClientPolicyBuilder;
|
||||
import org.keycloak.testsuite.util.ClientPoliciesUtil.ClientProfileBuilder;
|
||||
|
@ -574,6 +578,62 @@ public class ClientPoliciesTest extends AbstractClientPoliciesTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSuppressRefreshTokenRotationWithHolderOfKeyToken() throws Exception {
|
||||
Assume.assumeTrue("This test must be executed with enabled TLS.", ServerURLs.AUTH_SERVER_SSL_REQUIRED);
|
||||
|
||||
// register profiles
|
||||
String json = (new ClientProfilesBuilder()).addProfile(
|
||||
(new ClientProfileBuilder()).createProfile(PROFILE_NAME, "Le Premier Profil")
|
||||
.addExecutor(SuppressRefreshTokenRotationExecutorFactory.PROVIDER_ID, null)
|
||||
.addExecutor(HolderOfKeyEnforcerExecutorFactory.PROVIDER_ID,
|
||||
createHolderOfKeyEnforceExecutorConfig(Boolean.TRUE))
|
||||
.toRepresentation()
|
||||
).toString();
|
||||
updateProfiles(json);
|
||||
|
||||
// register policies
|
||||
json = (new ClientPoliciesBuilder()).addPolicy(
|
||||
(new ClientPolicyBuilder()).createPolicy(POLICY_NAME, "Den Forste Politikken", Boolean.TRUE)
|
||||
.addCondition(ClientRolesConditionFactory.PROVIDER_ID,
|
||||
createClientRolesConditionConfig(Arrays.asList(SAMPLE_CLIENT_ROLE)))
|
||||
.addProfile(PROFILE_NAME)
|
||||
.toRepresentation()
|
||||
).toString();
|
||||
updatePolicies(json);
|
||||
|
||||
try (ClientAttributeUpdater cau = ClientAttributeUpdater.forClient(adminClient, REALM_NAME, TEST_CLIENT)) {
|
||||
ClientRepresentation clientRep = cau.getResource().toRepresentation();
|
||||
Assert.assertNotNull(clientRep);
|
||||
OIDCAdvancedConfigWrapper.fromClientRepresentation(clientRep).setUseMtlsHoKToken(true);
|
||||
cau.update();
|
||||
// Check login.
|
||||
OAuthClient.AuthorizationEndpointResponse loginResponse = oauth.doLogin(TEST_USER_NAME, TEST_USER_PASSWORD);
|
||||
Assert.assertNull(loginResponse.getError());
|
||||
|
||||
String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
|
||||
|
||||
// Check token obtaining.
|
||||
OAuthClient.AccessTokenResponse accessTokenResponse;
|
||||
try (CloseableHttpClient client = MutualTLSUtils.newCloseableHttpClientWithDefaultKeyStoreAndTrustStore()) {
|
||||
accessTokenResponse = oauth.doAccessTokenRequest(code, TEST_CLIENT_SECRET, client);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
assertEquals(200, accessTokenResponse.getStatusCode());
|
||||
|
||||
// Check token refresh.
|
||||
OAuthClient.AccessTokenResponse accessTokenResponseRefreshed;
|
||||
try (CloseableHttpClient client = MutualTLSUtils.newCloseableHttpClientWithDefaultKeyStoreAndTrustStore()) {
|
||||
accessTokenResponseRefreshed = oauth.doRefreshTokenRequest(accessTokenResponse.getRefreshToken(), TEST_CLIENT_SECRET, client);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
assertEquals(200, accessTokenResponseRefreshed.getStatusCode());
|
||||
assertNull(accessTokenResponseRefreshed.getRefreshToken());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegativeLogicCondition() throws Exception {
|
||||
// register profiles
|
||||
|
|
Loading…
Reference in a new issue