Use realm default signature algorithm for id_token_signed_response_alg
Closes #9695 Signed-off-by: Justin Tay <49700559+justin-tay@users.noreply.github.com>
This commit is contained in:
parent
c1a471755d
commit
30cd40e097
3 changed files with 147 additions and 3 deletions
|
@ -21,6 +21,7 @@ import org.keycloak.OAuth2Constants;
|
|||
import org.keycloak.authentication.ClientAuthenticator;
|
||||
import org.keycloak.authentication.ClientAuthenticatorFactory;
|
||||
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
|
||||
import org.keycloak.crypto.Algorithm;
|
||||
import org.keycloak.jose.jwk.JSONWebKeySet;
|
||||
import org.keycloak.jose.jwk.JWK;
|
||||
import org.keycloak.jose.jwk.JWKParser;
|
||||
|
@ -159,9 +160,7 @@ public class DescriptionConverter {
|
|||
configWrapper.setAllowRegexPatternComparison(false);
|
||||
}
|
||||
|
||||
if (clientOIDC.getIdTokenSignedResponseAlg() != null) {
|
||||
configWrapper.setIdTokenSignedResponseAlg(clientOIDC.getIdTokenSignedResponseAlg());
|
||||
}
|
||||
configWrapper.setIdTokenSignedResponseAlg(clientOIDC.getIdTokenSignedResponseAlg());
|
||||
|
||||
if (clientOIDC.getIdTokenEncryptedResponseAlg() != null) {
|
||||
configWrapper.setIdTokenEncryptedResponseAlg(clientOIDC.getIdTokenEncryptedResponseAlg());
|
||||
|
@ -379,6 +378,10 @@ public class DescriptionConverter {
|
|||
throw new ClientRegistrationException("Illegal jwks format");
|
||||
}
|
||||
}
|
||||
String defaultSignatureAlgorithm = session.getContext().getRealm().getDefaultSignatureAlgorithm();
|
||||
if (Algorithm.RS256.equals(defaultSignatureAlgorithm) || StringUtil.isBlank(defaultSignatureAlgorithm)) {
|
||||
defaultSignatureAlgorithm = null;
|
||||
}
|
||||
// KEYCLOAK-6771 Certificate Bound Token
|
||||
// https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-6.5
|
||||
if (config.isUseMtlsHokToken()) {
|
||||
|
@ -391,6 +394,8 @@ public class DescriptionConverter {
|
|||
}
|
||||
if (config.getIdTokenSignedResponseAlg() != null) {
|
||||
response.setIdTokenSignedResponseAlg(config.getIdTokenSignedResponseAlg());
|
||||
} else if (defaultSignatureAlgorithm != null){
|
||||
response.setIdTokenSignedResponseAlg(defaultSignatureAlgorithm);
|
||||
}
|
||||
if (config.getIdTokenEncryptedResponseAlg() != null) {
|
||||
response.setIdTokenEncryptedResponseAlg(config.getIdTokenEncryptedResponseAlg());
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.client;
|
||||
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.client.registration.Auth;
|
||||
import org.keycloak.crypto.Algorithm;
|
||||
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
||||
import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
|
||||
import org.keycloak.representations.idm.ClientInitialAccessPresentation;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.oidc.OIDCClientRepresentation;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.util.TokenSignatureUtil;
|
||||
|
||||
public class OIDCClientRegistrationDefaultSignatureTest extends AbstractClientRegistrationTest {
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
|
||||
ClientInitialAccessPresentation token = adminClient.realm(REALM_NAME).clientInitialAccess().create(new ClientInitialAccessCreatePresentation(0, 10));
|
||||
reg.auth(Auth.token(token));
|
||||
}
|
||||
|
||||
private OIDCClientRepresentation createRep() {
|
||||
OIDCClientRepresentation client = new OIDCClientRepresentation();
|
||||
client.setClientName("RegistrationAccessTokenTest");
|
||||
client.setClientUri("http://root");
|
||||
client.setRedirectUris(Collections.singletonList("http://redirect"));
|
||||
client.setFrontChannelLogoutUri("http://frontchannel");
|
||||
client.setFrontchannelLogoutSessionRequired(true);
|
||||
return client;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenSignedResponse() throws Exception {
|
||||
OIDCClientRepresentation response = null;
|
||||
OIDCClientRepresentation updated = null;
|
||||
try {
|
||||
TokenSignatureUtil.changeRealmTokenSignatureProvider(adminClient, Algorithm.ES512);
|
||||
|
||||
// create (no specification)
|
||||
OIDCClientRepresentation clientRep = createRep();
|
||||
|
||||
response = reg.oidc().create(clientRep);
|
||||
Assert.assertEquals(Algorithm.ES512, response.getIdTokenSignedResponseAlg());
|
||||
|
||||
// Test Keycloak representation
|
||||
ClientRepresentation kcClient = getClient(response.getClientId());
|
||||
OIDCAdvancedConfigWrapper config = OIDCAdvancedConfigWrapper.fromClientRepresentation(kcClient);
|
||||
// Client representation of id.token.signed.response.alg is null as from realm
|
||||
Assert.assertNull(config.getIdTokenSignedResponseAlg());
|
||||
|
||||
// update
|
||||
reg.auth(Auth.token(response));
|
||||
response.setIdTokenSignedResponseAlg(Algorithm.ES256);
|
||||
updated = reg.oidc().update(response);
|
||||
Assert.assertEquals(Algorithm.ES256, updated.getIdTokenSignedResponseAlg());
|
||||
|
||||
// Test Keycloak representation
|
||||
kcClient = getClient(updated.getClientId());
|
||||
config = OIDCAdvancedConfigWrapper.fromClientRepresentation(kcClient);
|
||||
Assert.assertEquals(Algorithm.ES256, config.getIdTokenSignedResponseAlg());
|
||||
|
||||
// update after changing default realm token signature
|
||||
TokenSignatureUtil.changeRealmTokenSignatureProvider(adminClient, Algorithm.ES384);
|
||||
reg.auth(Auth.token(updated));
|
||||
updated.setIdTokenSignedResponseAlg(null);
|
||||
response = reg.oidc().update(updated);
|
||||
Assert.assertEquals(Algorithm.ES384, response.getIdTokenSignedResponseAlg());
|
||||
} finally {
|
||||
// revert
|
||||
TokenSignatureUtil.changeRealmTokenSignatureProvider(adminClient, Algorithm.RS256);
|
||||
reg.auth(Auth.token(response));
|
||||
response.setIdTokenSignedResponseAlg(null);
|
||||
updated = reg.oidc().update(response);
|
||||
Assert.assertNull(updated.getIdTokenSignedResponseAlg());
|
||||
|
||||
// Test Keycloak representation
|
||||
ClientRepresentation kcClient = getClient(updated.getClientId());
|
||||
OIDCAdvancedConfigWrapper config = OIDCAdvancedConfigWrapper.fromClientRepresentation(kcClient);
|
||||
// Client representation of id.token.signed.response.alg is null as from realm
|
||||
Assert.assertNull(config.getIdTokenSignedResponseAlg());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -477,6 +477,40 @@ public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdTokenSignedResponse() throws Exception {
|
||||
OIDCClientRepresentation response = null;
|
||||
OIDCClientRepresentation updated = null;
|
||||
try {
|
||||
// create (no specification)
|
||||
OIDCClientRepresentation clientRep = createRep();
|
||||
|
||||
response = reg.oidc().create(clientRep);
|
||||
Assert.assertNull(response.getIdTokenSignedResponseAlg());
|
||||
|
||||
// Test Keycloak representation
|
||||
ClientRepresentation kcClient = getClient(response.getClientId());
|
||||
OIDCAdvancedConfigWrapper config = OIDCAdvancedConfigWrapper.fromClientRepresentation(kcClient);
|
||||
Assert.assertNull(config.getIdTokenSignedResponseAlg());
|
||||
|
||||
// update
|
||||
reg.auth(Auth.token(response));
|
||||
response.setIdTokenSignedResponseAlg(Algorithm.ES256);
|
||||
updated = reg.oidc().update(response);
|
||||
Assert.assertEquals(Algorithm.ES256, updated.getIdTokenSignedResponseAlg());
|
||||
|
||||
// Test Keycloak representation
|
||||
kcClient = getClient(updated.getClientId());
|
||||
config = OIDCAdvancedConfigWrapper.fromClientRepresentation(kcClient);
|
||||
Assert.assertEquals(Algorithm.ES256, config.getIdTokenSignedResponseAlg());
|
||||
} finally {
|
||||
// revert
|
||||
reg.auth(Auth.token(updated));
|
||||
updated.setIdTokenSignedResponseAlg(null);
|
||||
reg.oidc().update(updated);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTokenEndpointSigningAlg() throws Exception {
|
||||
OIDCClientRepresentation response = null;
|
||||
|
|
Loading…
Reference in a new issue