[KEYCLOAK-12873] Fix differences between keycloak-saml.xml (adapter) and the keycloak-saml subsystem
This commit is contained in:
parent
5d1fa8719e
commit
d943b8a9e3
25 changed files with 1615 additions and 135 deletions
|
@ -32,6 +32,7 @@ public class Constants {
|
|||
static final String KEEP_DOM_ASSERTION = "keepDOMAssertion";
|
||||
static final String IS_PASSIVE = "isPassive";
|
||||
static final String TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN = "turnOffChangeSessionIdOnLogin";
|
||||
static final String AUTODETECT_BEARER_ONLY = "autodetectBearerOnly";
|
||||
static final String ROLE_ATTRIBUTES = "RoleIdentifiers";
|
||||
static final String SIGNING = "signing";
|
||||
static final String ENCRYPTION = "encryption";
|
||||
|
@ -62,6 +63,7 @@ public class Constants {
|
|||
static final String PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME = "PrincipalNameMapping-attribute-name";
|
||||
static final String SIGNATURE_ALGORITHM = "signatureAlgorithm";
|
||||
static final String SIGNATURE_CANONICALIZATION_METHOD = "signatureCanonicalizationMethod";
|
||||
static final String METADATA_URL = "metadataUrl";
|
||||
static final String PRIVATE_KEY_PEM = "PrivateKeyPem";
|
||||
static final String PUBLIC_KEY_PEM = "PublicKeyPem";
|
||||
static final String CERTIFICATE_PEM = "CertificatePem";
|
||||
|
@ -70,12 +72,25 @@ public class Constants {
|
|||
static final String FILE = "file";
|
||||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||
|
||||
// role mappings provider model constants.
|
||||
static final String ROLE_MAPPINGS_PROVIDER_ID = "roleMappingsProviderId";
|
||||
static final String ROLE_MAPPINGS_PROVIDER_CONFIG = "roleMappingsProviderConfig";
|
||||
|
||||
// allowed clock skew model constants
|
||||
static final String ALLOWED_CLOCK_SKEW = "AllowedClockSkew";
|
||||
static final String ALLOWED_CLOCK_SKEW_UNIT = "unit";
|
||||
static final String ALLOWED_CLOCK_SKEW_VALUE = "value";
|
||||
|
||||
// http client model constants
|
||||
static final String HTTP_CLIENT = "HttpClient";
|
||||
static final String ALLOW_ANY_HOSTNAME = "allowAnyHostname";
|
||||
static final String CLIENT_KEYSTORE = "clientKeystore";
|
||||
static final String CLIENT_KEYSTORE_PASSWORD = "clientKeystorePassword";
|
||||
static final String CONNECTION_POOL_SIZE = "connectionPoolSize";
|
||||
static final String DISABLE_TRUST_MANAGER = "disableTrustManager";
|
||||
static final String PROXY_URL = "proxyUrl";
|
||||
static final String TRUSTSTORE = "truststore";
|
||||
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
|
||||
}
|
||||
|
||||
static class XML {
|
||||
|
@ -101,6 +116,7 @@ public class Constants {
|
|||
static final String CERTIFICATE = "Certificate";
|
||||
static final String IS_PASSIVE = "isPassive";
|
||||
static final String TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN = "turnOffChangeSessionIdOnLogin";
|
||||
static final String AUTODETECT_BEARER_ONLY = "autodetectBearerOnly";
|
||||
|
||||
static final String PRIVATE_KEY_ALIAS = "alias";
|
||||
static final String PRIVATE_KEY_PASSWORD = "password";
|
||||
|
@ -124,6 +140,7 @@ public class Constants {
|
|||
static final String ATTRIBUTE = "Attribute";
|
||||
static final String SIGNATURE_ALGORITHM = "signatureAlgorithm";
|
||||
static final String SIGNATURE_CANONICALIZATION_METHOD = "signatureCanonicalizationMethod";
|
||||
static final String METADATA_URL = "metadataUrl";
|
||||
static final String PRIVATE_KEY_PEM = "PrivateKeyPem";
|
||||
static final String PUBLIC_KEY_PEM = "PublicKeyPem";
|
||||
static final String CERTIFICATE_PEM = "CertificatePem";
|
||||
|
@ -133,12 +150,25 @@ public class Constants {
|
|||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||
static final String ASSERTION_CONSUMER_SERVICE_URL = "assertionConsumerServiceUrl";
|
||||
|
||||
// role mappings provider XML constants
|
||||
static final String ID = "id";
|
||||
static final String VALUE = "value";
|
||||
static final String PROPERTY = "Property";
|
||||
static final String ROLE_MAPPINGS_PROVIDER = "RoleMappingsProvider";
|
||||
|
||||
// allowed clock skew XML constants
|
||||
static final String ALLOWED_CLOCK_SKEW = "AllowedClockSkew";
|
||||
static final String ALLOWED_CLOCK_SKEW_UNIT = "unit";
|
||||
|
||||
// http client XML constants
|
||||
static final String HTTP_CLIENT = "HttpClient";
|
||||
static final String ALLOW_ANY_HOSTNAME = "allowAnyHostname";
|
||||
static final String CLIENT_KEYSTORE = "clientKeystore";
|
||||
static final String CLIENT_KEYSTORE_PASSWORD = "clientKeystorePassword";
|
||||
static final String CONNECTION_POOL_SIZE = "connectionPoolSize";
|
||||
static final String DISABLE_TRUST_MANAGER = "disableTrustManager";
|
||||
static final String PROXY_URL = "proxyUrl";
|
||||
static final String TRUSTSTORE = "truststore";
|
||||
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2020 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.subsystem.saml.as7;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
import org.jboss.dmr.ModelType;
|
||||
|
||||
/**
|
||||
* This class contains the definitions for the {@code HttpClient} attributes, as specified in the schema's {@code http-client-type}
|
||||
* complex type.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
abstract class HttpClientDefinition {
|
||||
|
||||
private static final SimpleAttributeDefinition ALLOW_ANY_HOSTNAME =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.ALLOW_ANY_HOSTNAME, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.ALLOW_ANY_HOSTNAME)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition CLIENT_KEYSTORE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.CLIENT_KEYSTORE, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.CLIENT_KEYSTORE)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition CLIENT_KEYSTORE_PASSWORD =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.CLIENT_KEYSTORE_PASSWORD, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.CLIENT_KEYSTORE_PASSWORD)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition CONNECTION_POOL_SIZE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.CONNECTION_POOL_SIZE, ModelType.INT, true)
|
||||
.setXmlName(Constants.XML.CONNECTION_POOL_SIZE)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition DISABLE_TRUST_MANAGER =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.DISABLE_TRUST_MANAGER, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.DISABLE_TRUST_MANAGER)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition PROXY_URL =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.PROXY_URL, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.PROXY_URL)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition TRUSTSTORE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.TRUSTSTORE, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.TRUSTSTORE)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition TRUSTSTORE_PASSWORD =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.TRUSTSTORE_PASSWORD, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.TRUSTSTORE_PASSWORD)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {ALLOW_ANY_HOSTNAME, CLIENT_KEYSTORE, CLIENT_KEYSTORE_PASSWORD,
|
||||
CONNECTION_POOL_SIZE, DISABLE_TRUST_MANAGER, PROXY_URL, TRUSTSTORE, TRUSTSTORE_PASSWORD};
|
||||
|
||||
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (SimpleAttributeDefinition def : ATTRIBUTES) {
|
||||
ATTRIBUTE_MAP.put(def.getXmlName(), def);
|
||||
}
|
||||
}
|
||||
|
||||
static SimpleAttributeDefinition lookup(String xmlName) {
|
||||
return ATTRIBUTE_MAP.get(xmlName);
|
||||
}
|
||||
}
|
|
@ -36,44 +36,57 @@ import java.util.HashMap;
|
|||
*/
|
||||
public class IdentityProviderDefinition extends SimpleResourceDefinition {
|
||||
|
||||
static final SimpleAttributeDefinition SIGNATURES_REQUIRED =
|
||||
private static final SimpleAttributeDefinition SIGNATURES_REQUIRED =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURES_REQUIRED, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.SIGNATURES_REQUIRED)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition SIGNATURE_ALGORITHM =
|
||||
private static final SimpleAttributeDefinition SIGNATURE_ALGORITHM =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_ALGORITHM, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.SIGNATURE_ALGORITHM)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition SIGNATURE_CANONICALIZATION_METHOD =
|
||||
private static final SimpleAttributeDefinition SIGNATURE_CANONICALIZATION_METHOD =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_CANONICALIZATION_METHOD, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.SIGNATURE_CANONICALIZATION_METHOD)
|
||||
.build();
|
||||
|
||||
static final ObjectTypeAttributeDefinition SINGLE_SIGN_ON =
|
||||
private static final SimpleAttributeDefinition METADATA_URL =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.METADATA_URL, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.METADATA_URL)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final ObjectTypeAttributeDefinition SINGLE_SIGN_ON =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_SIGN_ON,
|
||||
SingleSignOnDefinition.ATTRIBUTES)
|
||||
.setAllowNull(false)
|
||||
.build();
|
||||
|
||||
static final ObjectTypeAttributeDefinition SINGLE_LOGOUT =
|
||||
private static final ObjectTypeAttributeDefinition SINGLE_LOGOUT =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_LOGOUT,
|
||||
SingleLogoutDefinition.ATTRIBUTES)
|
||||
.setAllowNull(false)
|
||||
.build();
|
||||
|
||||
static final ObjectTypeAttributeDefinition ALLOWED_CLOCK_SKEW =
|
||||
private static final ObjectTypeAttributeDefinition ALLOWED_CLOCK_SKEW =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.ALLOWED_CLOCK_SKEW,
|
||||
AllowedClockSkew.ATTRIBUTES)
|
||||
.setAllowNull(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD};
|
||||
private static final ObjectTypeAttributeDefinition HTTP_CLIENT =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.HTTP_CLIENT,
|
||||
HttpClientDefinition.ATTRIBUTES)
|
||||
.setAllowNull(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, SINGLE_SIGN_ON, SINGLE_LOGOUT, ALLOWED_CLOCK_SKEW};
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, METADATA_URL};
|
||||
|
||||
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, METADATA_URL,
|
||||
SINGLE_SIGN_ON, SINGLE_LOGOUT, ALLOWED_CLOCK_SKEW, HTTP_CLIENT};
|
||||
|
||||
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
|
||||
|
|
|
@ -35,17 +35,19 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUB
|
|||
*/
|
||||
public class KeycloakSamlExtension implements Extension {
|
||||
|
||||
public static final String SUBSYSTEM_NAME = "keycloak-saml";
|
||||
public static final String NAMESPACE_1_1 = "urn:jboss:domain:keycloak-saml:1.1";
|
||||
public static final String NAMESPACE_1_2 = "urn:jboss:domain:keycloak-saml:1.2";
|
||||
public static final String CURRENT_NAMESPACE = NAMESPACE_1_2;
|
||||
static final String SUBSYSTEM_NAME = "keycloak-saml";
|
||||
private static final String NAMESPACE_1_1 = "urn:jboss:domain:keycloak-saml:1.1";
|
||||
private static final String NAMESPACE_1_2 = "urn:jboss:domain:keycloak-saml:1.2";
|
||||
private static final String NAMESPACE_1_3 = "urn:jboss:domain:keycloak-saml:1.3";
|
||||
|
||||
static final String CURRENT_NAMESPACE = NAMESPACE_1_3;
|
||||
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
|
||||
static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
||||
private static final String RESOURCE_NAME = KeycloakSamlExtension.class.getPackage().getName() + ".LocalDescriptions";
|
||||
private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1, 1, 0);
|
||||
static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
||||
|
||||
public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
||||
static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
||||
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
|
||||
for (String kp : keyPrefix) {
|
||||
prefix.append('.').append(kp);
|
||||
|
@ -60,6 +62,7 @@ public class KeycloakSamlExtension implements Extension {
|
|||
public void initializeParsers(final ExtensionParsingContext context) {
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakSamlExtension.NAMESPACE_1_1, PARSER);
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakSamlExtension.NAMESPACE_1_2, PARSER);
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakSamlExtension.NAMESPACE_1_3, PARSER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -161,6 +161,8 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
readSingleLogout(addIdentityProvider, reader);
|
||||
} else if (Constants.XML.KEYS.equals(tagName)) {
|
||||
readKeys(list, reader, addr);
|
||||
} else if (Constants.XML.HTTP_CLIENT.equals(tagName)) {
|
||||
readHttpClient(addIdentityProvider, reader);
|
||||
} else if (Constants.XML.ALLOWED_CLOCK_SKEW.equals(tagName)) {
|
||||
readAllowedClockSkew(addIdentityProvider, reader);
|
||||
} else {
|
||||
|
@ -212,6 +214,21 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
list.addAll(keyList);
|
||||
}
|
||||
|
||||
void readHttpClient(final ModelNode addIdentityProvider, final XMLExtendedStreamReader reader) throws XMLStreamException {
|
||||
ModelNode httpClientNode = addIdentityProvider.get(Constants.Model.HTTP_CLIENT);
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++) {
|
||||
String name = reader.getAttributeLocalName(i);
|
||||
String value = reader.getAttributeValue(i);
|
||||
|
||||
SimpleAttributeDefinition attr = HttpClientDefinition.lookup(name);
|
||||
if (attr == null) {
|
||||
throw ParseUtils.unexpectedAttribute(reader, i);
|
||||
}
|
||||
attr.parseAndSetParameter(value, httpClientNode, reader);
|
||||
}
|
||||
ParseUtils.requireNoContent(reader);
|
||||
}
|
||||
|
||||
void readAllowedClockSkew(ModelNode addIdentityProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
|
||||
ModelNode allowedClockSkew = addIdentityProvider.get(Constants.Model.ALLOWED_CLOCK_SKEW);
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++) {
|
||||
|
@ -481,6 +498,7 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
writeSingleSignOn(writer, idpAttributes.get(Constants.Model.SINGLE_SIGN_ON));
|
||||
writeSingleLogout(writer, idpAttributes.get(Constants.Model.SINGLE_LOGOUT));
|
||||
writeKeys(writer, idpAttributes.get(Constants.Model.KEY));
|
||||
writeHttpClient(writer, idpAttributes.get(Constants.Model.HTTP_CLIENT));
|
||||
writeAllowedClockSkew(writer, idpAttributes.get(Constants.Model.ALLOWED_CLOCK_SKEW));
|
||||
}
|
||||
writer.writeEndElement();
|
||||
|
@ -536,6 +554,16 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
}
|
||||
}
|
||||
|
||||
void writeHttpClient(XMLExtendedStreamWriter writer, ModelNode httpClientModel) throws XMLStreamException {
|
||||
if (!httpClientModel.isDefined()) {
|
||||
return;
|
||||
}
|
||||
writer.writeStartElement(Constants.XML.HTTP_CLIENT);
|
||||
for (SimpleAttributeDefinition attr : HttpClientDefinition.ATTRIBUTES) {
|
||||
attr.marshallAsAttribute(httpClientModel, false, writer);
|
||||
}
|
||||
writer.writeEndElement();
|
||||
}
|
||||
void writeAllowedClockSkew(XMLExtendedStreamWriter writer, ModelNode allowedClockSkew) throws XMLStreamException {
|
||||
if (!allowedClockSkew.isDefined()) {
|
||||
return;
|
||||
|
|
|
@ -40,40 +40,47 @@ import java.util.HashMap;
|
|||
*/
|
||||
public class ServiceProviderDefinition extends SimpleResourceDefinition {
|
||||
|
||||
static final SimpleAttributeDefinition SSL_POLICY =
|
||||
private static final SimpleAttributeDefinition SSL_POLICY =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SSL_POLICY, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.SSL_POLICY)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition NAME_ID_POLICY_FORMAT =
|
||||
private static final SimpleAttributeDefinition NAME_ID_POLICY_FORMAT =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.NAME_ID_POLICY_FORMAT, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.NAME_ID_POLICY_FORMAT)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition LOGOUT_PAGE =
|
||||
private static final SimpleAttributeDefinition LOGOUT_PAGE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.LOGOUT_PAGE, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.LOGOUT_PAGE)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition FORCE_AUTHENTICATION =
|
||||
private static final SimpleAttributeDefinition FORCE_AUTHENTICATION =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.FORCE_AUTHENTICATION, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.FORCE_AUTHENTICATION)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition KEEP_DOM_ASSERTION =
|
||||
private static final SimpleAttributeDefinition KEEP_DOM_ASSERTION =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.KEEP_DOM_ASSERTION, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.KEEP_DOM_ASSERTION)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition IS_PASSIVE =
|
||||
private static final SimpleAttributeDefinition IS_PASSIVE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.IS_PASSIVE, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.IS_PASSIVE)
|
||||
.build();
|
||||
static final SimpleAttributeDefinition TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN =
|
||||
|
||||
private static final SimpleAttributeDefinition TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition AUTODETECT_BEARER_ONLY =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.AUTODETECT_BEARER_ONLY, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.AUTODETECT_BEARER_ONLY)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition PRINCIPAL_NAME_MAPPING_POLICY =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.PRINCIPAL_NAME_MAPPING_POLICY, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY)
|
||||
|
@ -101,13 +108,13 @@ public class ServiceProviderDefinition extends SimpleResourceDefinition {
|
|||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SSL_POLICY, NAME_ID_POLICY_FORMAT, LOGOUT_PAGE, FORCE_AUTHENTICATION,
|
||||
IS_PASSIVE, TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN, KEEP_DOM_ASSERTION};
|
||||
IS_PASSIVE, TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN, KEEP_DOM_ASSERTION, AUTODETECT_BEARER_ONLY};
|
||||
static final AttributeDefinition[] ELEMENTS = {PRINCIPAL_NAME_MAPPING_POLICY, PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, ROLE_ATTRIBUTES,
|
||||
ROLE_MAPPINGS_PROVIDER_ID, ROLE_MAPPINGS_PROVIDER_CONFIG};
|
||||
|
||||
|
||||
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
static final HashMap<String, AttributeDefinition> ALL_MAP = new HashMap<>();
|
||||
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
private static final HashMap<String, AttributeDefinition> ALL_MAP = new HashMap<>();
|
||||
static final Collection<AttributeDefinition> ALL_ATTRIBUTES;
|
||||
|
||||
static {
|
||||
|
|
|
@ -35,6 +35,7 @@ keycloak-saml.SP.forceAuthentication=Redirected unauthenticated request to a log
|
|||
keycloak-saml.SP.keepDOMAssertion=Attribute to inject the DOM representation of the assertion into the SamlPrincipal (respecting the original syntax)
|
||||
keycloak-saml.SP.isPassive=If user isn't logged in just return with an error. Used to check if a user is already logged in or not
|
||||
keycloak-saml.SP.turnOffChangeSessionIdOnLogin=The session id is changed by default on a successful login. Change this to true if you want to turn this off
|
||||
keycloak-saml.SP.autodetectBearerOnly=Set to true if the application serves both a web application and web services (e.g. SOAP or REST). It allows redirection of unauthenticated users of the web application to the Keycloak login page, but send an HTTP 401 status code to unauthenticated SOAP or REST clients instead
|
||||
keycloak-saml.SP.RoleIdentifiers=Role identifiers
|
||||
keycloak-saml.SP.PrincipalNameMapping-policy=Principal name mapping policy
|
||||
keycloak-saml.SP.PrincipalNameMapping-attribute-name=Principal name mapping attribute name
|
||||
|
@ -68,6 +69,7 @@ keycloak-saml.IDP.remove=Remove an identity provider
|
|||
keycloak-saml.IDP.signaturesRequired=Require signatures for SingleSignOnService and SingleLogoutService
|
||||
keycloak-saml.IDP.signatureAlgorithm=Signature algorithm
|
||||
keycloak-saml.IDP.signatureCanonicalizationMethod=Signature canonicalization method
|
||||
keycloak-saml.IDP.metadataUrl=The URL used to retrieve the IDP metadata from
|
||||
keycloak-saml.IDP.SingleSignOnService=Single sign-on configuration
|
||||
keycloak-saml.IDP.SingleSignOnService.signRequest=Sign SSO requests
|
||||
keycloak-saml.IDP.SingleSignOnService.validateResponseSignature=Validate an SSO response signature
|
||||
|
@ -89,3 +91,12 @@ keycloak-saml.IDP.Key=Key definition for identity provider
|
|||
keycloak-saml.IDP.AllowedClockSkew=Allowed clock skew between the IDP and the SP
|
||||
keycloak-saml.IDP.AllowedClockSkew.value=Allowed clock skew value between the IDP and the SP
|
||||
keycloak-saml.IDP.AllowedClockSkew.unit=Time unit for the value of the clock skew. Values: MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS
|
||||
keycloak-saml.IDP.HttpClient=Configuration of HTTP client used for automatic retrieval of certificates for signature validation
|
||||
keycloak-saml.IDP.HttpClient.allowAnyHostname=Define if hostname validation should be disabled (true) or not (false)
|
||||
keycloak-saml.IDP.HttpClient.clientKeystore=Path to the keystore that contains client certificates for two-way SSL
|
||||
keycloak-saml.IDP.HttpClient.clientKeystorePassword=The keystore password
|
||||
keycloak-saml.IDP.HttpClient.connectionPoolSize=The number of pooled connections
|
||||
keycloak-saml.IDP.HttpClient.disableTrustManager=Define if SSL certificate validation should be disabled (true) or not (false)
|
||||
keycloak-saml.IDP.HttpClient.proxyUrl=URL to the HTTP proxy, if applicable
|
||||
keycloak-saml.IDP.HttpClient.truststore=Path to the truststore used to validate the IDP certificates
|
||||
keycloak-saml.IDP.HttpClient.truststorePassword=The truststore password
|
|
@ -0,0 +1,570 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright 2020 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.autodetect
|
||||
-->
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="urn:jboss:domain:keycloak-saml:1.3"
|
||||
xmlns="urn:jboss:domain:keycloak-saml:1.3"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified"
|
||||
version="1.0">
|
||||
|
||||
<!-- The subsystem root element -->
|
||||
<xs:element name="subsystem" type="subsystem-type"/>
|
||||
|
||||
<xs:complexType name="subsystem-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<![CDATA[
|
||||
The Keycloak SAML adapter subsystem, used to register deployments managed by Keycloak SAML adapter
|
||||
]]>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:all>
|
||||
<xs:element name="secure-deployment" minOccurs="0" type="secure-deployment-type"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="secure-deployment-type">
|
||||
<xs:all>
|
||||
<xs:element name="SP" minOccurs="0" maxOccurs="1" type="sp-type"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name of the deployment</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="sp-type">
|
||||
<xs:all>
|
||||
<xs:element name="Keys" type="keys-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
List of service provider encryption and validation keys.
|
||||
|
||||
If the IDP requires that the client application (SP) sign all of its requests and/or if the IDP will encrypt assertions, you must define the keys used to do this. For client signed documents you must define both the private and public key or certificate that will be used to sign documents. For encryption, you only have to define the private key that will be used to decrypt.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="PrincipalNameMapping" type="principal-name-mapping-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>When creating a Java Principal object that you obtain from methods like HttpServletRequest.getUserPrincipal(), you can define what name that is returned by the Principal.getName() method.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="RoleIdentifiers" type="role-identifiers-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines what SAML attributes within the assertion received from the user should be used as role identifiers within the Java EE Security Context for the user.
|
||||
By default Role attribute values are converted to Java EE roles. Some IDPs send roles via a member or memberOf attribute assertion. You can define one or more Attribute elements to specify which SAML attributes must be converted into roles.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="RoleMappingsProvider" type="role-mappings-provider-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies the role mappings provider implementation that will be used to map the roles extracted from the SAML assertion into the final set of roles
|
||||
that will be assigned to the principal. A provider is typically used to map roles retrieved from third party IDPs into roles that exist in the JEE application environment. It can also
|
||||
assign extra roles to the assertion principal (for example, by connecting to an LDAP server to obtain more roles) or remove some of the roles that were set by the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="IDP" type="idp-type" minOccurs="1" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Describes configuration of SAML identity provider for this service provider.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="entityID" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the identifier for this client. The IDP needs this value to determine who the client is that is communicating with it.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="sslPolicy" type="ssl-policy-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SSL policy the adapter will enforce.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="nameIDPolicyFormat" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML clients can request a specific NameID Subject format. Fill in this value if you want a specific format. It must be a standard SAML format identifier, i.e. urn:oasis:names:tc:SAML:2.0:nameid-format:transient. By default, no special format is requested.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="logoutPage" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>URL of the logout page.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="forceAuthentication" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML clients can request that a user is re-authenticated even if they are already logged in at the IDP. Default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="keepDOMAssertion" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Attribute to inject the DOM representation of the assertion into the SamlPrincipal (respecting the original syntax). Default value is false</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="isPassive" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML clients can request that a user is never asked to authenticate even if they are not logged in at the IDP. Set this to true if you want this. Do not use together with forceAuthentication as they are opposite. Default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="turnOffChangeSessionIdOnLogin" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The session id is changed by default on a successful login on some platforms to plug a security attack vector. Change this to true to disable this. It is recommended you do not turn it off. Default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="autodetectBearerOnly" type="xs:boolean" use="optional" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This should be set to true if your application serves both a web application and web services (e.g. SOAP or REST). It allows you to redirect unauthenticated users of the web application to the Keycloak login page, but send an HTTP 401 status code to unauthenticated SOAP or REST clients instead as they would not understand a redirect to the login page. Keycloak auto-detects SOAP or REST clients based on typical headers like X-Requested-With, SOAPAction or Accept. The default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="keys-type">
|
||||
<xs:sequence>
|
||||
<xs:element name="Key" type="key-type" minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Describes a single key used for signing or encryption.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="key-type">
|
||||
<xs:all>
|
||||
<xs:element name="KeyStore" maxOccurs="1" minOccurs="0" type="key-store-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Java keystore to load keys and certificates from.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="PrivateKeyPem" type="xs:string" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Private key (PEM format)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="PublicKeyPem" type="xs:string" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Public key (PEM format)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="CertificatePem" type="xs:string" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Certificate key (PEM format)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="signing" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Flag defining whether the key should be used for signing.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="encryption" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Flag defining whether the key should be used for encryption</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="key-store-type">
|
||||
<xs:all>
|
||||
<xs:element name="PrivateKey" maxOccurs="1" minOccurs="0" type="private-key-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Private key declaration</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Certificate" type="certificate-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Certificate declaration</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="file" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>File path to the key store.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="resource" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>WAR resource path to the key store. This is a path used in method call to ServletContext.getResourceAsStream().</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="password" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The password of the key store.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="type" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Key store format</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="alias" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Key alias</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="private-key-type">
|
||||
<xs:attribute name="alias" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Alias that points to the key or cert within the keystore.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="password" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Keystores require an additional password to access private keys. In the PrivateKey element you must define this password within a password attribute.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="certificate-type">
|
||||
<xs:attribute name="alias" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Alias that points to the key or cert within the keystore.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="principal-name-mapping-type">
|
||||
<xs:attribute name="policy" type="principal-name-mapping-policy-type" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Policy used to populate value of Java Principal object obtained from methods like HttpServletRequest.getUserPrincipal().</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="attribute" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Name of the SAML assertion attribute to use within.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="principal-name-mapping-policy-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="FROM_NAME_ID">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This policy just uses whatever the SAML subject value is. This is the default setting</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="FROM_ATTRIBUTE">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This will pull the value from one of the attributes declared in the SAML assertion received from the server. You'll need to specify the name of the SAML assertion attribute to use within the attribute XML attribute.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="ssl-policy-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="ALL">
|
||||
<xs:annotation>
|
||||
<xs:documentation>All requests must come in via HTTPS.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="EXTERNAL">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Only non-private IP addresses must come over the wire via HTTPS.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="NONE">
|
||||
<xs:annotation>
|
||||
<xs:documentation>no requests are required to come over via HTTPS.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="signature-algorithm-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="RSA_SHA1"/>
|
||||
<xs:enumeration value="RSA_SHA256"/>
|
||||
<xs:enumeration value="RSA_SHA512"/>
|
||||
<xs:enumeration value="DSA_SHA1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="binding-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="POST"/>
|
||||
<xs:enumeration value="REDIRECT"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="role-identifiers-type">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="Attribute" maxOccurs="unbounded" minOccurs="0" type="attribute-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies SAML attribute to be converted into roles.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="attribute-type">
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies name of the SAML attribute to be converted into roles.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="role-mappings-provider-type">
|
||||
<xs:sequence>
|
||||
<xs:element name="Property" type="property-type" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies a configuration property for the provider.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="id" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The id of the role mappings provider that is to be used. Example: properties-based-provider.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="property-type">
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name (key) of the configuration property.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="value" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The value of the configuration property.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="idp-type">
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="SingleSignOnService" maxOccurs="1" minOccurs="1" type="sign-on-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Configuration of the login SAML endpoint of the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="SingleLogoutService" type="logout-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Configuration of the logout SAML endpoint of the IDP</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Keys" type="keys-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The Keys sub element of IDP is only used to define the certificate or public key to use to verify documents signed by the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="HttpClient" type="http-client-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Configuration of HTTP client used for automatic obtaining of certificates containing public keys for IDP signature verification via SAML descriptor of the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="AllowedClockSkew" type="allowed-clock-skew-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This defines the allowed clock skew between IDP and SP in milliseconds. The default value is 0.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="entityID" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>issuer ID of the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signaturesRequired" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If set to true, the client adapter will sign every document it sends to the IDP. Also, the client will expect that the IDP will be signing any documents sent to it. This switch sets the default for all request and response types.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signatureAlgorithm" type="signature-algorithm-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Signature algorithm that the IDP expects signed documents to use. Defaults to RSA_SHA256</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signatureCanonicalizationMethod" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the signature canonicalization method that the IDP expects signed documents to use. The default value is https://www.w3.org/2001/10/xml-exc-c14n# and should be good for most IDPs.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="encryption" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation></xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="metadataUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The URL used to retrieve the IDP metadata, currently this is only used to pick up signing and encryption keys periodically which allow cycling of these keys on the IDP without manual changes on the SP side.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="sign-on-type">
|
||||
<xs:attribute name="signRequest" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client sign authn requests? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect the IDP to sign the assertion response document sent back from an auhtn request? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateAssertionSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect the IDP to sign the individual assertions sent back from an auhtn request? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="requestBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML binding type used for communicating with the IDP. The default value is POST, but you can set it to REDIRECT as well.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="responseBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML allows the client to request what binding type it wants authn responses to use. This value maps to ProtocolBinding attribute in SAML AuthnRequest. The default is that the client will not request a specific binding type for responses.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="bindingUrl" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the URL for the IDP login service that the client will send requests to.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="assertionConsumerServiceUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>URL of the assertion consumer service (ACS) where the IDP login service should send responses to. By default it is unset, relying on the IdP settings. When set, it must end in "/saml". This property is typically accompanied by the responseBinding attribute.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="logout-type">
|
||||
<xs:attribute name="signRequest" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client sign authn requests? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signResponse" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client sign logout responses it sends to the IDP requests? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateRequestSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect signed logout request documents from the IDP? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect signed logout response documents from the IDP? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="requestBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the SAML binding type used for communicating SAML requests to the IDP. The default value is POST.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="responseBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the SAML binding type used for communicating SAML responses to the IDP. The default value is POST.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="postBindingUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the URL for the IDP's logout service when using the POST binding. This setting is REQUIRED if using the POST binding.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="redirectBindingUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the URL for the IDP's logout service when using the REDIRECT binding. This setting is REQUIRED if using the REDIRECT binding.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="http-client-type">
|
||||
<xs:attribute name="allowAnyHostname" type="xs:boolean" use="optional" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If the the IDP server requires HTTPS and this config option is set to true the IDP's certificate
|
||||
is validated via the truststore, but host name validation is not done. This setting should only be used during
|
||||
development and never in production as it will partly disable verification of SSL certificates.
|
||||
This seting may be useful in test environments. The default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="clientKeystore" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the file path to a keystore file. This keystore contains client certificate
|
||||
for two-way SSL when the adapter makes HTTPS requests to the IDP server.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="clientKeystorePassword" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Password for the client keystore and for the client's key.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="connectionPoolSize" type="xs:int" use="optional" default="10">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines number of pooled connections.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="disableTrustManager" type="xs:boolean" use="optional" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If the the IDP server requires HTTPS and this config option is set to true you do not have to specify a truststore.
|
||||
This setting should only be used during development and never in production as it will disable verification of SSL certificates.
|
||||
The default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="proxyUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>URL to HTTP proxy to use for HTTP connections.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="truststore" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="truststorePassword" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Password for the truststore keystore.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="allowed-clock-skew-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The value is the allowed clock skew between the IDP and the SP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:positiveInteger">
|
||||
<xs:attribute name="unit" type="clock-skew-unit-type"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="clock-skew-unit-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Time unit for the value of the clock skew.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="MINUTES" />
|
||||
<xs:enumeration value="SECONDS" />
|
||||
<xs:enumeration value="MILLISECONDS" />
|
||||
<xs:enumeration value="MICROSECONDS" />
|
||||
<xs:enumeration value="NANOSECONDS" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
</xs:schema>
|
|
@ -76,7 +76,7 @@ public class SubsystemParsingAllowedClockSkewTestCase extends AbstractSubsystemB
|
|||
|
||||
private void setSubsystemXml(String value, String unit) throws IOException {
|
||||
try {
|
||||
String template = readResource("keycloak-saml-1.2.xml");
|
||||
String template = readResource("keycloak-saml-1.3.xml");
|
||||
if (value != null) {
|
||||
// assign the AllowedClockSkew element using DOM
|
||||
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
|
|
|
@ -34,6 +34,6 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
|||
|
||||
@Override
|
||||
protected String getSubsystemXml() throws IOException {
|
||||
return readResource("keycloak-saml-1.2.xml");
|
||||
return readResource("keycloak-saml-1.3.xml");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright 2019 Red Hat, Inc. and/or its affiliates
|
||||
~ Copyright 2020 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");
|
||||
|
@ -15,7 +15,7 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.2">
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.3">
|
||||
<secure-deployment name="my-app.war">
|
||||
<SP entityID="http://localhost:8080/sales-post-enc/"
|
||||
sslPolicy="EXTERNAL"
|
||||
|
@ -24,7 +24,8 @@
|
|||
keepDOMAssertion="false"
|
||||
forceAuthentication="false"
|
||||
isPassive="true"
|
||||
turnOffChangeSessionIdOnLogin="true">
|
||||
turnOffChangeSessionIdOnLogin="true"
|
||||
autodetectBearerOnly="false">
|
||||
|
||||
<Keys>
|
||||
<Key encryption="true" signing="true">
|
||||
|
@ -46,7 +47,11 @@
|
|||
<Property name="properties.file.location" value="test-roles.properties"/>
|
||||
<Property name="another.property" value="another.value"/>
|
||||
</RoleMappingsProvider>
|
||||
<IDP entityID="idp" signaturesRequired="true" signatureAlgorithm="test" signatureCanonicalizationMethod="test">
|
||||
<IDP entityID="idp"
|
||||
signaturesRequired="true"
|
||||
signatureAlgorithm="DSA_SHA1"
|
||||
signatureCanonicalizationMethod="test"
|
||||
metadataUrl="http://localhost:8080/metadata">
|
||||
<SingleSignOnService signRequest="true"
|
||||
validateResponseSignature="true"
|
||||
validateAssertionSignature="true"
|
||||
|
@ -70,6 +75,14 @@
|
|||
</KeyStore>
|
||||
</Key>
|
||||
</Keys>
|
||||
<HttpClient allowAnyHostname="false"
|
||||
clientKeystore="/tmp/keystore.jks"
|
||||
clientKeystorePassword="testpwd1!@"
|
||||
connectionPoolSize="20"
|
||||
disableTrustManager="false"
|
||||
proxyUrl="http://localhost:9090/proxy"
|
||||
truststore="/tmp/truststore.jks"
|
||||
truststorePassword="trustpwd#*"/>
|
||||
</IDP>
|
||||
</SP>
|
||||
</secure-deployment>
|
|
@ -190,6 +190,16 @@
|
|||
<xs:documentation>The password of the key store.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="type" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Key store format</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="alias" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Key alias</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
<xs:complexType name="private-key-type">
|
||||
<xs:attribute name="alias" type="xs:string" use="required">
|
||||
|
|
|
@ -33,6 +33,7 @@ public class Constants {
|
|||
static final String KEEP_DOM_ASSERTION = "keepDOMAssertion";
|
||||
static final String IS_PASSIVE = "isPassive";
|
||||
static final String TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN = "turnOffChangeSessionIdOnLogin";
|
||||
static final String AUTODETECT_BEARER_ONLY = "autodetectBearerOnly";
|
||||
static final String ROLE_ATTRIBUTES = "RoleIdentifiers";
|
||||
static final String SIGNING = "signing";
|
||||
static final String ENCRYPTION = "encryption";
|
||||
|
@ -64,6 +65,7 @@ public class Constants {
|
|||
static final String PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME = "PrincipalNameMapping-attribute-name";
|
||||
static final String SIGNATURE_ALGORITHM = "signatureAlgorithm";
|
||||
static final String SIGNATURE_CANONICALIZATION_METHOD = "signatureCanonicalizationMethod";
|
||||
static final String METADATA_URL = "metadataUrl";
|
||||
static final String PRIVATE_KEY_PEM = "PrivateKeyPem";
|
||||
static final String PUBLIC_KEY_PEM = "PublicKeyPem";
|
||||
static final String CERTIFICATE_PEM = "CertificatePem";
|
||||
|
@ -72,14 +74,26 @@ public class Constants {
|
|||
static final String FILE = "file";
|
||||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||
|
||||
// role mappings provider constants
|
||||
static final String ROLE_MAPPINGS_PROVIDER_ID = "roleMappingsProviderId";
|
||||
static final String ROLE_MAPPINGS_PROVIDER_CONFIG = "roleMappingsProviderConfig";
|
||||
|
||||
// allowed clock skew model constants
|
||||
static final String ALLOWED_CLOCK_SKEW = "AllowedClockSkew";
|
||||
static final String ALLOWED_CLOCK_SKEW_UNIT = "unit";
|
||||
static final String ALLOWED_CLOCK_SKEW_VALUE = "value";
|
||||
}
|
||||
|
||||
// http client model constants
|
||||
static final String HTTP_CLIENT = "HttpClient";
|
||||
static final String ALLOW_ANY_HOSTNAME = "allowAnyHostname";
|
||||
static final String CLIENT_KEYSTORE = "clientKeystore";
|
||||
static final String CLIENT_KEYSTORE_PASSWORD = "clientKeystorePassword";
|
||||
static final String CONNECTION_POOL_SIZE = "connectionPoolSize";
|
||||
static final String DISABLE_TRUST_MANAGER = "disableTrustManager";
|
||||
static final String PROXY_URL = "proxyUrl";
|
||||
static final String TRUSTSTORE = "truststore";
|
||||
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
|
||||
}
|
||||
|
||||
static class XML {
|
||||
static final String SECURE_DEPLOYMENT = "secure-deployment";
|
||||
|
@ -104,6 +118,7 @@ public class Constants {
|
|||
static final String CERTIFICATE = "Certificate";
|
||||
static final String IS_PASSIVE = "isPassive";
|
||||
static final String TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN = "turnOffChangeSessionIdOnLogin";
|
||||
static final String AUTODETECT_BEARER_ONLY = "autodetectBearerOnly";
|
||||
|
||||
static final String PRIVATE_KEY_ALIAS = "alias";
|
||||
static final String PRIVATE_KEY_PASSWORD = "password";
|
||||
|
@ -127,6 +142,7 @@ public class Constants {
|
|||
static final String ATTRIBUTE = "Attribute";
|
||||
static final String SIGNATURE_ALGORITHM = "signatureAlgorithm";
|
||||
static final String SIGNATURE_CANONICALIZATION_METHOD = "signatureCanonicalizationMethod";
|
||||
static final String METADATA_URL = "metadataUrl";
|
||||
static final String PRIVATE_KEY_PEM = "PrivateKeyPem";
|
||||
static final String PUBLIC_KEY_PEM = "PublicKeyPem";
|
||||
static final String CERTIFICATE_PEM = "CertificatePem";
|
||||
|
@ -136,13 +152,26 @@ public class Constants {
|
|||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||
static final String ASSERTION_CONSUMER_SERVICE_URL = "assertionConsumerServiceUrl";
|
||||
|
||||
// role mappings provider XML constants
|
||||
static final String ID = "id";
|
||||
static final String VALUE = "value";
|
||||
static final String PROPERTY = "Property";
|
||||
static final String ROLE_MAPPINGS_PROVIDER = "RoleMappingsProvider";
|
||||
|
||||
// allowed clock skew XML constants
|
||||
static final String ALLOWED_CLOCK_SKEW = "AllowedClockSkew";
|
||||
static final String ALLOWED_CLOCK_SKEW_UNIT = "unit";
|
||||
|
||||
// http client XML constants
|
||||
static final String HTTP_CLIENT = "HttpClient";
|
||||
static final String ALLOW_ANY_HOSTNAME = "allowAnyHostname";
|
||||
static final String CLIENT_KEYSTORE = "clientKeystore";
|
||||
static final String CLIENT_KEYSTORE_PASSWORD = "clientKeystorePassword";
|
||||
static final String CONNECTION_POOL_SIZE = "connectionPoolSize";
|
||||
static final String DISABLE_TRUST_MANAGER = "disableTrustManager";
|
||||
static final String PROXY_URL = "proxyUrl";
|
||||
static final String TRUSTSTORE = "truststore";
|
||||
static final String TRUSTSTORE_PASSWORD = "truststorePassword";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright 2020 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.subsystem.adapter.saml.extension;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.jboss.as.controller.SimpleAttributeDefinition;
|
||||
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
|
||||
import org.jboss.dmr.ModelType;
|
||||
|
||||
/**
|
||||
* This class contains the definitions for the {@code HttpClient} attributes, as specified in the schema's {@code http-client-type}
|
||||
* complex type.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
abstract class HttpClientDefinition {
|
||||
|
||||
private static final SimpleAttributeDefinition ALLOW_ANY_HOSTNAME =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.ALLOW_ANY_HOSTNAME, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.ALLOW_ANY_HOSTNAME)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition CLIENT_KEYSTORE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.CLIENT_KEYSTORE, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.CLIENT_KEYSTORE)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition CLIENT_KEYSTORE_PASSWORD =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.CLIENT_KEYSTORE_PASSWORD, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.CLIENT_KEYSTORE_PASSWORD)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition CONNECTION_POOL_SIZE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.CONNECTION_POOL_SIZE, ModelType.INT, true)
|
||||
.setXmlName(Constants.XML.CONNECTION_POOL_SIZE)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition DISABLE_TRUST_MANAGER =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.DISABLE_TRUST_MANAGER, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.DISABLE_TRUST_MANAGER)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition PROXY_URL =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.PROXY_URL, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.PROXY_URL)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition TRUSTSTORE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.TRUSTSTORE, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.TRUSTSTORE)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition TRUSTSTORE_PASSWORD =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.TRUSTSTORE_PASSWORD, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.TRUSTSTORE_PASSWORD)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {ALLOW_ANY_HOSTNAME, CLIENT_KEYSTORE, CLIENT_KEYSTORE_PASSWORD,
|
||||
CONNECTION_POOL_SIZE, DISABLE_TRUST_MANAGER, PROXY_URL, TRUSTSTORE, TRUSTSTORE_PASSWORD};
|
||||
|
||||
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (SimpleAttributeDefinition def : ATTRIBUTES) {
|
||||
ATTRIBUTE_MAP.put(def.getXmlName(), def);
|
||||
}
|
||||
}
|
||||
|
||||
static SimpleAttributeDefinition lookup(String xmlName) {
|
||||
return ATTRIBUTE_MAP.get(xmlName);
|
||||
}
|
||||
}
|
|
@ -36,44 +36,57 @@ import java.util.HashMap;
|
|||
*/
|
||||
public class IdentityProviderDefinition extends SimpleResourceDefinition {
|
||||
|
||||
static final SimpleAttributeDefinition SIGNATURES_REQUIRED =
|
||||
private static final SimpleAttributeDefinition SIGNATURES_REQUIRED =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURES_REQUIRED, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.SIGNATURES_REQUIRED)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition SIGNATURE_ALGORITHM =
|
||||
private static final SimpleAttributeDefinition SIGNATURE_ALGORITHM =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_ALGORITHM, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.SIGNATURE_ALGORITHM)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition SIGNATURE_CANONICALIZATION_METHOD =
|
||||
private static final SimpleAttributeDefinition SIGNATURE_CANONICALIZATION_METHOD =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_CANONICALIZATION_METHOD, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.SIGNATURE_CANONICALIZATION_METHOD)
|
||||
.build();
|
||||
|
||||
static final ObjectTypeAttributeDefinition SINGLE_SIGN_ON =
|
||||
private static final SimpleAttributeDefinition METADATA_URL =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.METADATA_URL, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.METADATA_URL)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
private static final ObjectTypeAttributeDefinition SINGLE_SIGN_ON =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_SIGN_ON,
|
||||
SingleSignOnDefinition.ATTRIBUTES)
|
||||
.setAllowNull(false)
|
||||
.build();
|
||||
|
||||
static final ObjectTypeAttributeDefinition SINGLE_LOGOUT =
|
||||
private static final ObjectTypeAttributeDefinition SINGLE_LOGOUT =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_LOGOUT,
|
||||
SingleLogoutDefinition.ATTRIBUTES)
|
||||
.setAllowNull(false)
|
||||
.build();
|
||||
|
||||
static final ObjectTypeAttributeDefinition ALLOWED_CLOCK_SKEW =
|
||||
private static final ObjectTypeAttributeDefinition ALLOWED_CLOCK_SKEW =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.ALLOWED_CLOCK_SKEW,
|
||||
AllowedClockSkew.ATTRIBUTES)
|
||||
.setAllowNull(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD};
|
||||
private static final ObjectTypeAttributeDefinition HTTP_CLIENT =
|
||||
ObjectTypeAttributeDefinition.Builder.of(Constants.Model.HTTP_CLIENT,
|
||||
HttpClientDefinition.ATTRIBUTES)
|
||||
.setAllowNull(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, SINGLE_SIGN_ON, SINGLE_LOGOUT, ALLOWED_CLOCK_SKEW};
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, METADATA_URL};
|
||||
|
||||
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, METADATA_URL,
|
||||
SINGLE_SIGN_ON, SINGLE_LOGOUT, ALLOWED_CLOCK_SKEW, HTTP_CLIENT};
|
||||
|
||||
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
|
||||
|
|
|
@ -35,17 +35,19 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUB
|
|||
*/
|
||||
public class KeycloakSamlExtension implements Extension {
|
||||
|
||||
public static final String SUBSYSTEM_NAME = "keycloak-saml";
|
||||
public static final String NAMESPACE_1_1 = "urn:jboss:domain:keycloak-saml:1.1";
|
||||
public static final String NAMESPACE_1_2 = "urn:jboss:domain:keycloak-saml:1.2";
|
||||
public static final String CURRENT_NAMESPACE = NAMESPACE_1_2;
|
||||
static final String SUBSYSTEM_NAME = "keycloak-saml";
|
||||
private static final String NAMESPACE_1_1 = "urn:jboss:domain:keycloak-saml:1.1";
|
||||
private static final String NAMESPACE_1_2 = "urn:jboss:domain:keycloak-saml:1.2";
|
||||
private static final String NAMESPACE_1_3 = "urn:jboss:domain:keycloak-saml:1.3";
|
||||
|
||||
static final String CURRENT_NAMESPACE = NAMESPACE_1_3;
|
||||
private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
|
||||
static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
||||
private static final String RESOURCE_NAME = KeycloakSamlExtension.class.getPackage().getName() + ".LocalDescriptions";
|
||||
private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1, 1, 0);
|
||||
static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
|
||||
|
||||
public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
||||
static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
|
||||
StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
|
||||
for (String kp : keyPrefix) {
|
||||
prefix.append('.').append(kp);
|
||||
|
@ -60,6 +62,7 @@ public class KeycloakSamlExtension implements Extension {
|
|||
public void initializeParsers(final ExtensionParsingContext context) {
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakSamlExtension.NAMESPACE_1_1, PARSER);
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakSamlExtension.NAMESPACE_1_2, PARSER);
|
||||
context.setSubsystemXmlMapping(SUBSYSTEM_NAME, KeycloakSamlExtension.NAMESPACE_1_3, PARSER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -159,6 +159,8 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
readSingleLogout(addIdentityProvider, reader);
|
||||
} else if (Constants.XML.KEYS.equals(tagName)) {
|
||||
readKeys(list, reader, addr);
|
||||
} else if (Constants.XML.HTTP_CLIENT.equals(tagName)) {
|
||||
readHttpClient(addIdentityProvider, reader);
|
||||
} else if (Constants.XML.ALLOWED_CLOCK_SKEW.equals(tagName)) {
|
||||
readAllowedClockSkew(addIdentityProvider, reader);
|
||||
} else {
|
||||
|
@ -210,6 +212,21 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
list.addAll(keyList);
|
||||
}
|
||||
|
||||
void readHttpClient(final ModelNode addIdentityProvider, final XMLExtendedStreamReader reader) throws XMLStreamException {
|
||||
ModelNode httpClientNode = addIdentityProvider.get(Constants.Model.HTTP_CLIENT);
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++) {
|
||||
String name = reader.getAttributeLocalName(i);
|
||||
String value = reader.getAttributeValue(i);
|
||||
|
||||
SimpleAttributeDefinition attr = HttpClientDefinition.lookup(name);
|
||||
if (attr == null) {
|
||||
throw ParseUtils.unexpectedAttribute(reader, i);
|
||||
}
|
||||
attr.parseAndSetParameter(value, httpClientNode, reader);
|
||||
}
|
||||
ParseUtils.requireNoContent(reader);
|
||||
}
|
||||
|
||||
void readAllowedClockSkew(ModelNode addIdentityProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
|
||||
ModelNode allowedClockSkew = addIdentityProvider.get(Constants.Model.ALLOWED_CLOCK_SKEW);
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++) {
|
||||
|
@ -479,6 +496,7 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
writeSingleSignOn(writer, idpAttributes.get(Constants.Model.SINGLE_SIGN_ON));
|
||||
writeSingleLogout(writer, idpAttributes.get(Constants.Model.SINGLE_LOGOUT));
|
||||
writeKeys(writer, idpAttributes.get(Constants.Model.KEY));
|
||||
writeHttpClient(writer, idpAttributes.get(Constants.Model.HTTP_CLIENT));
|
||||
writeAllowedClockSkew(writer, idpAttributes.get(Constants.Model.ALLOWED_CLOCK_SKEW));
|
||||
}
|
||||
writer.writeEndElement();
|
||||
|
@ -534,6 +552,17 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
|
|||
}
|
||||
}
|
||||
|
||||
void writeHttpClient(XMLExtendedStreamWriter writer, ModelNode httpClientModel) throws XMLStreamException {
|
||||
if (!httpClientModel.isDefined()) {
|
||||
return;
|
||||
}
|
||||
writer.writeStartElement(Constants.XML.HTTP_CLIENT);
|
||||
for (SimpleAttributeDefinition attr : HttpClientDefinition.ATTRIBUTES) {
|
||||
attr.marshallAsAttribute(httpClientModel, false, writer);
|
||||
}
|
||||
writer.writeEndElement();
|
||||
}
|
||||
|
||||
void writeAllowedClockSkew(XMLExtendedStreamWriter writer, ModelNode allowedClockSkew) throws XMLStreamException {
|
||||
if (!allowedClockSkew.isDefined()) {
|
||||
return;
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.keycloak.subsystem.adapter.saml.extension;
|
|||
|
||||
import org.jboss.as.controller.AttributeDefinition;
|
||||
import org.jboss.as.controller.AttributeMarshallers;
|
||||
import org.jboss.as.controller.AttributeParsers;
|
||||
import org.jboss.as.controller.ListAttributeDefinition;
|
||||
import org.jboss.as.controller.OperationStepHandler;
|
||||
import org.jboss.as.controller.PathElement;
|
||||
|
@ -42,40 +41,46 @@ import java.util.HashMap;
|
|||
*/
|
||||
public class ServiceProviderDefinition extends SimpleResourceDefinition {
|
||||
|
||||
static final SimpleAttributeDefinition SSL_POLICY =
|
||||
private static final SimpleAttributeDefinition SSL_POLICY =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.SSL_POLICY, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.SSL_POLICY)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition NAME_ID_POLICY_FORMAT =
|
||||
private static final SimpleAttributeDefinition NAME_ID_POLICY_FORMAT =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.NAME_ID_POLICY_FORMAT, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.NAME_ID_POLICY_FORMAT)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition LOGOUT_PAGE =
|
||||
private static final SimpleAttributeDefinition LOGOUT_PAGE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.LOGOUT_PAGE, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.LOGOUT_PAGE)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition FORCE_AUTHENTICATION =
|
||||
private static final SimpleAttributeDefinition FORCE_AUTHENTICATION =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.FORCE_AUTHENTICATION, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.FORCE_AUTHENTICATION)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition KEEP_DOM_ASSERTION =
|
||||
private static final SimpleAttributeDefinition KEEP_DOM_ASSERTION =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.KEEP_DOM_ASSERTION, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.KEEP_DOM_ASSERTION)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition IS_PASSIVE =
|
||||
private static final SimpleAttributeDefinition IS_PASSIVE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.IS_PASSIVE, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.IS_PASSIVE)
|
||||
.build();
|
||||
static final SimpleAttributeDefinition TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN =
|
||||
private static final SimpleAttributeDefinition TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN)
|
||||
.build();
|
||||
|
||||
private static final SimpleAttributeDefinition AUTODETECT_BEARER_ONLY =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.AUTODETECT_BEARER_ONLY, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.AUTODETECT_BEARER_ONLY)
|
||||
.setAllowExpression(true)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition PRINCIPAL_NAME_MAPPING_POLICY =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.PRINCIPAL_NAME_MAPPING_POLICY, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY)
|
||||
|
@ -102,13 +107,13 @@ public class ServiceProviderDefinition extends SimpleResourceDefinition {
|
|||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SSL_POLICY, NAME_ID_POLICY_FORMAT, LOGOUT_PAGE, FORCE_AUTHENTICATION,
|
||||
IS_PASSIVE, TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN, KEEP_DOM_ASSERTION};
|
||||
IS_PASSIVE, TURN_OFF_CHANGE_SESSSION_ID_ON_LOGIN, KEEP_DOM_ASSERTION, AUTODETECT_BEARER_ONLY};
|
||||
static final AttributeDefinition[] ELEMENTS = {PRINCIPAL_NAME_MAPPING_POLICY, PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, ROLE_ATTRIBUTES,
|
||||
ROLE_MAPPINGS_PROVIDER_ID, ROLE_MAPPINGS_PROVIDER_CONFIG};
|
||||
|
||||
|
||||
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
static final HashMap<String, AttributeDefinition> ALL_MAP = new HashMap<>();
|
||||
private static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
private static final HashMap<String, AttributeDefinition> ALL_MAP = new HashMap<>();
|
||||
static final Collection<AttributeDefinition> ALL_ATTRIBUTES;
|
||||
|
||||
static {
|
||||
|
|
|
@ -35,6 +35,7 @@ keycloak-saml.SP.forceAuthentication=Redirected unauthenticated request to a log
|
|||
keycloak-saml.SP.keepDOMAssertion=Attribute to inject the DOM representation of the assertion into the SamlPrincipal (respecting the original syntax)
|
||||
keycloak-saml.SP.isPassive=If user isn't logged in just return with an error. Used to check if a user is already logged in or not
|
||||
keycloak-saml.SP.turnOffChangeSessionIdOnLogin=The session id is changed by default on a successful login. Change this to true if you want to turn this off
|
||||
keycloak-saml.SP.autodetectBearerOnly=Set to true if the application serves both a web application and web services (e.g. SOAP or REST). It allows redirection of unauthenticated users of the web application to the Keycloak login page, but send an HTTP 401 status code to unauthenticated SOAP or REST clients instead
|
||||
keycloak-saml.SP.RoleIdentifiers=Role identifiers
|
||||
keycloak-saml.SP.PrincipalNameMapping-policy=Principal name mapping policy
|
||||
keycloak-saml.SP.PrincipalNameMapping-attribute-name=Principal name mapping attribute name
|
||||
|
@ -67,6 +68,7 @@ keycloak-saml.IDP.remove=Remove an identity provider
|
|||
keycloak-saml.IDP.signaturesRequired=Require signatures for SingleSignOnService and SingleLogoutService
|
||||
keycloak-saml.IDP.signatureAlgorithm=Signature algorithm
|
||||
keycloak-saml.IDP.signatureCanonicalizationMethod=Signature canonicalization method
|
||||
keycloak-saml.IDP.metadataUrl=The URL used to retrieve the IDP metadata from
|
||||
keycloak-saml.IDP.SingleSignOnService=Single sign-on configuration
|
||||
keycloak-saml.IDP.SingleSignOnService.signRequest=Sign SSO requests
|
||||
keycloak-saml.IDP.SingleSignOnService.validateResponseSignature=Validate an SSO response signature
|
||||
|
@ -88,3 +90,12 @@ keycloak-saml.IDP.Key=Key definition for identity provider
|
|||
keycloak-saml.IDP.AllowedClockSkew=Allowed clock skew between the IDP and the SP
|
||||
keycloak-saml.IDP.AllowedClockSkew.value=Allowed clock skew value between the IDP and the SP
|
||||
keycloak-saml.IDP.AllowedClockSkew.unit=Time unit for the value of the clock skew. Values: MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS
|
||||
keycloak-saml.IDP.HttpClient=Configuration of HTTP client used for automatic retrieval of certificates for signature validation
|
||||
keycloak-saml.IDP.HttpClient.allowAnyHostname=Define if hostname validation should be disabled (true) or not (false)
|
||||
keycloak-saml.IDP.HttpClient.clientKeystore=Path to the keystore that contains client certificates for two-way SSL
|
||||
keycloak-saml.IDP.HttpClient.clientKeystorePassword=The keystore password
|
||||
keycloak-saml.IDP.HttpClient.connectionPoolSize=The number of pooled connections
|
||||
keycloak-saml.IDP.HttpClient.disableTrustManager=Define if SSL certificate validation should be disabled (true) or not (false)
|
||||
keycloak-saml.IDP.HttpClient.proxyUrl=URL to the HTTP proxy, if applicable
|
||||
keycloak-saml.IDP.HttpClient.truststore=Path to the truststore used to validate the IDP certificates
|
||||
keycloak-saml.IDP.HttpClient.truststorePassword=The truststore password
|
|
@ -0,0 +1,570 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright 2020 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.autodetect
|
||||
-->
|
||||
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="urn:jboss:domain:keycloak-saml:1.3"
|
||||
xmlns="urn:jboss:domain:keycloak-saml:1.3"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified"
|
||||
version="1.0">
|
||||
|
||||
<!-- The subsystem root element -->
|
||||
<xs:element name="subsystem" type="subsystem-type"/>
|
||||
|
||||
<xs:complexType name="subsystem-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<![CDATA[
|
||||
The Keycloak SAML adapter subsystem, used to register deployments managed by Keycloak SAML adapter
|
||||
]]>
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:all>
|
||||
<xs:element name="secure-deployment" minOccurs="0" type="secure-deployment-type"/>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="secure-deployment-type">
|
||||
<xs:all>
|
||||
<xs:element name="SP" minOccurs="0" maxOccurs="1" type="sp-type"/>
|
||||
</xs:all>
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name of the deployment</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="sp-type">
|
||||
<xs:all>
|
||||
<xs:element name="Keys" type="keys-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
List of service provider encryption and validation keys.
|
||||
|
||||
If the IDP requires that the client application (SP) sign all of its requests and/or if the IDP will encrypt assertions, you must define the keys used to do this. For client signed documents you must define both the private and public key or certificate that will be used to sign documents. For encryption, you only have to define the private key that will be used to decrypt.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="PrincipalNameMapping" type="principal-name-mapping-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>When creating a Java Principal object that you obtain from methods like HttpServletRequest.getUserPrincipal(), you can define what name that is returned by the Principal.getName() method.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="RoleIdentifiers" type="role-identifiers-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines what SAML attributes within the assertion received from the user should be used as role identifiers within the Java EE Security Context for the user.
|
||||
By default Role attribute values are converted to Java EE roles. Some IDPs send roles via a member or memberOf attribute assertion. You can define one or more Attribute elements to specify which SAML attributes must be converted into roles.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="RoleMappingsProvider" type="role-mappings-provider-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies the role mappings provider implementation that will be used to map the roles extracted from the SAML assertion into the final set of roles
|
||||
that will be assigned to the principal. A provider is typically used to map roles retrieved from third party IDPs into roles that exist in the JEE application environment. It can also
|
||||
assign extra roles to the assertion principal (for example, by connecting to an LDAP server to obtain more roles) or remove some of the roles that were set by the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="IDP" type="idp-type" minOccurs="1" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Describes configuration of SAML identity provider for this service provider.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="entityID" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the identifier for this client. The IDP needs this value to determine who the client is that is communicating with it.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="sslPolicy" type="ssl-policy-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SSL policy the adapter will enforce.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="nameIDPolicyFormat" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML clients can request a specific NameID Subject format. Fill in this value if you want a specific format. It must be a standard SAML format identifier, i.e. urn:oasis:names:tc:SAML:2.0:nameid-format:transient. By default, no special format is requested.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="logoutPage" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>URL of the logout page.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="forceAuthentication" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML clients can request that a user is re-authenticated even if they are already logged in at the IDP. Default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="keepDOMAssertion" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Attribute to inject the DOM representation of the assertion into the SamlPrincipal (respecting the original syntax). Default value is false</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="isPassive" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML clients can request that a user is never asked to authenticate even if they are not logged in at the IDP. Set this to true if you want this. Do not use together with forceAuthentication as they are opposite. Default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="turnOffChangeSessionIdOnLogin" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The session id is changed by default on a successful login on some platforms to plug a security attack vector. Change this to true to disable this. It is recommended you do not turn it off. Default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="autodetectBearerOnly" type="xs:boolean" use="optional" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This should be set to true if your application serves both a web application and web services (e.g. SOAP or REST). It allows you to redirect unauthenticated users of the web application to the Keycloak login page, but send an HTTP 401 status code to unauthenticated SOAP or REST clients instead as they would not understand a redirect to the login page. Keycloak auto-detects SOAP or REST clients based on typical headers like X-Requested-With, SOAPAction or Accept. The default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="keys-type">
|
||||
<xs:sequence>
|
||||
<xs:element name="Key" type="key-type" minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Describes a single key used for signing or encryption.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="key-type">
|
||||
<xs:all>
|
||||
<xs:element name="KeyStore" maxOccurs="1" minOccurs="0" type="key-store-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Java keystore to load keys and certificates from.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="PrivateKeyPem" type="xs:string" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Private key (PEM format)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="PublicKeyPem" type="xs:string" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Public key (PEM format)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="CertificatePem" type="xs:string" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Certificate key (PEM format)</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="signing" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Flag defining whether the key should be used for signing.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="encryption" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Flag defining whether the key should be used for encryption</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="key-store-type">
|
||||
<xs:all>
|
||||
<xs:element name="PrivateKey" maxOccurs="1" minOccurs="0" type="private-key-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Private key declaration</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Certificate" type="certificate-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Certificate declaration</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="file" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>File path to the key store.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="resource" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>WAR resource path to the key store. This is a path used in method call to ServletContext.getResourceAsStream().</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="password" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The password of the key store.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="type" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Key store format</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="alias" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Key alias</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="private-key-type">
|
||||
<xs:attribute name="alias" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Alias that points to the key or cert within the keystore.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="password" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Keystores require an additional password to access private keys. In the PrivateKey element you must define this password within a password attribute.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="certificate-type">
|
||||
<xs:attribute name="alias" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Alias that points to the key or cert within the keystore.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="principal-name-mapping-type">
|
||||
<xs:attribute name="policy" type="principal-name-mapping-policy-type" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Policy used to populate value of Java Principal object obtained from methods like HttpServletRequest.getUserPrincipal().</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="attribute" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Name of the SAML assertion attribute to use within.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:simpleType name="principal-name-mapping-policy-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="FROM_NAME_ID">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This policy just uses whatever the SAML subject value is. This is the default setting</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="FROM_ATTRIBUTE">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This will pull the value from one of the attributes declared in the SAML assertion received from the server. You'll need to specify the name of the SAML assertion attribute to use within the attribute XML attribute.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="ssl-policy-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="ALL">
|
||||
<xs:annotation>
|
||||
<xs:documentation>All requests must come in via HTTPS.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="EXTERNAL">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Only non-private IP addresses must come over the wire via HTTPS.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
<xs:enumeration value="NONE">
|
||||
<xs:annotation>
|
||||
<xs:documentation>no requests are required to come over via HTTPS.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="signature-algorithm-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="RSA_SHA1"/>
|
||||
<xs:enumeration value="RSA_SHA256"/>
|
||||
<xs:enumeration value="RSA_SHA512"/>
|
||||
<xs:enumeration value="DSA_SHA1"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:simpleType name="binding-type">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="POST"/>
|
||||
<xs:enumeration value="REDIRECT"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="role-identifiers-type">
|
||||
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="Attribute" maxOccurs="unbounded" minOccurs="0" type="attribute-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies SAML attribute to be converted into roles.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="attribute-type">
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies name of the SAML attribute to be converted into roles.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="role-mappings-provider-type">
|
||||
<xs:sequence>
|
||||
<xs:element name="Property" type="property-type" minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies a configuration property for the provider.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="id" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The id of the role mappings provider that is to be used. Example: properties-based-provider.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="property-type">
|
||||
<xs:attribute name="name" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name (key) of the configuration property.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="value" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The value of the configuration property.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="idp-type">
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="SingleSignOnService" maxOccurs="1" minOccurs="1" type="sign-on-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Configuration of the login SAML endpoint of the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="SingleLogoutService" type="logout-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Configuration of the logout SAML endpoint of the IDP</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="Keys" type="keys-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The Keys sub element of IDP is only used to define the certificate or public key to use to verify documents signed by the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="HttpClient" type="http-client-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Configuration of HTTP client used for automatic obtaining of certificates containing public keys for IDP signature verification via SAML descriptor of the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="AllowedClockSkew" type="allowed-clock-skew-type" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This defines the allowed clock skew between IDP and SP in milliseconds. The default value is 0.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="entityID" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>issuer ID of the IDP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signaturesRequired" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If set to true, the client adapter will sign every document it sends to the IDP. Also, the client will expect that the IDP will be signing any documents sent to it. This switch sets the default for all request and response types.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signatureAlgorithm" type="signature-algorithm-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Signature algorithm that the IDP expects signed documents to use. Defaults to RSA_SHA256</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signatureCanonicalizationMethod" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the signature canonicalization method that the IDP expects signed documents to use. The default value is https://www.w3.org/2001/10/xml-exc-c14n# and should be good for most IDPs.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="encryption" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation></xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="metadataUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The URL used to retrieve the IDP metadata, currently this is only used to pick up signing and encryption keys periodically which allow cycling of these keys on the IDP without manual changes on the SP side.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="sign-on-type">
|
||||
<xs:attribute name="signRequest" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client sign authn requests? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect the IDP to sign the assertion response document sent back from an auhtn request? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateAssertionSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect the IDP to sign the individual assertions sent back from an auhtn request? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="requestBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML binding type used for communicating with the IDP. The default value is POST, but you can set it to REDIRECT as well.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="responseBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>SAML allows the client to request what binding type it wants authn responses to use. This value maps to ProtocolBinding attribute in SAML AuthnRequest. The default is that the client will not request a specific binding type for responses.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="bindingUrl" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the URL for the IDP login service that the client will send requests to.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="assertionConsumerServiceUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>URL of the assertion consumer service (ACS) where the IDP login service should send responses to. By default it is unset, relying on the IdP settings. When set, it must end in "/saml". This property is typically accompanied by the responseBinding attribute.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="logout-type">
|
||||
<xs:attribute name="signRequest" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client sign authn requests? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signResponse" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client sign logout responses it sends to the IDP requests? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateRequestSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect signed logout request documents from the IDP? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Should the client expect signed logout response documents from the IDP? Defaults to whatever the IDP signaturesRequired element value is.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="requestBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the SAML binding type used for communicating SAML requests to the IDP. The default value is POST.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="responseBinding" type="binding-type" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the SAML binding type used for communicating SAML responses to the IDP. The default value is POST.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="postBindingUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the URL for the IDP's logout service when using the POST binding. This setting is REQUIRED if using the POST binding.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="redirectBindingUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the URL for the IDP's logout service when using the REDIRECT binding. This setting is REQUIRED if using the REDIRECT binding.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="http-client-type">
|
||||
<xs:attribute name="allowAnyHostname" type="xs:boolean" use="optional" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If the the IDP server requires HTTPS and this config option is set to true the IDP's certificate
|
||||
is validated via the truststore, but host name validation is not done. This setting should only be used during
|
||||
development and never in production as it will partly disable verification of SSL certificates.
|
||||
This seting may be useful in test environments. The default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="clientKeystore" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the file path to a keystore file. This keystore contains client certificate
|
||||
for two-way SSL when the adapter makes HTTPS requests to the IDP server.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="clientKeystorePassword" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Password for the client keystore and for the client's key.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="connectionPoolSize" type="xs:int" use="optional" default="10">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Defines number of pooled connections.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="disableTrustManager" type="xs:boolean" use="optional" default="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If the the IDP server requires HTTPS and this config option is set to true you do not have to specify a truststore.
|
||||
This setting should only be used during development and never in production as it will disable verification of SSL certificates.
|
||||
The default value is false.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="proxyUrl" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>URL to HTTP proxy to use for HTTP connections.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="truststore" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The value is the file path to a keystore file. If you prefix the path with classpath:,
|
||||
then the truststore will be obtained from the deployment's classpath instead. Used for outgoing
|
||||
HTTPS communications to the IDP server. Client making HTTPS requests need
|
||||
a way to verify the host of the server they are talking to. This is what the trustore does.
|
||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
||||
You can create this truststore by extracting the public certificate of the IDP's SSL keystore.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="truststorePassword" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Password for the truststore keystore.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="allowed-clock-skew-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The value is the allowed clock skew between the IDP and the SP.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:positiveInteger">
|
||||
<xs:attribute name="unit" type="clock-skew-unit-type"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
<xs:simpleType name="clock-skew-unit-type">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Time unit for the value of the clock skew.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="MINUTES" />
|
||||
<xs:enumeration value="SECONDS" />
|
||||
<xs:enumeration value="MILLISECONDS" />
|
||||
<xs:enumeration value="MICROSECONDS" />
|
||||
<xs:enumeration value="NANOSECONDS" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
</xs:schema>
|
|
@ -19,6 +19,6 @@
|
|||
<!-- Template used by WildFly build when directed to include Keycloak SAML subsystem in a configuration. -->
|
||||
<config>
|
||||
<extension-module>org.keycloak.keycloak-saml-adapter-subsystem</extension-module>
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.2">
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.3">
|
||||
</subsystem>
|
||||
</config>
|
||||
|
|
|
@ -77,7 +77,7 @@ public class SubsystemParsingAllowedClockSkewTestCase extends AbstractSubsystemB
|
|||
|
||||
@Override
|
||||
protected String getSubsystemXsdPath() throws Exception {
|
||||
return "schema/wildfly-keycloak-saml_1_2.xsd";
|
||||
return "schema/wildfly-keycloak-saml_1_3.xsd";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -94,7 +94,7 @@ public class SubsystemParsingAllowedClockSkewTestCase extends AbstractSubsystemB
|
|||
|
||||
private void setSubsystemXml(String value, String unit) throws IOException {
|
||||
try {
|
||||
String template = readResource("keycloak-saml-1.2.xml");
|
||||
String template = readResource("keycloak-saml-1.3.xml");
|
||||
if (value != null) {
|
||||
// assign the AllowedClockSkew element using DOM
|
||||
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
|
|
|
@ -39,12 +39,12 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
|||
|
||||
@Override
|
||||
protected String getSubsystemXml() throws IOException {
|
||||
return readResource("keycloak-saml-1.2.xml");
|
||||
return readResource("keycloak-saml-1.3.xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubsystemXsdPath() throws Exception {
|
||||
return "schema/wildfly-keycloak-saml_1_2.xsd";
|
||||
return "schema/wildfly-keycloak-saml_1_3.xsd";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.2">
|
||||
<secure-deployment name="my-app.war">
|
||||
<SP entityID="http://localhost:8080/sales-post-enc/"
|
||||
sslPolicy="EXTERNAL"
|
||||
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||
logoutPage="/logout.jsp"
|
||||
forceAuthentication="false">
|
||||
|
||||
<Keys>
|
||||
<Key encryption="true" signing="true">
|
||||
<PrivateKeyPem>my_key.pem</PrivateKeyPem>
|
||||
<PublicKeyPem>my_key.pub</PublicKeyPem>
|
||||
<CertificatePem>cert.cer</CertificatePem>
|
||||
<KeyStore resource="/WEB-INF/keystore.jks" password="store123" file="test" alias="test" type="jks">
|
||||
<PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
|
||||
<Certificate alias="http://localhost:8080/sales-post-enc/"/>
|
||||
</KeyStore>
|
||||
</Key>
|
||||
</Keys>
|
||||
<PrincipalNameMapping policy="FROM_NAME_ID" attribute="test"/>
|
||||
<RoleIdentifiers>
|
||||
<Attribute name="Role"/>
|
||||
<Attribute name="Role2"/>
|
||||
</RoleIdentifiers>
|
||||
<IDP entityID="idp" signaturesRequired="true" signatureAlgorithm="test" signatureCanonicalizationMethod="test" encryption="test">
|
||||
<SingleSignOnService signRequest="true"
|
||||
validateResponseSignature="true"
|
||||
validateAssertionSignature="true"
|
||||
requestBinding="POST"
|
||||
responseBinding="POST"
|
||||
bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
|
||||
<SingleLogoutService
|
||||
validateRequestSignature="true"
|
||||
validateResponseSignature="true"
|
||||
signRequest="true"
|
||||
signResponse="true"
|
||||
requestBinding="POST"
|
||||
responseBinding="POST"
|
||||
postBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"
|
||||
redirectBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
|
||||
<Keys>
|
||||
<Key signing="true">
|
||||
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
||||
<Certificate alias="saml-demo"/>
|
||||
</KeyStore>
|
||||
</Key>
|
||||
</Keys>
|
||||
</IDP>
|
||||
</SP>
|
||||
</secure-deployment>
|
||||
</subsystem>
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
~ Copyright 2019 Red Hat, Inc. and/or its affiliates
|
||||
~ Copyright 2020 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");
|
||||
|
@ -15,16 +15,17 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.2">
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.3">
|
||||
<secure-deployment name="my-app.war">
|
||||
<SP entityID="http://localhost:8080/sales-post-enc/"
|
||||
sslPolicy="EXTERNAL"
|
||||
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||
logoutPage="/logout.jsp"
|
||||
forceAuthentication="false"
|
||||
keepDOMAssertion="false"
|
||||
forceAuthentication="false"
|
||||
isPassive="true"
|
||||
turnOffChangeSessionIdOnLogin="true">
|
||||
turnOffChangeSessionIdOnLogin="true"
|
||||
autodetectBearerOnly="false">
|
||||
|
||||
<Keys>
|
||||
<Key encryption="true" signing="true">
|
||||
|
@ -46,7 +47,11 @@
|
|||
<Property name="properties.file.location" value="test-roles.properties"/>
|
||||
<Property name="another.property" value="another.value"/>
|
||||
</RoleMappingsProvider>
|
||||
<IDP entityID="idp" signaturesRequired="true" signatureAlgorithm="test" signatureCanonicalizationMethod="test">
|
||||
<IDP entityID="idp"
|
||||
signaturesRequired="true"
|
||||
signatureAlgorithm="DSA_SHA1"
|
||||
signatureCanonicalizationMethod="test"
|
||||
metadataUrl="http://localhost:8080/metadata">
|
||||
<SingleSignOnService signRequest="true"
|
||||
validateResponseSignature="true"
|
||||
validateAssertionSignature="true"
|
||||
|
@ -70,6 +75,14 @@
|
|||
</KeyStore>
|
||||
</Key>
|
||||
</Keys>
|
||||
<HttpClient allowAnyHostname="false"
|
||||
clientKeystore="/tmp/keystore.jks"
|
||||
clientKeystorePassword="testpwd1!@"
|
||||
connectionPoolSize="20"
|
||||
disableTrustManager="false"
|
||||
proxyUrl="http://localhost:9090/proxy"
|
||||
truststore="/tmp/truststore.jks"
|
||||
truststorePassword="trustpwd#*"/>
|
||||
</IDP>
|
||||
</SP>
|
||||
</secure-deployment>
|
Loading…
Reference in a new issue