KEYCLOAK-4167 Make OIDC identity provider key ID configurable
This commit is contained in:
parent
23c8809598
commit
e11957ecf3
5 changed files with 57 additions and 5 deletions
|
@ -17,7 +17,6 @@
|
|||
package org.keycloak.broker.oidc;
|
||||
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
/**
|
||||
* @author Pedro Igor
|
||||
|
@ -61,6 +60,14 @@ public class OIDCIdentityProviderConfig extends OAuth2IdentityProviderConfig {
|
|||
getConfig().put("publicKeySignatureVerifier", signingCertificate);
|
||||
}
|
||||
|
||||
public String getPublicKeySignatureVerifierKeyId() {
|
||||
return getConfig().get("publicKeySignatureVerifierKeyId");
|
||||
}
|
||||
|
||||
public void setPublicKeySignatureVerifierKeyId(String publicKeySignatureVerifierKeyId) {
|
||||
getConfig().put("publicKeySignatureVerifierKeyId", publicKeySignatureVerifierKeyId);
|
||||
}
|
||||
|
||||
public boolean isValidateSignature() {
|
||||
return Boolean.valueOf(getConfig().get("validateSignature"));
|
||||
}
|
||||
|
|
|
@ -60,7 +60,10 @@ public class OIDCIdentityProviderPublicKeyLoader implements PublicKeyLoader {
|
|||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
String kid = KeyUtils.createKeyId(publicKey);
|
||||
String presetKeyId = config.getPublicKeySignatureVerifierKeyId();
|
||||
String kid = (presetKeyId == null || presetKeyId.trim().isEmpty())
|
||||
? KeyUtils.createKeyId(publicKey)
|
||||
: presetKeyId;
|
||||
return Collections.singletonMap(kid, publicKey);
|
||||
} catch (Exception e) {
|
||||
logger.warnf(e, "Unable to retrieve publicKey for verify signature of identityProvider '%s' . Error details: %s", config.getAlias(), e.getMessage());
|
||||
|
|
|
@ -24,12 +24,12 @@ import javax.ws.rs.core.UriBuilder;
|
|||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.*;
|
||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||
import org.keycloak.keys.KeyProvider;
|
||||
import org.keycloak.keys.PublicKeyStorageUtils;
|
||||
import org.keycloak.keys.loader.PublicKeyStorageManager;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
|
@ -181,6 +181,38 @@ public class KcOIDCBrokerWithSignatureTest extends AbstractBaseBrokerTest {
|
|||
assertErrorPage("Unexpected error when authenticating with identity provider");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignatureVerificationHardcodedPublicKeyWithKeyIdSetExplicitly() throws Exception {
|
||||
// Configure OIDC identity provider with JWKS URL
|
||||
IdentityProviderRepresentation idpRep = getIdentityProvider();
|
||||
OIDCIdentityProviderConfigRep cfg = new OIDCIdentityProviderConfigRep(idpRep);
|
||||
cfg.setValidateSignature(true);
|
||||
cfg.setUseJwksUrl(false);
|
||||
|
||||
KeysMetadataRepresentation.KeyMetadataRepresentation key = ApiUtil.findActiveKey(providerRealm());
|
||||
String pemData = key.getPublicKey();
|
||||
cfg.setPublicKeySignatureVerifier(pemData);
|
||||
String expectedKeyId = KeyUtils.createKeyId(PemUtils.decodePublicKey(pemData));
|
||||
updateIdentityProvider(idpRep);
|
||||
|
||||
// Check that user is able to login
|
||||
logInAsUserInIDPForFirstTime();
|
||||
assertLoggedInAccountManagement();
|
||||
|
||||
logoutFromRealm(bc.consumerRealmName());
|
||||
|
||||
// Set key id to an invalid one
|
||||
cfg.setPublicKeySignatureVerifierKeyId("invalid-key-id");
|
||||
updateIdentityProvider(idpRep);
|
||||
|
||||
logInAsUserInIDP();
|
||||
assertErrorPage("Unexpected error when authenticating with identity provider");
|
||||
|
||||
// Set key id to a valid one
|
||||
cfg.setPublicKeySignatureVerifierKeyId(expectedKeyId);
|
||||
updateIdentityProvider(idpRep);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testClearKeysCache() throws Exception {
|
||||
|
|
|
@ -503,6 +503,8 @@ identity-provider.use-jwks-url.tooltip=If the switch is on, then identity provid
|
|||
identity-provider.jwks-url.tooltip=URL where identity provider keys in JWK format are stored. See JWK specification for more details. If you use external keycloak identity provider, then you can use URL like 'http://broker-keycloak:8180/auth/realms/test/protocol/openid-connect/certs' assuming your brokered keycloak is running on 'http://broker-keycloak:8180' and it's realm is 'test' .
|
||||
validating-public-key=Validating Public Key
|
||||
identity-provider.validating-public-key.tooltip=The public key in PEM format that must be used to verify external IDP signatures.
|
||||
validating-public-key-id=Validating Public Key Id
|
||||
identity-provider.validating-public-key-id.tooltip=Explicit ID of the validating public key given above if the key ID. Leave unset if the external IDP is Keycloak or uses the same mechanism to determine key ID.
|
||||
import-external-idp-config=Import External IDP Config
|
||||
import-external-idp-config.tooltip=Allows you to load external IDP metadata from a config file or to download it from a URL.
|
||||
import-from-url=Import from URL
|
||||
|
|
|
@ -211,13 +211,21 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group clearfix" data-ng-hide="identityProvider.config.useJwksUrl == 'true'">
|
||||
<label class="col-md-2 control-label" for="publicKeySignatureVerifier">{{:: 'validating-public-key' | translate}}</label>
|
||||
<label class="col-md-2 control-label" for="publicKeySignatureVerifierKey">{{:: 'validating-public-key' | translate}}</label>
|
||||
<div class="col-md-6">
|
||||
<textarea class="form-control" id="publicKeySignatureVerifier" ng-model="identityProvider.config.publicKeySignatureVerifier"/>
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'identity-provider.validating-public-key.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="form-group clearfix" data-ng-hide="identityProvider.config.useJwksUrl == 'true'">
|
||||
<label class="col-md-2 control-label" for="publicKeySignatureVerifierKeyId">{{:: 'validating-public-key-id' | translate}}</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" id="publicKeySignatureVerifierKeyId" ng-model="identityProvider.config.publicKeySignatureVerifierKeyId"/>
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'identity-provider.validating-public-key-id.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
|
|
Loading…
Reference in a new issue