diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java b/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java index 6da630f557..a67741968e 100755 --- a/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java +++ b/broker/core/src/main/java/org/keycloak/broker/provider/AbstractIdentityProvider.java @@ -92,4 +92,9 @@ public abstract class AbstractIdentityProvider public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) { } + + @Override + public IdentityProviderDataMarshaller getMarshaller() { + return new DefaultDataMarshaller(); + } } diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/DefaultDataMarshaller.java b/broker/core/src/main/java/org/keycloak/broker/provider/DefaultDataMarshaller.java new file mode 100644 index 0000000000..3f8fcf2f48 --- /dev/null +++ b/broker/core/src/main/java/org/keycloak/broker/provider/DefaultDataMarshaller.java @@ -0,0 +1,40 @@ +package org.keycloak.broker.provider; + +import java.io.IOException; + +import org.keycloak.common.util.Base64Url; +import org.keycloak.util.JsonSerialization; + +/** + * @author Marek Posolda + */ +public class DefaultDataMarshaller implements IdentityProviderDataMarshaller { + + @Override + public String serialize(Object value) { + if (value instanceof String) { + return (String) value; + } else { + try { + byte[] bytes = JsonSerialization.writeValueAsBytes(value); + return Base64Url.encode(bytes); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + } + + @Override + public T deserialize(String serialized, Class clazz) { + if (clazz.equals(String.class)) { + return clazz.cast(serialized); + } else { + byte[] bytes = Base64Url.decode(serialized); + try { + return JsonSerialization.readValue(bytes, clazz); + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + } +} diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java index 1d775eec5c..42eb6fedf4 100755 --- a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java +++ b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProvider.java @@ -103,4 +103,10 @@ public interface IdentityProvider extends Provi */ Response export(UriInfo uriInfo, RealmModel realm, String format); + /** + * Implementation of marshaller to serialize/deserialize attached data to Strings, which can be saved in clientSession + * @return + */ + IdentityProviderDataMarshaller getMarshaller(); + } diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderDataMarshaller.java b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderDataMarshaller.java new file mode 100644 index 0000000000..7e57653613 --- /dev/null +++ b/broker/core/src/main/java/org/keycloak/broker/provider/IdentityProviderDataMarshaller.java @@ -0,0 +1,12 @@ +package org.keycloak.broker.provider; + +/** + * + * @author Marek Posolda + */ +public interface IdentityProviderDataMarshaller { + + String serialize(Object obj); + T deserialize(String serialized, Class clazz); + +} diff --git a/broker/saml/pom.xml b/broker/saml/pom.xml index 858a7ba21a..21a00994f0 100755 --- a/broker/saml/pom.xml +++ b/broker/saml/pom.xml @@ -45,6 +45,11 @@ jboss-logging provided + + junit + junit + test + diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLDataMarshaller.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLDataMarshaller.java new file mode 100644 index 0000000000..61f4d8af7a --- /dev/null +++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLDataMarshaller.java @@ -0,0 +1,88 @@ +package org.keycloak.broker.saml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +import javax.xml.stream.XMLEventReader; + +import org.keycloak.broker.provider.DefaultDataMarshaller; +import org.keycloak.dom.saml.v2.assertion.AssertionType; +import org.keycloak.dom.saml.v2.assertion.AuthnStatementType; +import org.keycloak.dom.saml.v2.protocol.ResponseType; +import org.keycloak.saml.common.exceptions.ParsingException; +import org.keycloak.saml.common.exceptions.ProcessingException; +import org.keycloak.saml.common.util.StaxUtil; +import org.keycloak.saml.processing.core.parsers.saml.SAMLParser; +import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil; +import org.keycloak.saml.processing.core.saml.v2.writers.SAMLAssertionWriter; +import org.keycloak.saml.processing.core.saml.v2.writers.SAMLResponseWriter; + +/** + * @author Marek Posolda + */ +public class SAMLDataMarshaller extends DefaultDataMarshaller { + + @Override + public String serialize(Object obj) { + + // Lame impl, but hopefully sufficient for now. See if something better is needed... + if (obj.getClass().getName().startsWith("org.keycloak.dom.saml")) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + try { + if (obj instanceof ResponseType) { + ResponseType responseType = (ResponseType) obj; + SAMLResponseWriter samlWriter = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos)); + samlWriter.write(responseType); + } else if (obj instanceof AssertionType) { + AssertionType assertion = (AssertionType) obj; + SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos)); + samlWriter.write(assertion); + } else if (obj instanceof AuthnStatementType) { + AuthnStatementType authnStatement = (AuthnStatementType) obj; + SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos)); + samlWriter.write(authnStatement, true); + } else { + throw new IllegalArgumentException("Don't know how to serialize object of type " + obj.getClass().getName()); + } + } catch (ProcessingException pe) { + throw new RuntimeException(pe); + } + + return new String(bos.toByteArray()); + } else { + return super.serialize(obj); + } + } + + @Override + public T deserialize(String serialized, Class clazz) { + if (clazz.getName().startsWith("org.keycloak.dom.saml")) { + String xmlString = serialized; + + try { + if (clazz.equals(ResponseType.class) || clazz.equals(AssertionType.class)) { + byte[] bytes = xmlString.getBytes(); + InputStream is = new ByteArrayInputStream(bytes); + Object respType = new SAMLParser().parse(is); + return clazz.cast(respType); + } else if (clazz.equals(AuthnStatementType.class)) { + byte[] bytes = xmlString.getBytes(); + InputStream is = new ByteArrayInputStream(bytes); + XMLEventReader xmlEventReader = new SAMLParser().createEventReader(is); + AuthnStatementType authnStatement = SAMLParserUtil.parseAuthnStatement(xmlEventReader); + return clazz.cast(authnStatement); + } else { + throw new IllegalArgumentException("Don't know how to deserialize object of type " + clazz.getName()); + } + } catch (ParsingException pe) { + throw new RuntimeException(pe); + } + + } else { + return super.deserialize(serialized, clazz); + } + } + +} diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java index 248c4de35b..0014470637 100755 --- a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java +++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java @@ -22,6 +22,7 @@ import org.keycloak.broker.provider.AbstractIdentityProvider; import org.keycloak.broker.provider.AuthenticationRequest; import org.keycloak.broker.provider.BrokeredIdentityContext; import org.keycloak.broker.provider.IdentityBrokerException; +import org.keycloak.broker.provider.IdentityProviderDataMarshaller; import org.keycloak.broker.provider.util.SimpleHttp; import org.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.dom.saml.v2.assertion.AuthnStatementType; @@ -263,4 +264,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProviderMarek Posolda + */ +public class SAMLDataMarshallerTest { + + private static final String TEST_RESPONSE = "http://localhost:8082/auth/realms/realm-with-saml-idp-basichttp://localhost:8082/auth/realms/realm-with-saml-idp-basictest-userhttp://localhost:8081/auth/realms/realm-with-brokerurn:oasis:names:tc:SAML:2.0:ac:classes:unspecified617-666-7777test-user@localhostmanager"; + + private static final String TEST_ASSERTION = "http://localhost:8082/auth/realms/realm-with-saml-idp-basictest-userhttp://localhost:8081/auth/realms/realm-with-brokerurn:oasis:names:tc:SAML:2.0:ac:classes:unspecified617-666-7777test-user@localhostmanager"; + + private static final String TEST_AUTHN_TYPE = "urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified"; + + @Test + public void testParseResponse() throws Exception { + SAMLDataMarshaller serializer = new SAMLDataMarshaller(); + ResponseType responseType = serializer.deserialize(TEST_RESPONSE, ResponseType.class); + + // test ResponseType + Assert.assertEquals(responseType.getID(), "ID_4804cf50-cd96-4b92-823e-89adaa0c78ba"); + Assert.assertEquals(responseType.getDestination(), "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint"); + Assert.assertEquals(responseType.getIssuer().getValue(), "http://localhost:8082/auth/realms/realm-with-saml-idp-basic"); + Assert.assertEquals(responseType.getAssertions().get(0).getID(), "ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9"); + + // back to String + String serialized = serializer.serialize(responseType); + Assert.assertEquals(TEST_RESPONSE, serialized); + } + + @Test + public void testParseAssertion() throws Exception { + SAMLDataMarshaller serializer = new SAMLDataMarshaller(); + AssertionType assertion = serializer.deserialize(TEST_ASSERTION, AssertionType.class); + + // test assertion + Assert.assertEquals(assertion.getID(), "ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9"); + Assert.assertEquals(((NameIDType) assertion.getSubject().getSubType().getBaseID()).getValue(), "test-user"); + + // back to String + String serialized = serializer.serialize(assertion); + Assert.assertEquals(TEST_ASSERTION, serialized); + } + + @Test + public void testParseAuthnType() throws Exception { + SAMLDataMarshaller serializer = new SAMLDataMarshaller(); + AuthnStatementType authnStatement = serializer.deserialize(TEST_AUTHN_TYPE, AuthnStatementType.class); + + // test authnStatement + Assert.assertEquals(authnStatement.getSessionIndex(), "fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5"); + + // back to String + String serialized = serializer.serialize(authnStatement); + Assert.assertEquals(TEST_AUTHN_TYPE, serialized); + } +} diff --git a/common/src/main/java/org/keycloak/common/util/ObjectUtil.java b/common/src/main/java/org/keycloak/common/util/ObjectUtil.java index cec9ea984b..1ade852c88 100644 --- a/common/src/main/java/org/keycloak/common/util/ObjectUtil.java +++ b/common/src/main/java/org/keycloak/common/util/ObjectUtil.java @@ -13,7 +13,7 @@ public class ObjectUtil { * @param str2 * @return true if both strings are null or equal */ - public static boolean isEqualOrNull(Object str1, Object str2) { + public static boolean isEqualOrBothNull(Object str1, Object str2) { if (str1 == null && str2 == null) { return true; } diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml new file mode 100644 index 0000000000..4f7d5fcd9f --- /dev/null +++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-master.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-master.xml index 3010118039..2acc0bba74 100755 --- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-master.xml +++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-master.xml @@ -10,4 +10,5 @@ + diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java index 401cf74b2d..a5429e4685 100755 --- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java +++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/updater/JpaUpdaterProvider.java @@ -12,7 +12,7 @@ public interface JpaUpdaterProvider extends Provider { public String FIRST_VERSION = "1.0.0.Final"; - public String LAST_VERSION = "1.6.1"; + public String LAST_VERSION = "1.7.0"; public String getCurrentVersionSql(String defaultSchema); diff --git a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java index 1e74002bc8..864d255dc0 100755 --- a/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java +++ b/core/src/main/java/org/keycloak/representations/idm/IdentityProviderRepresentation.java @@ -52,6 +52,7 @@ public class IdentityProviderRepresentation { protected boolean storeToken; protected boolean addReadTokenRoleOnCreate; protected boolean authenticateByDefault; + protected String firstBrokerLoginFlowAlias; protected Map config = new HashMap(); public String getInternalId() { @@ -127,6 +128,14 @@ public class IdentityProviderRepresentation { this.authenticateByDefault = authenticateByDefault; } + public String getFirstBrokerLoginFlowAlias() { + return firstBrokerLoginFlowAlias; + } + + public void setFirstBrokerLoginFlowAlias(String firstBrokerLoginFlowAlias) { + this.firstBrokerLoginFlowAlias = firstBrokerLoginFlowAlias; + } + public boolean isStoreToken() { return this.storeToken; } diff --git a/events/api/src/main/java/org/keycloak/events/Errors.java b/events/api/src/main/java/org/keycloak/events/Errors.java index d7ca253778..34c5979c7c 100755 --- a/events/api/src/main/java/org/keycloak/events/Errors.java +++ b/events/api/src/main/java/org/keycloak/events/Errors.java @@ -53,4 +53,5 @@ public interface Errors { String EMAIL_SEND_FAILED = "email_send_failed"; String INVALID_EMAIL = "invalid_email"; String IDENTITY_PROVIDER_LOGIN_FAILURE = "identity_provider_login_failure"; + String IDENTITY_PROVIDER_ERROR = "identity_provider_error"; } diff --git a/events/api/src/main/java/org/keycloak/events/EventType.java b/events/api/src/main/java/org/keycloak/events/EventType.java index 0a8b3aecee..5cffe7845c 100755 --- a/events/api/src/main/java/org/keycloak/events/EventType.java +++ b/events/api/src/main/java/org/keycloak/events/EventType.java @@ -60,6 +60,8 @@ public enum EventType { IDENTITY_PROVIDER_LOGIN(false), IDENTITY_PROVIDER_LOGIN_ERROR(false), + IDENTITY_PROVIDER_FIRST_LOGIN(true), + IDENTITY_PROVIDER_FIRST_LOGIN_ERROR(true), IDENTITY_PROVIDER_RESPONSE(false), IDENTITY_PROVIDER_RESPONSE_ERROR(false), IDENTITY_PROVIDER_RETRIEVE_TOKEN(false), diff --git a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/impl/KerberosUsernamePasswordAuthenticator.java b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/impl/KerberosUsernamePasswordAuthenticator.java index ea3f953c5a..f38eeb5be1 100644 --- a/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/impl/KerberosUsernamePasswordAuthenticator.java +++ b/federation/kerberos/src/main/java/org/keycloak/federation/kerberos/impl/KerberosUsernamePasswordAuthenticator.java @@ -17,6 +17,7 @@ import javax.security.auth.login.LoginException; import org.jboss.logging.Logger; import org.keycloak.federation.kerberos.CommonKerberosConfig; +import org.keycloak.models.ModelException; /** * @author Marek Posolda @@ -54,6 +55,8 @@ public class KerberosUsernamePasswordAuthenticator { String message = le.getMessage(); logger.debug("Message from kerberos: " + message); + checkKerberosServerAvailable(le); + // Bit cumbersome, but seems to work with tested kerberos servers boolean exists = (!message.contains("Client not found")); return exists; @@ -74,11 +77,19 @@ public class KerberosUsernamePasswordAuthenticator { logoutSubject(); return true; } catch (LoginException le) { + checkKerberosServerAvailable(le); + logger.debug("Failed to authenticate user " + username, le); return false; } } + protected void checkKerberosServerAvailable(LoginException le) { + if (le.getMessage().contains("Port Unreachable")) { + throw new ModelException("Kerberos unreachable", le); + } + } + /** * Returns true if user was successfully authenticated against Kerberos diff --git a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties index 8c8f074196..ebf3a83e46 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties +++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties @@ -374,6 +374,7 @@ table-of-identity-providers=Table of identity providers add-provider.placeholder=Add provider... provider=Provider gui-order=GUI order +first-broker-login-flow=First Login Flow redirect-uri=Redirect URI redirect-uri.tooltip=The redirect uri to use when configuring the identity provider. alias=Alias @@ -393,6 +394,7 @@ update-profile-on-first-login.tooltip=Define conditions under which a user has t trust-email=Trust Email trust-email.tooltip=If enabled then email provided by this provider is not verified even if verification is enabled for the realm. gui-order.tooltip=Number defining order of the provider in GUI (eg. on Login page). +first-broker-login-flow.tooltip=Alias of authentication flow, which is triggered after first login with this identity provider. openid-connect-config=OpenID Connect Config openid-connect-config.tooltip=OIDC SP and external IDP configuration. authorization-url=Authorization URL diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js index f1d922b31a..96ee94d8aa 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/app.js @@ -199,6 +199,9 @@ module.config([ '$routeProvider', function($routeProvider) { }, providerFactory : function(IdentityProviderFactoryLoader) { return {}; + }, + authFlows : function(AuthenticationFlowsLoader) { + return {}; } }, controller : 'RealmIdentityProviderCtrl' @@ -217,6 +220,9 @@ module.config([ '$routeProvider', function($routeProvider) { }, providerFactory : function(IdentityProviderFactoryLoader) { return new IdentityProviderFactoryLoader(); + }, + authFlows : function(AuthenticationFlowsLoader) { + return AuthenticationFlowsLoader(); } }, controller : 'RealmIdentityProviderCtrl' @@ -235,6 +241,9 @@ module.config([ '$routeProvider', function($routeProvider) { }, providerFactory : function(IdentityProviderFactoryLoader) { return IdentityProviderFactoryLoader(); + }, + authFlows : function(AuthenticationFlowsLoader) { + return AuthenticationFlowsLoader(); } }, controller : 'RealmIdentityProviderCtrl' diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js index 7b321603be..37ec3abed2 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js @@ -594,7 +594,7 @@ module.controller('IdentityProviderTabCtrl', function(Dialog, $scope, Current, N }; }); -module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload, $http, $route, realm, instance, providerFactory, IdentityProvider, serverInfo, $location, Notifications, Dialog) { +module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload, $http, $route, realm, instance, providerFactory, IdentityProvider, serverInfo, authFlows, $location, Notifications, Dialog) { console.log('RealmIdentityProviderCtrl'); $scope.realm = angular.copy(realm); @@ -678,6 +678,7 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload $scope.identityProvider.enabled = true; $scope.identityProvider.updateProfileFirstLoginMode = "off"; $scope.identityProvider.authenticateByDefault = false; + $scope.identityProvider.firstBrokerLoginFlowAlias = 'first broker login'; $scope.newIdentityProvider = true; } @@ -696,6 +697,13 @@ module.controller('RealmIdentityProviderCtrl', function($scope, $filter, $upload $scope.configuredProviders = angular.copy(realm.identityProviders); + $scope.authFlows = []; + for (var i=0 ; i {{:: 'gui-order.tooltip' | translate}} +
+ +
+
+ +
+
+ {{:: 'first-broker-login-flow.tooltip' | translate}} +
{{:: 'openid-connect-config' | translate}} {{:: 'openid-connect-config.tooltip' | translate}} diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html index bb9726f6e9..53cbf3a159 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html @@ -79,6 +79,19 @@ {{:: 'gui-order.tooltip' | translate}} +
+ +
+
+ +
+
+ {{:: 'first-broker-login-flow.tooltip' | translate}} +
{{:: 'saml-config' | translate}} {{:: 'identity-provider.saml-config.tooltip' | translate}} diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html index 2f71d197be..a4e3f1331b 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-social.html @@ -97,6 +97,19 @@ {{:: 'gui-order.tooltip' | translate}} +
+ +
+
+ +
+
+ {{:: 'first-broker-login-flow.tooltip' | translate}} +
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-confirm.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-confirm.ftl new file mode 100644 index 0000000000..28b12d0789 --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-confirm.ftl @@ -0,0 +1,21 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout displayMessage=false; section> + <#if section = "title"> + ${msg("confirmLinkIdpTitle")} + <#elseif section = "header"> + ${msg("confirmLinkIdpTitle")} + <#elseif section = "form"> +
+

${message.summary}

+
+ +
+ +
+ + +
+ +
+ + \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-email.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-email.ftl new file mode 100644 index 0000000000..ab3e83e091 --- /dev/null +++ b/forms/common-themes/src/main/resources/theme/base/login/login-idp-link-email.ftl @@ -0,0 +1,15 @@ +<#import "template.ftl" as layout> +<@layout.registrationLayout; section> + <#if section = "title"> + ${msg("emailLinkIdpTitle", idpAlias)} + <#elseif section = "header"> + ${msg("emailLinkIdpTitle", idpAlias)} + <#elseif section = "form"> +

+ ${msg("emailLinkIdp1", idpAlias, brokerContext.username, realm.name)} +

+

+ ${msg("emailLinkIdp2")} ${msg("doClickHere")} ${msg("emailLinkIdp3")} +

+ + \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-update-profile.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-update-profile.ftl index 584bea322b..458884c849 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/login-update-profile.ftl +++ b/forms/common-themes/src/main/resources/theme/base/login/login-update-profile.ftl @@ -6,7 +6,7 @@ ${msg("loginProfileTitle")} <#elseif section = "form">
- <#if realm.editUsernameAllowed> + <#if user.editUsernameAllowed>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login.ftl b/forms/common-themes/src/main/resources/theme/base/login/login.ftl index 925f99c207..5786807722 100755 --- a/forms/common-themes/src/main/resources/theme/base/login/login.ftl +++ b/forms/common-themes/src/main/resources/theme/base/login/login.ftl @@ -13,7 +13,11 @@
- + <#if usernameEditDisabled??> + + <#else> + +
@@ -29,7 +33,7 @@
- <#if realm.rememberMe> + <#if realm.rememberMe && !usernameEditDisabled??>