434 lines
13 KiB
Java
Executable File
434 lines
13 KiB
Java
Executable File
/*
|
|
* Copyright 2016 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.adapters.saml;
|
|
|
|
import org.keycloak.common.enums.SslRequired;
|
|
import org.keycloak.saml.SignatureAlgorithm;
|
|
|
|
import java.security.KeyPair;
|
|
import java.security.PrivateKey;
|
|
import java.security.PublicKey;
|
|
import java.util.Set;
|
|
import org.apache.http.client.HttpClient;
|
|
import org.keycloak.adapters.HttpClientBuilder;
|
|
import org.keycloak.adapters.saml.rotation.SamlDescriptorPublicKeyLocator;
|
|
import org.keycloak.rotation.CompositeKeyLocator;
|
|
import org.keycloak.rotation.HardcodedKeyLocator;
|
|
import org.keycloak.rotation.KeyLocator;
|
|
|
|
/**
|
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
* @version $Revision: 1 $
|
|
*/
|
|
public class DefaultSamlDeployment implements SamlDeployment {
|
|
|
|
public static class DefaultSingleSignOnService implements IDP.SingleSignOnService {
|
|
private boolean signRequest;
|
|
private boolean validateResponseSignature;
|
|
private boolean validateAssertionSignature;
|
|
private Binding requestBinding;
|
|
private Binding responseBinding;
|
|
private String requestBindingUrl;
|
|
|
|
@Override
|
|
public boolean signRequest() {
|
|
return signRequest;
|
|
}
|
|
|
|
@Override
|
|
public boolean validateResponseSignature() {
|
|
return validateResponseSignature;
|
|
}
|
|
|
|
@Override
|
|
public boolean validateAssertionSignature() {
|
|
return validateAssertionSignature;
|
|
}
|
|
|
|
@Override
|
|
public Binding getRequestBinding() {
|
|
return requestBinding;
|
|
}
|
|
|
|
@Override
|
|
public Binding getResponseBinding() {
|
|
return responseBinding;
|
|
}
|
|
|
|
@Override
|
|
public String getRequestBindingUrl() {
|
|
return requestBindingUrl;
|
|
}
|
|
|
|
public void setSignRequest(boolean signRequest) {
|
|
this.signRequest = signRequest;
|
|
}
|
|
|
|
public void setValidateResponseSignature(boolean validateResponseSignature) {
|
|
this.validateResponseSignature = validateResponseSignature;
|
|
}
|
|
|
|
public void setValidateAssertionSignature(boolean validateAssertionSignature) {
|
|
this.validateAssertionSignature = validateAssertionSignature;
|
|
}
|
|
|
|
public void setRequestBinding(Binding requestBinding) {
|
|
this.requestBinding = requestBinding;
|
|
}
|
|
|
|
public void setResponseBinding(Binding responseBinding) {
|
|
this.responseBinding = responseBinding;
|
|
}
|
|
|
|
public void setRequestBindingUrl(String requestBindingUrl) {
|
|
this.requestBindingUrl = requestBindingUrl;
|
|
}
|
|
}
|
|
|
|
public static class DefaultSingleLogoutService implements IDP.SingleLogoutService {
|
|
private boolean validateRequestSignature;
|
|
private boolean validateResponseSignature;
|
|
private boolean signRequest;
|
|
private boolean signResponse;
|
|
private Binding requestBinding;
|
|
private Binding responseBinding;
|
|
private String requestBindingUrl;
|
|
private String responseBindingUrl;
|
|
|
|
@Override
|
|
public boolean validateRequestSignature() {
|
|
return validateRequestSignature;
|
|
}
|
|
|
|
@Override
|
|
public boolean validateResponseSignature() {
|
|
return validateResponseSignature;
|
|
}
|
|
|
|
@Override
|
|
public boolean signRequest() {
|
|
return signRequest;
|
|
}
|
|
|
|
@Override
|
|
public boolean signResponse() {
|
|
return signResponse;
|
|
}
|
|
|
|
@Override
|
|
public Binding getRequestBinding() {
|
|
return requestBinding;
|
|
}
|
|
|
|
@Override
|
|
public Binding getResponseBinding() {
|
|
return responseBinding;
|
|
}
|
|
|
|
@Override
|
|
public String getRequestBindingUrl() {
|
|
return requestBindingUrl;
|
|
}
|
|
|
|
@Override
|
|
public String getResponseBindingUrl() {
|
|
return responseBindingUrl;
|
|
}
|
|
|
|
public void setValidateRequestSignature(boolean validateRequestSignature) {
|
|
this.validateRequestSignature = validateRequestSignature;
|
|
}
|
|
|
|
public void setValidateResponseSignature(boolean validateResponseSignature) {
|
|
this.validateResponseSignature = validateResponseSignature;
|
|
}
|
|
|
|
public void setSignRequest(boolean signRequest) {
|
|
this.signRequest = signRequest;
|
|
}
|
|
|
|
public void setSignResponse(boolean signResponse) {
|
|
this.signResponse = signResponse;
|
|
}
|
|
|
|
public void setRequestBinding(Binding requestBinding) {
|
|
this.requestBinding = requestBinding;
|
|
}
|
|
|
|
public void setResponseBinding(Binding responseBinding) {
|
|
this.responseBinding = responseBinding;
|
|
}
|
|
|
|
public void setRequestBindingUrl(String requestBindingUrl) {
|
|
this.requestBindingUrl = requestBindingUrl;
|
|
}
|
|
|
|
public void setResponseBindingUrl(String responseBindingUrl) {
|
|
this.responseBindingUrl = responseBindingUrl;
|
|
}
|
|
}
|
|
|
|
public static class DefaultIDP implements IDP {
|
|
|
|
private static final int DEFAULT_CACHE_TTL = 24 * 60 * 60;
|
|
|
|
private String entityID;
|
|
private final CompositeKeyLocator signatureValidationKeyLocator = new CompositeKeyLocator();
|
|
private SingleSignOnService singleSignOnService;
|
|
private SingleLogoutService singleLogoutService;
|
|
private HardcodedKeyLocator hardcodedKeyLocator;
|
|
private int minTimeBetweenDescriptorRequests;
|
|
|
|
@Override
|
|
public String getEntityID() {
|
|
return entityID;
|
|
}
|
|
|
|
@Override
|
|
public SingleSignOnService getSingleSignOnService() {
|
|
return singleSignOnService;
|
|
}
|
|
|
|
@Override
|
|
public SingleLogoutService getSingleLogoutService() {
|
|
return singleLogoutService;
|
|
}
|
|
|
|
@Override
|
|
public KeyLocator getSignatureValidationKeyLocator() {
|
|
return this.signatureValidationKeyLocator;
|
|
}
|
|
|
|
@Override
|
|
public int getMinTimeBetweenDescriptorRequests() {
|
|
return minTimeBetweenDescriptorRequests;
|
|
}
|
|
|
|
public void setMinTimeBetweenDescriptorRequests(int minTimeBetweenDescriptorRequests) {
|
|
this.minTimeBetweenDescriptorRequests = minTimeBetweenDescriptorRequests;
|
|
}
|
|
|
|
public void setEntityID(String entityID) {
|
|
this.entityID = entityID;
|
|
}
|
|
|
|
public void setSignatureValidationKey(PublicKey signatureValidationKey) {
|
|
this.hardcodedKeyLocator = signatureValidationKey == null ? null : new HardcodedKeyLocator(signatureValidationKey);
|
|
refreshKeyLocatorConfiguration();
|
|
}
|
|
|
|
public void setSingleSignOnService(SingleSignOnService singleSignOnService) {
|
|
this.singleSignOnService = singleSignOnService;
|
|
refreshKeyLocatorConfiguration();
|
|
}
|
|
|
|
public void setSingleLogoutService(SingleLogoutService singleLogoutService) {
|
|
this.singleLogoutService = singleLogoutService;
|
|
}
|
|
|
|
public void refreshKeyLocatorConfiguration() {
|
|
this.signatureValidationKeyLocator.clear();
|
|
|
|
// When key is set, use that (and only that), otherwise configure dynamic key locator
|
|
if (this.hardcodedKeyLocator != null) {
|
|
this.signatureValidationKeyLocator.add(this.hardcodedKeyLocator);
|
|
} else if (this.singleSignOnService != null) {
|
|
String samlDescriptorUrl = singleSignOnService.getRequestBindingUrl() + "/descriptor";
|
|
// TODO
|
|
HttpClient httpClient = new HttpClientBuilder().build();
|
|
SamlDescriptorPublicKeyLocator samlDescriptorPublicKeyLocator =
|
|
new SamlDescriptorPublicKeyLocator(
|
|
samlDescriptorUrl, this.minTimeBetweenDescriptorRequests, DEFAULT_CACHE_TTL, httpClient);
|
|
this.signatureValidationKeyLocator.add(samlDescriptorPublicKeyLocator);
|
|
}
|
|
}
|
|
}
|
|
|
|
private IDP idp;
|
|
private boolean configured;
|
|
private SslRequired sslRequired = SslRequired.EXTERNAL;
|
|
private String entityID;
|
|
private String nameIDPolicyFormat;
|
|
private boolean forceAuthentication;
|
|
private boolean isPassive;
|
|
private boolean turnOffChangeSessionIdOnLogin;
|
|
private PrivateKey decryptionKey;
|
|
private KeyPair signingKeyPair;
|
|
private String assertionConsumerServiceUrl;
|
|
private Set<String> roleAttributeNames;
|
|
private PrincipalNamePolicy principalNamePolicy = PrincipalNamePolicy.FROM_NAME_ID;
|
|
private String principalAttributeName;
|
|
private String logoutPage;
|
|
private SignatureAlgorithm signatureAlgorithm;
|
|
private String signatureCanonicalizationMethod;
|
|
|
|
@Override
|
|
public boolean turnOffChangeSessionIdOnLogin() {
|
|
return turnOffChangeSessionIdOnLogin;
|
|
}
|
|
|
|
public void setTurnOffChangeSessionIdOnLogin(boolean turnOffChangeSessionIdOnLogin) {
|
|
this.turnOffChangeSessionIdOnLogin = turnOffChangeSessionIdOnLogin;
|
|
}
|
|
|
|
|
|
@Override
|
|
public IDP getIDP() {
|
|
return idp;
|
|
}
|
|
|
|
@Override
|
|
public boolean isConfigured() {
|
|
return configured;
|
|
}
|
|
|
|
@Override
|
|
public SslRequired getSslRequired() {
|
|
return sslRequired;
|
|
}
|
|
|
|
@Override
|
|
public String getEntityID() {
|
|
return entityID;
|
|
}
|
|
|
|
@Override
|
|
public String getNameIDPolicyFormat() {
|
|
return nameIDPolicyFormat;
|
|
}
|
|
|
|
@Override
|
|
public boolean isForceAuthentication() {
|
|
return forceAuthentication;
|
|
}
|
|
|
|
@Override
|
|
public boolean isIsPassive() {
|
|
return isPassive;
|
|
}
|
|
|
|
@Override
|
|
public PrivateKey getDecryptionKey() {
|
|
return decryptionKey;
|
|
}
|
|
|
|
@Override
|
|
public KeyPair getSigningKeyPair() {
|
|
return signingKeyPair;
|
|
}
|
|
|
|
@Override
|
|
public String getAssertionConsumerServiceUrl() {
|
|
return assertionConsumerServiceUrl;
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getRoleAttributeNames() {
|
|
return roleAttributeNames;
|
|
}
|
|
|
|
@Override
|
|
public PrincipalNamePolicy getPrincipalNamePolicy() {
|
|
return principalNamePolicy;
|
|
}
|
|
|
|
@Override
|
|
public String getPrincipalAttributeName() {
|
|
return principalAttributeName;
|
|
}
|
|
|
|
public void setIdp(IDP idp) {
|
|
this.idp = idp;
|
|
}
|
|
|
|
public void setConfigured(boolean configured) {
|
|
this.configured = configured;
|
|
}
|
|
|
|
public void setSslRequired(SslRequired sslRequired) {
|
|
this.sslRequired = sslRequired;
|
|
}
|
|
|
|
public void setEntityID(String entityID) {
|
|
this.entityID = entityID;
|
|
}
|
|
|
|
public void setNameIDPolicyFormat(String nameIDPolicyFormat) {
|
|
this.nameIDPolicyFormat = nameIDPolicyFormat;
|
|
}
|
|
|
|
public void setForceAuthentication(boolean forceAuthentication) {
|
|
this.forceAuthentication = forceAuthentication;
|
|
}
|
|
|
|
public void setIsPassive(boolean isPassive){
|
|
this.isPassive = isPassive;
|
|
}
|
|
|
|
public void setDecryptionKey(PrivateKey decryptionKey) {
|
|
this.decryptionKey = decryptionKey;
|
|
}
|
|
|
|
public void setSigningKeyPair(KeyPair signingKeyPair) {
|
|
this.signingKeyPair = signingKeyPair;
|
|
}
|
|
|
|
public void setAssertionConsumerServiceUrl(String assertionConsumerServiceUrl) {
|
|
this.assertionConsumerServiceUrl = assertionConsumerServiceUrl;
|
|
}
|
|
|
|
public void setRoleAttributeNames(Set<String> roleAttributeNames) {
|
|
this.roleAttributeNames = roleAttributeNames;
|
|
}
|
|
|
|
public void setPrincipalNamePolicy(PrincipalNamePolicy principalNamePolicy) {
|
|
this.principalNamePolicy = principalNamePolicy;
|
|
}
|
|
|
|
public void setPrincipalAttributeName(String principalAttributeName) {
|
|
this.principalAttributeName = principalAttributeName;
|
|
}
|
|
|
|
@Override
|
|
public String getLogoutPage() {
|
|
return logoutPage;
|
|
}
|
|
|
|
public void setLogoutPage(String logoutPage) {
|
|
this.logoutPage = logoutPage;
|
|
}
|
|
|
|
@Override
|
|
public String getSignatureCanonicalizationMethod() {
|
|
return signatureCanonicalizationMethod;
|
|
}
|
|
|
|
public void setSignatureCanonicalizationMethod(String signatureCanonicalizationMethod) {
|
|
this.signatureCanonicalizationMethod = signatureCanonicalizationMethod;
|
|
}
|
|
|
|
@Override
|
|
public SignatureAlgorithm getSignatureAlgorithm() {
|
|
return signatureAlgorithm;
|
|
}
|
|
|
|
public void setSignatureAlgorithm(SignatureAlgorithm signatureAlgorithm) {
|
|
this.signatureAlgorithm = signatureAlgorithm;
|
|
}
|
|
}
|