KEYCLOAK-13950 SAML2 Identity Provider - Send Subject in SAML requests
This commit is contained in:
parent
344003264a
commit
e82fe7d9e3
19 changed files with 210 additions and 26 deletions
|
@ -17,7 +17,9 @@
|
|||
package org.keycloak.saml;
|
||||
|
||||
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
||||
import org.keycloak.dom.saml.v2.assertion.SubjectType;
|
||||
import org.keycloak.dom.saml.v2.protocol.AuthnRequestType;
|
||||
import org.keycloak.dom.saml.v2.protocol.ExtensionsType;
|
||||
import org.keycloak.saml.processing.api.saml.v2.request.SAML2Request;
|
||||
import org.keycloak.saml.processing.core.saml.v2.common.IDGenerator;
|
||||
import org.keycloak.saml.processing.core.saml.v2.util.XMLTimeUtil;
|
||||
|
@ -26,7 +28,6 @@ import org.w3c.dom.Document;
|
|||
import java.net.URI;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.keycloak.dom.saml.v2.protocol.ExtensionsType;
|
||||
|
||||
/**
|
||||
* @author pedroigor
|
||||
|
@ -88,6 +89,25 @@ public class SAML2AuthnRequestBuilder implements SamlProtocolExtensionsAwareBuil
|
|||
return this;
|
||||
}
|
||||
|
||||
public SAML2AuthnRequestBuilder subject(String subject) {
|
||||
String sanitizedSubject = subject != null ? subject.trim() : null;
|
||||
if (sanitizedSubject != null && !sanitizedSubject.isEmpty()) {
|
||||
this.authnRequestType.setSubject(createSubject(sanitizedSubject));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private SubjectType createSubject(String value) {
|
||||
NameIDType nameId = new NameIDType();
|
||||
nameId.setValue(value);
|
||||
nameId.setFormat(this.authnRequestType.getNameIDPolicy() != null ? this.authnRequestType.getNameIDPolicy().getFormat() : null);
|
||||
SubjectType subject = new SubjectType();
|
||||
SubjectType.STSubType subType = new SubjectType.STSubType();
|
||||
subType.addBaseID(nameId);
|
||||
subject.setSubType(subType);
|
||||
return subject;
|
||||
}
|
||||
|
||||
public Document toDocument() {
|
||||
try {
|
||||
AuthnRequestType authnRequestType = createAuthnRequest();
|
||||
|
|
|
@ -81,10 +81,12 @@ public class BaseWriter {
|
|||
*
|
||||
* @throws org.keycloak.saml.common.exceptions.ProcessingException
|
||||
*/
|
||||
public void write(NameIDType nameIDType, QName tag) throws ProcessingException {
|
||||
public void write(NameIDType nameIDType, QName tag, boolean writeNamespace) throws ProcessingException {
|
||||
StaxUtil.writeStartElement(writer, tag.getPrefix(), tag.getLocalPart(), tag.getNamespaceURI());
|
||||
|
||||
StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
|
||||
if (writeNamespace) {
|
||||
StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
|
||||
}
|
||||
|
||||
URI format = nameIDType.getFormat();
|
||||
if (format != null) {
|
||||
|
@ -115,6 +117,13 @@ public class BaseWriter {
|
|||
StaxUtil.flush(writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write {@code NameIDType} to stream without writing a namespace
|
||||
*/
|
||||
public void write(NameIDType nameIDType, QName tag) throws ProcessingException {
|
||||
this.write(nameIDType, tag, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an {@code AttributeType} to stream
|
||||
*
|
||||
|
|
|
@ -64,6 +64,7 @@ public class SAMLRequestWriter extends BaseWriter {
|
|||
public void write(AuthnRequestType request) throws ProcessingException {
|
||||
StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.AUTHN_REQUEST.get(), PROTOCOL_NSURI.get());
|
||||
StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, PROTOCOL_NSURI.get());
|
||||
StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
|
||||
StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
|
||||
|
||||
// Attributes
|
||||
|
@ -119,7 +120,12 @@ public class SAMLRequestWriter extends BaseWriter {
|
|||
|
||||
NameIDType issuer = request.getIssuer();
|
||||
if (issuer != null) {
|
||||
write(issuer, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
|
||||
write(issuer, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX), false);
|
||||
}
|
||||
|
||||
SubjectType subject = request.getSubject();
|
||||
if (subject != null) {
|
||||
write(subject);
|
||||
}
|
||||
|
||||
Element sig = request.getSignature();
|
||||
|
@ -157,6 +163,7 @@ public class SAMLRequestWriter extends BaseWriter {
|
|||
StaxUtil.writeStartElement(writer, PROTOCOL_PREFIX, JBossSAMLConstants.LOGOUT_REQUEST.get(), PROTOCOL_NSURI.get());
|
||||
|
||||
StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, PROTOCOL_NSURI.get());
|
||||
StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, ASSERTION_NSURI.get());
|
||||
StaxUtil.writeDefaultNameSpace(writer, ASSERTION_NSURI.get());
|
||||
|
||||
// Attributes
|
||||
|
|
|
@ -162,12 +162,13 @@ public class SAMLResponseWriter extends BaseWriter {
|
|||
}
|
||||
|
||||
StaxUtil.writeNameSpace(writer, PROTOCOL_PREFIX, JBossSAMLURIConstants.PROTOCOL_NSURI.get());
|
||||
StaxUtil.writeNameSpace(writer, ASSERTION_PREFIX, JBossSAMLURIConstants.ASSERTION_NSURI.get());
|
||||
StaxUtil.writeDefaultNameSpace(writer, JBossSAMLURIConstants.ASSERTION_NSURI.get());
|
||||
|
||||
writeBaseAttributes(response);
|
||||
|
||||
NameIDType issuer = response.getIssuer();
|
||||
write(issuer, new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get(), ASSERTION_PREFIX));
|
||||
write(issuer, new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ISSUER.get()));
|
||||
|
||||
Element sig = response.getSignature();
|
||||
if (sig != null) {
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
|||
public class IdentityProviderModel implements Serializable {
|
||||
|
||||
public static final String ALLOWED_CLOCK_SKEW = "allowedClockSkew";
|
||||
public static final String LOGIN_HINT = "loginHint";
|
||||
|
||||
public static final String SYNC_MODE = "syncMode";
|
||||
|
||||
|
@ -218,4 +219,12 @@ public class IdentityProviderModel implements Serializable {
|
|||
public void setSyncMode(IdentityProviderSyncMode syncMode) {
|
||||
getConfig().put(SYNC_MODE, syncMode.toString());
|
||||
}
|
||||
|
||||
public boolean isLoginHint() {
|
||||
return Boolean.valueOf(getConfig().get(LOGIN_HINT));
|
||||
}
|
||||
|
||||
public void setLoginHint(boolean loginHint) {
|
||||
getConfig().put(LOGIN_HINT, String.valueOf(loginHint));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,14 +92,6 @@ public class OAuth2IdentityProviderConfig extends IdentityProviderModel {
|
|||
public void setDefaultScope(String defaultScope) {
|
||||
getConfig().put("defaultScope", defaultScope);
|
||||
}
|
||||
|
||||
public boolean isLoginHint() {
|
||||
return Boolean.valueOf(getConfig().get("loginHint"));
|
||||
}
|
||||
|
||||
public void setLoginHint(boolean loginHint) {
|
||||
getConfig().put("loginHint", String.valueOf(loginHint));
|
||||
}
|
||||
|
||||
public boolean isJWTAuthentication() {
|
||||
if (getClientAuthMethod().equals(OIDCLoginProtocol.CLIENT_SECRET_JWT)
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.keycloak.dom.saml.v2.protocol.ResponseType;
|
|||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.keys.RsaKeyMetadata;
|
||||
import org.keycloak.models.*;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
|
||||
import org.keycloak.protocol.saml.SamlSessionUtils;
|
||||
import org.keycloak.protocol.saml.preprocessor.SamlAuthenticationPreprocessor;
|
||||
|
@ -63,6 +64,7 @@ import java.util.TreeSet;
|
|||
*/
|
||||
public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityProviderConfig> {
|
||||
protected static final Logger logger = Logger.getLogger(SAMLIdentityProvider.class);
|
||||
|
||||
private final DestinationValidator destinationValidator;
|
||||
public SAMLIdentityProvider(KeycloakSession session, SAMLIdentityProviderConfig config, DestinationValidator destinationValidator) {
|
||||
super(session, config);
|
||||
|
@ -95,13 +97,15 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
protocolBinding = JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get();
|
||||
}
|
||||
|
||||
String loginHint = getConfig().isLoginHint() ? request.getAuthenticationSession().getClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM) : null;
|
||||
SAML2AuthnRequestBuilder authnRequestBuilder = new SAML2AuthnRequestBuilder()
|
||||
.assertionConsumerUrl(assertionConsumerServiceUrl)
|
||||
.destination(destinationUrl)
|
||||
.issuer(issuerURL)
|
||||
.forceAuthn(getConfig().isForceAuthn())
|
||||
.protocolBinding(protocolBinding)
|
||||
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat));
|
||||
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat))
|
||||
.subject(loginHint);
|
||||
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session)
|
||||
.relayState(request.getState().getEncoded());
|
||||
boolean postBinding = getConfig().isPostBindingAuthnRequest();
|
||||
|
|
|
@ -124,6 +124,7 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
|
|||
samlIdentityProviderConfig.setPostBindingResponse(postBindingResponse);
|
||||
samlIdentityProviderConfig.setPostBindingAuthnRequest(postBindingResponse);
|
||||
samlIdentityProviderConfig.setPostBindingLogout(postBindingLogout);
|
||||
samlIdentityProviderConfig.setLoginHint(false);
|
||||
|
||||
List<String> nameIdFormatList = idpDescriptor.getNameIDFormat();
|
||||
if (nameIdFormatList != null && !nameIdFormatList.isEmpty())
|
||||
|
|
|
@ -353,8 +353,9 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
|||
public Response performPostLogin(@PathParam("provider_id") String providerId,
|
||||
@QueryParam(LoginActionsService.SESSION_CODE) String code,
|
||||
@QueryParam("client_id") String clientId,
|
||||
@QueryParam(Constants.TAB_ID) String tabId) {
|
||||
return performLogin(providerId, code, clientId, tabId);
|
||||
@QueryParam(Constants.TAB_ID) String tabId,
|
||||
@QueryParam(OIDCLoginProtocol.LOGIN_HINT_PARAM) String loginHint) {
|
||||
return performLogin(providerId, code, clientId, tabId, loginHint);
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -363,7 +364,8 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
|||
public Response performLogin(@PathParam("provider_id") String providerId,
|
||||
@QueryParam(LoginActionsService.SESSION_CODE) String code,
|
||||
@QueryParam("client_id") String clientId,
|
||||
@QueryParam(Constants.TAB_ID) String tabId) {
|
||||
@QueryParam(Constants.TAB_ID) String tabId,
|
||||
@QueryParam(OIDCLoginProtocol.LOGIN_HINT_PARAM) String loginHint) {
|
||||
this.event.detail(Details.IDENTITY_PROVIDER, providerId);
|
||||
|
||||
if (isDebugEnabled()) {
|
||||
|
@ -376,15 +378,18 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
|||
return parsedCode.response;
|
||||
}
|
||||
|
||||
ClientSessionCode clientSessionCode = parsedCode.clientSessionCode;
|
||||
ClientSessionCode<AuthenticationSessionModel> clientSessionCode = parsedCode.clientSessionCode;
|
||||
IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
|
||||
if (identityProviderModel == null) {
|
||||
throw new IdentityBrokerException("Identity Provider [" + providerId + "] not found.");
|
||||
}
|
||||
if (identityProviderModel.isLinkOnly()) {
|
||||
throw new IdentityBrokerException("Identity Provider [" + providerId + "] is not allowed to perform a login.");
|
||||
|
||||
}
|
||||
if (clientSessionCode != null && clientSessionCode.getClientSession() != null && loginHint != null) {
|
||||
clientSessionCode.getClientSession().setClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
|
||||
}
|
||||
|
||||
IdentityProviderFactory providerFactory = getIdentityProviderFactory(session, identityProviderModel);
|
||||
|
||||
IdentityProvider identityProvider = providerFactory.create(session, identityProviderModel);
|
||||
|
|
|
@ -36,11 +36,11 @@ import static org.junit.Assert.assertThat;
|
|||
*/
|
||||
public class SAMLDataMarshallerTest {
|
||||
|
||||
private static final String TEST_RESPONSE = "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_4804cf50-cd96-4b92-823e-89adaa0c78ba\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.920Z\" Destination=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\" InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">manager</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>";
|
||||
private static final String TEST_RESPONSE = "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_4804cf50-cd96-4b92-823e-89adaa0c78ba\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.920Z\" Destination=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\" InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\"><saml:Issuer>http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer>http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">manager</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>";
|
||||
|
||||
private static final String TEST_ASSERTION = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">manager</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>";
|
||||
private static final String TEST_ASSERTION = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer>http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">manager</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>";
|
||||
|
||||
private static final String TEST_ASSERTION_WITH_NAME_ID = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\">b2c6275838784dba219c92f53ea5493c8ef4da09</saml:NameID></saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>";
|
||||
private static final String TEST_ASSERTION_WITH_NAME_ID = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer>http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue><saml:NameID Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\">b2c6275838784dba219c92f53ea5493c8ef4da09</saml:NameID></saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>";
|
||||
|
||||
private static final String TEST_AUTHN_TYPE = "<saml:AuthnStatement xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement>";
|
||||
|
||||
|
|
|
@ -888,7 +888,8 @@ public class IdentityProviderTest extends AbstractAdminTest {
|
|||
"wantAuthnRequestsSigned",
|
||||
"nameIDPolicyFormat",
|
||||
"signingCertificate",
|
||||
"addExtensionsElementWithKeyInfo"
|
||||
"addExtensionsElementWithKeyInfo",
|
||||
"loginHint"
|
||||
));
|
||||
assertThat(config, hasEntry("validateSignature", "true"));
|
||||
assertThat(config, hasEntry("singleLogoutServiceUrl", "http://localhost:8080/auth/realms/master/protocol/saml"));
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package org.keycloak.testsuite.broker;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.openqa.selenium.JavascriptExecutor;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestTools.getConsumerRoot;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestTools.waitForPage;
|
||||
|
||||
/**
|
||||
* Test of various scenarios related to the use of login hint
|
||||
*/
|
||||
public abstract class AbstractSamlLoginHintTest extends AbstractInitializedBaseBrokerTest {
|
||||
|
||||
// KEYCLOAK-13950
|
||||
@Test
|
||||
public void testPassLoginHintShouldSendSubjectAndPrefillUsername() {
|
||||
String username = "all-info-set@localhost.com";
|
||||
createUser(bc.providerRealmName(), username, "password");
|
||||
|
||||
driver.navigate().to(getAccountUrl(getConsumerRoot(), bc.consumerRealmName()));
|
||||
log.debug("Clicking social " + bc.getIDPAlias());
|
||||
addLoginHintOnSocialButton(username);
|
||||
loginPage.clickSocial(bc.getIDPAlias());
|
||||
waitForPage(driver, "log in to", true);
|
||||
Assert.assertTrue("Driver should be on the provider realm page right now",
|
||||
driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
|
||||
log.debug("Logging in");
|
||||
|
||||
if (isLoginHintOptionEnabled()) {
|
||||
assertEquals("Username input should contain the SAML subject", loginPage.getUsername(), username);
|
||||
} else {
|
||||
assertEquals("Username input should the SAML subject", loginPage.getUsername(), "");
|
||||
}
|
||||
}
|
||||
|
||||
// KEYCLOAK-13950
|
||||
@Test
|
||||
public void testPassEmptyLoginHintShouldNotSendSubjectAndShouldNotPrefillUsername() {
|
||||
String username = "all-info-set@localhost.com";
|
||||
createUser(bc.providerRealmName(), username, "password", "FirstName");
|
||||
|
||||
driver.navigate().to(getAccountUrl(getConsumerRoot(), bc.consumerRealmName()));
|
||||
log.debug("Clicking social " + bc.getIDPAlias());
|
||||
addLoginHintOnSocialButton("");
|
||||
loginPage.clickSocial(bc.getIDPAlias());
|
||||
waitForPage(driver, "log in to", true);
|
||||
Assert.assertTrue("Driver should be on the provider realm page right now",
|
||||
driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
|
||||
log.debug("Logging in");
|
||||
|
||||
assertEquals("Username input should not contain any username", loginPage.getUsername(), "");
|
||||
}
|
||||
|
||||
abstract boolean isLoginHintOptionEnabled();
|
||||
|
||||
protected void addLoginHintOnSocialButton(String hint) {
|
||||
JavascriptExecutor executor = (JavascriptExecutor) driver;
|
||||
WebElement button = loginPage.findSocialButton(bc.getIDPAlias());
|
||||
String url = button.getAttribute("href") + "&"+ OIDCLoginProtocol.LOGIN_HINT_PARAM+"="+hint;
|
||||
executor.executeScript("document.getElementById('"+button.getAttribute("id")+"').setAttribute('href', '"+url+"')");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BrokerConfiguration getBrokerConfiguration() {
|
||||
return new KcSamlBrokerConfiguration(isLoginHintOptionEnabled());
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import static org.keycloak.testsuite.broker.BrokerTestTools.getConsumerRoot;
|
|||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.IdentityProviderSyncMode;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
@ -36,7 +37,7 @@ public class KcOidcBrokerLoginHintTest extends AbstractBrokerTest {
|
|||
|
||||
Map<String, String> config = idp.getConfig();
|
||||
applyDefaultConfiguration(config, syncMode);
|
||||
config.put("loginHint", "true");
|
||||
config.put(IdentityProviderModel.LOGIN_HINT, "true");
|
||||
return idp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import static org.keycloak.testsuite.broker.BrokerTestTools.waitForPage;
|
|||
import static org.keycloak.testsuite.broker.BrokerTestTools.getConsumerRoot;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.IdentityProviderSyncMode;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
@ -31,7 +32,7 @@ public class KcOidcBrokerNoLoginHintTest extends AbstractBrokerTest {
|
|||
|
||||
Map<String, String> config = idp.getConfig();
|
||||
applyDefaultConfiguration(config, syncMode);
|
||||
config.put("loginHint", "false");
|
||||
config.put(IdentityProviderModel.LOGIN_HINT, "false");
|
||||
return idp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,16 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
|
|||
public static final KcSamlBrokerConfiguration INSTANCE = new KcSamlBrokerConfiguration();
|
||||
public static final String ATTRIBUTE_TO_MAP_FRIENDLY_NAME = "user-attribute-friendly";
|
||||
|
||||
private final boolean loginHint;
|
||||
|
||||
public KcSamlBrokerConfiguration() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public KcSamlBrokerConfiguration(boolean loginHint) {
|
||||
this.loginHint = loginHint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RealmRepresentation createProviderRealm() {
|
||||
RealmRepresentation realm = new RealmRepresentation();
|
||||
|
@ -87,6 +97,7 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
|
|||
attributes.put(SamlConfigAttributes.SAML_SERVER_SIGNATURE, "false");
|
||||
attributes.put(SamlConfigAttributes.SAML_CLIENT_SIGNATURE_ATTRIBUTE, "false");
|
||||
attributes.put(SamlConfigAttributes.SAML_ENCRYPT, "false");
|
||||
attributes.put(IdentityProviderModel.LOGIN_HINT, String.valueOf(loginHint));
|
||||
|
||||
client.setAttributes(attributes);
|
||||
|
||||
|
@ -211,6 +222,7 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
|
|||
config.put(SINGLE_LOGOUT_SERVICE_URL, getProviderRoot() + "/auth/realms/" + REALM_PROV_NAME + "/protocol/saml");
|
||||
config.put(NAME_ID_POLICY_FORMAT, "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
|
||||
config.put(FORCE_AUTHN, "false");
|
||||
config.put(IdentityProviderModel.LOGIN_HINT, String.valueOf(loginHint));
|
||||
config.put(POST_BINDING_RESPONSE, "true");
|
||||
config.put(POST_BINDING_AUTHN_REQUEST, "true");
|
||||
config.put(VALIDATE_SIGNATURE, "false");
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package org.keycloak.testsuite.broker;
|
||||
|
||||
public class KcSamlBrokerLoginHintWithOptionDisabledTest extends AbstractSamlLoginHintTest {
|
||||
@Override
|
||||
boolean isLoginHintOptionEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package org.keycloak.testsuite.broker;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestTools.getConsumerRoot;
|
||||
import static org.keycloak.testsuite.broker.BrokerTestTools.waitForPage;
|
||||
|
||||
public class KcSamlBrokerLoginHintWithOptionEnabledTest extends AbstractSamlLoginHintTest {
|
||||
|
||||
|
||||
// KEYCLOAK-13950
|
||||
@Test
|
||||
public void testPassLoginHintWithXmlCharShouldEncodeIt() {
|
||||
String username = "all-info-set@localhost.com";
|
||||
createUser(bc.providerRealmName(), username, "password", "FirstName");
|
||||
|
||||
driver.navigate().to(getAccountUrl(getConsumerRoot(), bc.consumerRealmName()));
|
||||
log.debug("Clicking social " + bc.getIDPAlias());
|
||||
String fishyLoginHint = "<an-xml-tag>";
|
||||
addLoginHintOnSocialButton(fishyLoginHint);
|
||||
loginPage.clickSocial(bc.getIDPAlias());
|
||||
waitForPage(driver, "log in to", true);
|
||||
Assert.assertTrue("Driver should be on the provider realm page right now",
|
||||
driver.getCurrentUrl().contains("/auth/realms/" + bc.providerRealmName() + "/"));
|
||||
log.debug("Logging in");
|
||||
|
||||
assertEquals("Username input should contain the SAML subject", loginPage.getUsername(), fishyLoginHint);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isLoginHintOptionEnabled() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ public class KcSamlFirstBrokerLoginTest extends AbstractFirstBrokerLoginTest {
|
|||
return KcSamlBrokerConfiguration.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testUpdateProfileIfNotMissingInformation() {
|
||||
|
|
|
@ -260,6 +260,13 @@
|
|||
</div>
|
||||
<kc-tooltip>{{:: 'validating-x509-certificate.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="loginHint">{{:: 'saml.loginHint' | translate}}</label>
|
||||
<div class="col-sm-4">
|
||||
<input ng-model="identityProvider.config.loginHint" id="loginHint" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'saml.loginHint.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-md-2 control-label" for="allowedClockSkew">{{:: 'allowed-clock-skew' | translate}}</label>
|
||||
<div class="col-md-6 time-selector">
|
||||
|
|
Loading…
Reference in a new issue