KEYCLOAK-12870 - Allow to pick arbitrary user for IdP linking (#6828)

* KEYCLOAK-12870 - Allow to pick arbitrary user for IdP linking

* KEYCLOAK-12870: always allow to choose user if password reset is called from first broker login flow

* KEYCLOAK-12870: remove "already authenticated as different user" check and message

* KEYCLOAK-12870: translations

* KEYCLOAK-12870: fix tests
This commit is contained in:
Dmitry Telegin 2020-03-20 09:41:35 +03:00 committed by GitHub
parent 2eab44d3f3
commit 3b24465141
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 328 additions and 73 deletions

View file

@ -40,6 +40,8 @@ public interface LoginFormsProvider extends Provider {
String USERNAME_EDIT_DISABLED = "usernameEditDisabled";
String REGISTRATION_DISABLED = "registrationDisabled";
/**
* Adds a script to the html header

View file

@ -84,14 +84,6 @@ public class ResetCredentialsActionTokenHandler extends AbstractActionTokenHande
if (firstBrokerLoginInProgress) {
UserModel linkingUser = AbstractIdpAuthenticator.getExistingUser(session, realm, authenticationSession);
if (!linkingUser.getId().equals(authenticationSession.getAuthenticatedUser().getId())) {
return ErrorPage.error(session, authenticationSession, Response.Status.INTERNAL_SERVER_ERROR,
Messages.IDENTITY_PROVIDER_DIFFERENT_USER_MESSAGE,
authenticationSession.getAuthenticatedUser().getUsername(),
linkingUser.getUsername()
);
}
SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authenticationSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
authenticationSession.setAuthNote(AbstractIdpAuthenticator.FIRST_BROKER_LOGIN_SUCCESS, serializedCtx.getIdentityProviderId());

View file

@ -56,6 +56,8 @@ public abstract class AbstractIdpAuthenticator implements Authenticator {
// Set after firstBrokerLogin is successfully finished and contains the providerId of the provider, whose 'first-broker-login' flow was just finished
public static final String FIRST_BROKER_LOGIN_SUCCESS = "FIRST_BROKER_LOGIN_SUCCESS";
// Set if nested firstBrokerLogin is detected, allowing to report a detailed error
public static final String NESTED_FIRST_BROKER_CONTEXT = "NESTED_FIRST_BROKER_CONTEXT";
@Override
public void authenticate(AuthenticationFlowContext context) {

View file

@ -22,16 +22,22 @@ import org.keycloak.authentication.AuthenticationFlowError;
import org.keycloak.authentication.AuthenticationFlowException;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
import org.keycloak.authentication.authenticators.browser.UsernamePasswordForm;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.UserModel;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import java.util.Optional;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
/**
* Same like classic username+password form, but username is "known" and user can't change it
* Same like classic username+password form, but for use in IdP linking.
*
* User identity is optionally established by the preceding idp-create-user-if-unique execution.
* In this case username field will be pre-filled (but still changeable).
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@ -39,34 +45,53 @@ public class IdpUsernamePasswordForm extends UsernamePasswordForm {
@Override
protected Response challenge(AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getAuthenticationSession());
return setupForm(context, formData, existingUser)
return setupForm(context, formData, getExistingUser(context))
.setStatus(Response.Status.OK)
.createLoginUsernamePassword();
}
@Override
protected boolean validateForm(AuthenticationFlowContext context, MultivaluedMap<String, String> formData) {
UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getAuthenticationSession());
context.setUser(existingUser);
Optional<UserModel> existingUser = getExistingUser(context);
existingUser.ifPresent(context::setUser);
boolean result = validateUserAndPassword(context, formData);
// Restore formData for the case of error
setupForm(context, formData, existingUser);
return validatePassword(context, existingUser, formData);
return result;
}
protected LoginFormsProvider setupForm(AuthenticationFlowContext context, MultivaluedMap<String, String> formData, UserModel existingUser) {
protected LoginFormsProvider setupForm(AuthenticationFlowContext context, MultivaluedMap<String, String> formData, Optional<UserModel> existingUser) {
SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(context.getAuthenticationSession(), AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
if (serializedCtx == null) {
throw new AuthenticationFlowException("Not found serialized context in clientSession", AuthenticationFlowError.IDENTITY_PROVIDER_ERROR);
}
formData.putSingle(AuthenticationManager.FORM_USERNAME, existingUser.getUsername());
return context.form()
existingUser.ifPresent(u -> formData.putSingle(AuthenticationManager.FORM_USERNAME, u.getUsername()));
LoginFormsProvider form = context.form()
.setFormData(formData)
.setAttribute(LoginFormsProvider.USERNAME_EDIT_DISABLED, true)
.setInfo(Messages.FEDERATED_IDENTITY_CONFIRM_REAUTHENTICATE_MESSAGE, existingUser.getUsername(), serializedCtx.getIdentityProviderId());
.setAttribute(LoginFormsProvider.REGISTRATION_DISABLED, true)
.setInfo(Messages.FEDERATED_IDENTITY_CONFIRM_REAUTHENTICATE_MESSAGE, serializedCtx.getIdentityProviderId());
SerializedBrokeredIdentityContext serializedCtx0 = SerializedBrokeredIdentityContext.readFromAuthenticationSession(context.getAuthenticationSession(), AbstractIdpAuthenticator.NESTED_FIRST_BROKER_CONTEXT);
if (serializedCtx0 != null) {
BrokeredIdentityContext ctx0 = serializedCtx0.deserialize(context.getSession(), context.getAuthenticationSession());
form.setError(Messages.NESTED_FIRST_BROKER_FLOW_MESSAGE, ctx0.getIdpConfig().getAlias(), ctx0.getUsername());
context.getAuthenticationSession().setAuthNote(AbstractIdpAuthenticator.NESTED_FIRST_BROKER_CONTEXT, null);
}
return form;
}
private Optional<UserModel> getExistingUser(AuthenticationFlowContext context) {
try {
return Optional.of(AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getAuthenticationSession()));
} catch (AuthenticationFlowException ex) {
log.debug("No existing user in authSession", ex);
return Optional.empty();
}
}
}

View file

@ -42,7 +42,7 @@ public class IdpUsernamePasswordFormFactory extends UsernamePasswordFormFactory
@Override
public String getHelpText() {
return "Validates a password from login form. Username is already known from identity provider authentication";
return "Validates a password from login form. Username may be already known from identity provider authentication";
}
@Override

View file

@ -54,9 +54,10 @@ public class ResetCredentialChooseUser implements Authenticator, AuthenticatorFa
if (existingUserId != null) {
UserModel existingUser = AbstractIdpAuthenticator.getExistingUser(context.getSession(), context.getRealm(), context.getAuthenticationSession());
logger.debugf("Forget-password triggered when reauthenticating user after first broker login. Skipping reset-credential-choose-user screen and using user '%s' ", existingUser.getUsername());
logger.debugf("Forget-password triggered when reauthenticating user after first broker login. Prefilling reset-credential-choose-user screen with user '%s' ", existingUser.getUsername());
context.setUser(existingUser);
context.success();
Response challenge = context.form().createPasswordReset();
context.challenge(challenge);
return;
}

View file

@ -400,7 +400,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
attributes.put("realm", new RealmBean(realm));
List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
identityProviders = LoginFormsUtil.filterIdentityProviders(identityProviders, session, realm, attributes, formData);
identityProviders = LoginFormsUtil.filterIdentityProviders(identityProviders, session, realm, attributes, formData, context);
attributes.put("social", new IdentityProviderBean(realm, session, identityProviders, baseUriWithCodeAndClientId));
attributes.put("url", new UrlBean(realm, theme, baseUri, this.actionUri));

View file

@ -17,19 +17,25 @@
package org.keycloak.forms.login.freemarker;
import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.sessions.AuthenticationSessionModel;
import javax.ws.rs.core.MultivaluedMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Various util methods, so the logic is not hardcoded in freemarker beans
@ -39,7 +45,7 @@ import java.util.Set;
public class LoginFormsUtil {
// Display just those identityProviders on login screen, which are already linked to "known" established user
public static List<IdentityProviderModel> filterIdentityProviders(List<IdentityProviderModel> providers, KeycloakSession session, RealmModel realm,
public static List<IdentityProviderModel> filterIdentityProvidersByUser(List<IdentityProviderModel> providers, KeycloakSession session, RealmModel realm,
Map<String, Object> attributes, MultivaluedMap<String, String> formData) {
Boolean usernameEditDisabled = (Boolean) attributes.get(LoginFormsProvider.USERNAME_EDIT_DISABLED);
@ -71,4 +77,21 @@ public class LoginFormsUtil {
return providers;
}
}
public static List<IdentityProviderModel> filterIdentityProviders(List<IdentityProviderModel> providers, KeycloakSession session, RealmModel realm,
Map<String, Object> attributes, MultivaluedMap<String, String> formData, AuthenticationFlowContext context) {
if (context != null) {
AuthenticationSessionModel authSession = context.getAuthenticationSession();
SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
if (serializedCtx != null) {
IdentityProviderModel idp = serializedCtx.deserialize(session, authSession).getIdpConfig();
return providers.stream()
.filter(p -> !Objects.equals(p.getProviderId(), idp.getProviderId()))
.collect(Collectors.toList());
}
}
return providers;
}
}

View file

@ -80,7 +80,7 @@ public class Messages {
public static final String FEDERATED_IDENTITY_CONFIRM_REAUTHENTICATE_MESSAGE = "federatedIdentityConfirmReauthenticateMessage";
public static final String IDENTITY_PROVIDER_DIFFERENT_USER_MESSAGE = "identityProviderDifferentUserMessage";
public static final String NESTED_FIRST_BROKER_FLOW_MESSAGE = "nestedFirstBrokerFlowMessage";
public static final String CONFIGURE_TOTP = "configureTotpMessage";

View file

@ -22,6 +22,7 @@ import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.OAuthErrorException;
import org.keycloak.authentication.AuthenticationProcessor;
import org.keycloak.authentication.AuthenticationFlowException;
import org.keycloak.authentication.authenticators.broker.AbstractIdpAuthenticator;
import org.keycloak.authentication.authenticators.broker.util.PostBrokerLoginConstants;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
@ -85,6 +86,7 @@ import org.keycloak.services.managers.BruteForceProtector;
import org.keycloak.services.managers.ClientSessionCode;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.account.AccountFormService;
import org.keycloak.services.util.AuthenticationFlowURLHelper;
import org.keycloak.services.util.BrowserHistoryHelper;
import org.keycloak.services.util.CacheControlUtil;
import org.keycloak.services.util.DefaultClientSessionContext;
@ -103,6 +105,7 @@ import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.URI;
@ -553,7 +556,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
if (federatedUser == null) {
logger.debugf("Federated user not found for provider '%s' and broker username '%s' . Redirecting to flow for firstBrokerLogin", providerId, context.getUsername());
logger.debugf("Federated user not found for provider '%s' and broker username '%s'", providerId, context.getUsername());
String username = context.getModelUsername();
if (username == null) {
@ -568,6 +571,19 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
username = username.trim();
context.setModelUsername(username);
SerializedBrokeredIdentityContext ctx0 = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authenticationSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
if (ctx0 != null) {
SerializedBrokeredIdentityContext ctx1 = SerializedBrokeredIdentityContext.serialize(context);
ctx1.saveToAuthenticationSession(authenticationSession, AbstractIdpAuthenticator.NESTED_FIRST_BROKER_CONTEXT);
logger.warnv("Nested first broker flow detected: {0} -> {1}", ctx0.getIdentityProviderId(), ctx1.getIdentityProviderId());
logger.debug("Resuming last execution");
URI redirect = new AuthenticationFlowURLHelper(session, realmModel, session.getContext().getUri())
.getLastExecutionUrl(authenticationSession);
return Response.status(Status.FOUND).location(redirect).build();
}
logger.debug("Redirecting to flow for firstBrokerLogin");
boolean forwardedPassiveLogin = "true".equals(authenticationSession.getAuthNote(AuthenticationProcessor.FORWARDED_PASSIVE_LOGIN));
// Redirect to firstBrokerLogin after successful login and ensure that previous authentication state removed
AuthenticationProcessor.resetFlow(authenticationSession, LoginActionsService.FIRST_BROKER_LOGIN_PATH);
@ -796,11 +812,6 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
if (firstBrokerLoginInProgress) {
logger.debugf("Reauthenticated with broker '%s' when linking user '%s' with other broker", context.getIdpConfig().getAlias(), federatedUser.getUsername());
UserModel linkingUser = AbstractIdpAuthenticator.getExistingUser(session, realmModel, authSession);
if (!linkingUser.getId().equals(federatedUser.getId())) {
return redirectToErrorPage(authSession, Response.Status.BAD_REQUEST, Messages.IDENTITY_PROVIDER_DIFFERENT_USER_MESSAGE, federatedUser.getUsername(), linkingUser.getUsername());
}
SerializedBrokeredIdentityContext serializedCtx = SerializedBrokeredIdentityContext.readFromAuthenticationSession(authSession, AbstractIdpAuthenticator.BROKERED_CONTEXT_NOTE);
authSession.setAuthNote(AbstractIdpAuthenticator.FIRST_BROKER_LOGIN_SUCCESS, serializedCtx.getIdentityProviderId());

View file

@ -39,6 +39,10 @@ public class LoginPasswordResetPage extends LanguageComboboxAwarePage {
@FindBy(partialLinkText = "Back to Login")
private WebElement backToLogin;
public void changePassword() {
submitButton.click();
}
public void changePassword(String username) {
usernameInput.clear();
usernameInput.sendKeys(username);
@ -62,6 +66,10 @@ public class LoginPasswordResetPage extends LanguageComboboxAwarePage {
return emailErrorMessage != null ? emailErrorMessage.getText() : null;
}
public String getUsername() {
return usernameInput.getAttribute("value");
}
public void backToLogin() {
backToLogin.click();
}

View file

@ -181,7 +181,7 @@ public class ProvidersTest extends AbstractAuthenticationTest {
addProviderInfo(result, "idp-review-profile", "Review Profile",
"User reviews and updates profile data retrieved from Identity Provider in the displayed form");
addProviderInfo(result, "idp-username-password-form", "Username Password Form for identity provider reauthentication",
"Validates a password from login form. Username is already known from identity provider authentication");
"Validates a password from login form. Username may be already known from identity provider authentication");
addProviderInfo(result, "no-cookie-redirect", "Browser Redirect/Refresh", "Perform a 302 redirect to get user agent's current URI on authenticate path with an auth_session_id query parameter. This is for client's that do not support cookies.");
addProviderInfo(result, "push-button-authenticator", "TEST: Button Login",
"Just press the button to login.");

View file

@ -45,6 +45,7 @@ import org.keycloak.testsuite.pages.InfoPage;
import org.keycloak.testsuite.pages.LoginConfigTotpPage;
import org.keycloak.testsuite.pages.LoginExpiredPage;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.LoginPasswordResetPage;
import org.keycloak.testsuite.pages.LoginTotpPage;
import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.keycloak.testsuite.pages.ProceedPage;
@ -112,6 +113,9 @@ public abstract class AbstractBaseBrokerTest extends AbstractKeycloakTest {
@Page
protected LoginConfigTotpPage totpPage;
@Page
protected LoginPasswordResetPage loginPasswordResetPage;
@Page
protected VerifyEmailPage verifyEmailPage;
@ -172,14 +176,19 @@ public abstract class AbstractBaseBrokerTest extends AbstractKeycloakTest {
}
protected String createUser(String username) {
UserRepresentation newUser = UserBuilder.create().username(username).email(USER_EMAIL).enabled(true).build();
protected String createUser(String username, String email) {
UserRepresentation newUser = UserBuilder.create().username(username).email(email).enabled(true).build();
String userId = createUserWithAdminClient(adminClient.realm(bc.consumerRealmName()), newUser);
resetUserPassword(adminClient.realm(bc.consumerRealmName()).users().get(userId), "password", false);
return userId;
}
protected String createUser(String username) {
return createUser(username, USER_EMAIL);
}
protected void assertNumFederatedIdentities(String userId, int expected) {
assertEquals(expected, adminClient.realm(bc.consumerRealmName()).users().get(userId).getFederatedIdentity().size());
}

View file

@ -4,6 +4,7 @@ import org.jboss.arquillian.graphene.page.Page;
import org.junit.Test;
import org.keycloak.admin.client.resource.AuthenticationManagementResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.authentication.authenticators.broker.IdpConfirmLinkAuthenticatorFactory;
import org.keycloak.authentication.authenticators.broker.IdpCreateUserIfUniqueAuthenticatorFactory;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
@ -173,4 +174,11 @@ public abstract class AbstractBrokerTest extends AbstractInitializedBaseBrokerTe
flows.updateAuthenticatorConfig(config.getId(), config);
}
}
static void disableExistingUser(AuthenticationExecutionInfoRepresentation execution, AuthenticationManagementResource flows) {
if (execution.getProviderId() != null && (execution.getProviderId().equals(IdpCreateUserIfUniqueAuthenticatorFactory.PROVIDER_ID) || execution.getProviderId().equals(IdpConfirmLinkAuthenticatorFactory.PROVIDER_ID))) {
execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED.name());
flows.updateExecutions(DefaultAuthenticationFlows.FIRST_BROKER_LOGIN_FLOW, execution);
}
}
}

View file

@ -91,7 +91,7 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractInitializedBa
assertEquals("User with email user@localhost.com already exists. How do you want to continue?", idpConfirmLinkPage.getMessage());
idpConfirmLinkPage.clickLinkAccount();
assertEquals("Authenticate as consumer to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
try {
this.loginPage.findSocialButton(bc.getIDPAlias());
@ -112,6 +112,143 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractInitializedBa
assertNumFederatedIdentities(existingUser, 1);
}
/**
* KEYCLOAK-12870
*/
@Test
public void testLinkAccountByReauthenticationWithUsernameAndPassword() {
updateExecutions(AbstractBrokerTest::disableUpdateProfileOnFirstLogin);
String existingUser = createUser("consumer");
String anotherUser = createUser("foobar", "foo@bar.baz");
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
logInWithBroker(bc);
waitForPage(driver, "account already exists", false);
assertTrue(idpConfirmLinkPage.isCurrent());
assertEquals("User with email user@localhost.com already exists. How do you want to continue?", idpConfirmLinkPage.getMessage());
idpConfirmLinkPage.clickLinkAccount();
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
try {
this.loginPage.findSocialButton(bc.getIDPAlias());
Assert.fail("Not expected to see social button with " + bc.getIDPAlias());
} catch (NoSuchElementException expected) {
}
try {
this.loginPage.clickRegister();
Assert.fail("Not expected to see register link");
} catch (NoSuchElementException expected) {
}
loginPage.login("foobar", "password");
waitForAccountManagementTitle();
accountUpdateProfilePage.assertCurrent();
assertNumFederatedIdentities(existingUser, 0);
assertNumFederatedIdentities(anotherUser, 1);
}
/**
* KEYCLOAK-12870
*/
@Test
public void testLinkAccountByReauthenticationNoExistingUser() {
updateExecutions(AbstractBrokerTest::disableUpdateProfileOnFirstLogin);
updateExecutions(AbstractBrokerTest::disableExistingUser);
String existingUser = createUser("consumer");
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
logInWithBroker(bc);
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
try {
this.loginPage.findSocialButton(bc.getIDPAlias());
Assert.fail("Not expected to see social button with " + bc.getIDPAlias());
} catch (NoSuchElementException expected) {
}
try {
this.loginPage.clickRegister();
Assert.fail("Not expected to see register link");
} catch (NoSuchElementException expected) {
}
loginPage.login("consumer", "password");
waitForAccountManagementTitle();
accountUpdateProfilePage.assertCurrent();
assertNumFederatedIdentities(existingUser, 1);
}
/**
* KEYCLOAK-12870
*/
@Test
public void testLinkAccountByReauthenticationResetPassword() {
updateExecutions(AbstractBrokerTest::disableUpdateProfileOnFirstLogin);
String existingUser = createUser("consumer");
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
logInWithBroker(bc);
waitForPage(driver, "account already exists", false);
assertTrue(idpConfirmLinkPage.isCurrent());
assertEquals("User with email user@localhost.com already exists. How do you want to continue?", idpConfirmLinkPage.getMessage());
idpConfirmLinkPage.clickLinkAccount();
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
try {
this.loginPage.findSocialButton(bc.getIDPAlias());
Assert.fail("Not expected to see social button with " + bc.getIDPAlias());
} catch (NoSuchElementException expected) {
}
try {
this.loginPage.clickRegister();
Assert.fail("Not expected to see register link");
} catch (NoSuchElementException expected) {
}
loginPage.resetPassword();
loginPasswordResetPage.assertCurrent();
assertEquals("consumer", loginPasswordResetPage.getUsername());
}
/**
* KEYCLOAK-12870
*/
@Test
public void testLinkAccountByReauthenticationResetPasswordNoExistingUser() {
updateExecutions(AbstractBrokerTest::disableUpdateProfileOnFirstLogin);
updateExecutions(AbstractBrokerTest::disableExistingUser);
String existingUser = createUser("consumer");
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
logInWithBroker(bc);
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
try {
this.loginPage.findSocialButton(bc.getIDPAlias());
Assert.fail("Not expected to see social button with " + bc.getIDPAlias());
} catch (NoSuchElementException expected) {
}
try {
this.loginPage.clickRegister();
Assert.fail("Not expected to see register link");
} catch (NoSuchElementException expected) {
}
loginPage.resetPassword();
loginPasswordResetPage.assertCurrent();
assertTrue(loginPasswordResetPage.getUsername().isEmpty());
}
/**
* Refers to in old test suite: org.keycloak.testsuite.broker.AbstractFirstBrokerLoginTest#testLinkAccountByReauthenticationWithPassword_browserButtons
@ -163,11 +300,11 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractInitializedBa
idpConfirmLinkPage.assertCurrent();
idpConfirmLinkPage.clickLinkAccount();
// Login screen shown. Username is prefilled and disabled. Registration link and social buttons are not shown
// Login screen shown. Username is prefilled. Registration link and social buttons are not shown
assertEquals("consumer", loginPage.getUsername());
assertFalse(loginPage.isUsernameInputEnabled());
assertTrue(loginPage.isUsernameInputEnabled());
assertEquals("Authenticate as consumer to link your account with " + bc.getIDPAlias(), this.loginPage.getInfoMessage());
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), this.loginPage.getInfoMessage());
try {
loginPage.findSocialButton(bc.getIDPAlias());
@ -217,6 +354,8 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractInitializedBa
configureSMTPServer();
this.loginPage.resetPassword();
this.loginPasswordResetPage.assertCurrent();
this.loginPasswordResetPage.changePassword();
assertEquals("You should receive an email shortly with further instructions.", this.loginPage.getSuccessMessage());
assertEquals(1, MailServer.getReceivedMessages().length);
MimeMessage message = MailServer.getLastReceivedMessage();
@ -268,6 +407,8 @@ public abstract class AbstractFirstBrokerLoginTest extends AbstractInitializedBa
configureSMTPServer();
this.loginPage.resetPassword();
this.loginPasswordResetPage.assertCurrent();
this.loginPasswordResetPage.changePassword();
assertEquals("You should receive an email shortly with further instructions.", this.loginPage.getSuccessMessage());
assertEquals(1, MailServer.getReceivedMessages().length);
MimeMessage message = MailServer.getLastReceivedMessage();

View file

@ -44,6 +44,7 @@ public class KcOidcBrokerConfiguration implements BrokerConfiguration {
RealmRepresentation realm = new RealmRepresentation();
realm.setRealm(REALM_CONS_NAME);
realm.setEnabled(true);
realm.setResetPasswordAllowed(true);
return realm;
}

View file

@ -52,7 +52,7 @@ public class KcOidcFirstBrokerLoginTest extends AbstractFirstBrokerLoginTest {
assertEquals("User with email user@localhost.com already exists. How do you want to continue?", idpConfirmLinkPage.getMessage());
idpConfirmLinkPage.clickLinkAccount();
assertEquals("Authenticate as testuser to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
try {
this.loginPage.findSocialButton(bc.getIDPAlias());
@ -72,6 +72,51 @@ public class KcOidcFirstBrokerLoginTest extends AbstractFirstBrokerLoginTest {
}
}
/**
* Tests that nested first broker flows are not allowed. The user wants to link federatedIdentity with existing account. He will try link by reauthentication
* with different broker not linked to his account. Error message should be shown, and reauthentication should be resumed.
*/
@Test
public void testNestedFirstBrokerFlow() {
KcSamlBrokerConfiguration samlBrokerConfig = KcSamlBrokerConfiguration.INSTANCE;
ClientRepresentation samlClient = samlBrokerConfig.createProviderClients(suiteContext).get(0);
IdentityProviderRepresentation samlBroker = samlBrokerConfig.setUpIdentityProvider(suiteContext);
RealmResource consumerRealm = adminClient.realm(bc.consumerRealmName());
try {
updateExecutions(AbstractBrokerTest::disableUpdateProfileOnFirstLogin);
adminClient.realm(bc.providerRealmName()).clients().create(samlClient);
consumerRealm.identityProviders().create(samlBroker);
driver.navigate().to(getAccountUrl(bc.consumerRealmName()));
createUser(bc.getUserLogin());
logInWithBroker(bc);
waitForPage(driver, "account already exists", false);
assertTrue(idpConfirmLinkPage.isCurrent());
assertEquals("User with email user@localhost.com already exists. How do you want to continue?", idpConfirmLinkPage.getMessage());
idpConfirmLinkPage.clickLinkAccount();
assertEquals("Authenticate to link your account with " + bc.getIDPAlias(), loginPage.getInfoMessage());
try {
this.loginPage.findSocialButton(bc.getIDPAlias());
org.junit.Assert.fail("Not expected to see social button with " + samlBrokerConfig.getIDPAlias());
} catch (NoSuchElementException expected) {
}
log.debug("Clicking social " + samlBrokerConfig.getIDPAlias());
loginPage.clickSocial(samlBrokerConfig.getIDPAlias());
assertEquals(String.format("The %s user %s is not linked to any known user.", samlBrokerConfig.getIDPAlias(), samlBrokerConfig.getUserLogin()), loginPage.getError());
assertNumFederatedIdentities(consumerRealm.users().search(samlBrokerConfig.getUserLogin()).get(0).getId(), 0);
} finally {
updateExecutions(AbstractBrokerTest::setUpMissingUpdateProfileOnFirstLogin);
removeUserByUsername(consumerRealm, "consumer");
}
}
/**
* Refers to in old test suite: OIDCFirstBrokerLoginTest#testMoreIdpAndBackButtonWhenLinkingAccount

View file

@ -51,6 +51,7 @@ public class KcSamlBrokerConfiguration implements BrokerConfiguration {
realm.setEnabled(true);
realm.setRealm(REALM_CONS_NAME);
realm.setResetPasswordAllowed(true);
return realm;
}

View file

@ -168,7 +168,7 @@ federatedIdentityExistsMessage=Ein Benutzer mit {0} {1} existiert bereits. Bitte
confirmLinkIdpTitle=Das Benutzerkonto existiert bereits.
federatedIdentityConfirmLinkMessage=Ein Benutzer mit {0} {1} existiert bereits. Wie m\u00F6chten Sie fortfahren?
federatedIdentityConfirmReauthenticateMessage=Als {0} anmelden um das Benutzerkonto mit {1} zu verkn\u00FCpfen
federatedIdentityConfirmReauthenticateMessage=Anmelden um das Benutzerkonto mit {0} zu verkn\u00FCpfen
confirmLinkIdpReviewProfile=Benutzerkonto \u00FCberpr\u00FCfen
confirmLinkIdpContinue=Zu einem bestehenden Benutzerkonto hinzuf\u00FCgen
@ -221,7 +221,6 @@ couldNotObtainTokenMessage=Konnte kein Token vom Identity Provider erhalten.
unexpectedErrorRetrievingTokenMessage=Unerwarteter Fehler w\u00E4hrend dem Empfang des Tokens vom Identity Provider.
unexpectedErrorHandlingResponseMessage=Unerwarteter Fehler w\u00E4hrend der Bearbeitung der Antwort vom Identity Provider.
identityProviderAuthenticationFailedMessage=Authentifizierung fehlgeschlagen. Authentifizierung mit dem Identity Provider nicht m\u00F6glich.
identityProviderDifferentUserMessage=Als {0} authentifiziert, aber Authentifizierung als {1} erwartet
couldNotSendAuthenticationRequestMessage=Konnte Authentifizierungsanfrage nicht an den Identity Provider senden.
unexpectedErrorHandlingRequestMessage=Unerwarteter Fehler w\u00E4hrend der Bearbeitung der Anfrage an den Identity Provider.
invalidAccessCodeMessage=Ung\u00FCltiger Access-Code.

View file

@ -175,7 +175,7 @@ federatedIdentityEmailExistsMessage=Cet utilisateur avec ce courriel existe d\u0
confirmLinkIdpTitle=Ce compte existe d\u00e9j\u00e0
federatedIdentityConfirmLinkMessage=L''utilisateur {0} {1} existe d\u00e9j\u00e0. Que souhaitez-vous faire ?
federatedIdentityConfirmReauthenticateMessage=Identifiez vous en tant que {0} afin de lier votre compte avec {1}
federatedIdentityConfirmReauthenticateMessage=Identifiez vous afin de lier votre compte avec {0}
confirmLinkIdpReviewProfile=V\u00e9rifiez vos informations de profil
confirmLinkIdpContinue=Souhaitez-vous lier {0} \u00e0 votre compte existant
@ -228,7 +228,6 @@ couldNotObtainTokenMessage=Impossible de r\u00e9cup\u00e9rer le jeton du fournis
unexpectedErrorRetrievingTokenMessage=Erreur inattendue lors de la r\u00e9cup\u00e9ration du jeton provenant du fournisseur d''identit\u00e9.
unexpectedErrorHandlingResponseMessage=Erreur inattendue lors du traitement de la r\u00e9ponse provenant du fournisseur d''identit\u00e9.
identityProviderAuthenticationFailedMessage=L''authentification a \u00e9chou\u00e9e. Impossible de s''authentifier avec le fournisseur d''identit\u00e9.
identityProviderDifferentUserMessage=Authentifi\u00e9 en tant que {0}, alors que l''authentification aurait du \u00eatre {1}
couldNotSendAuthenticationRequestMessage=Impossible d''envoyer la requ\u00eate d''authentification vers le fournisseur d''identit\u00e9.
unexpectedErrorHandlingRequestMessage=Erreur inattendue lors du traitement de la requ\u00eate vers le fournisseur d''identit\u00e9.
invalidAccessCodeMessage=Code d''acc\u00e8s invalide.
@ -273,4 +272,4 @@ noCertificate=[Pas de certificat]
pageNotFound=Page non trouv\u00e9e
internalServerError=Une erreur interne du serveur s''est produite
internalServerError=Une erreur interne du serveur s''est produite

View file

@ -138,7 +138,7 @@ federatedIdentityExistsMessage=L''utente con {0} {1} esiste gi\u00e0. Effettua i
confirmLinkIdpTitle=Account gi\u00e0 esistente
federatedIdentityConfirmLinkMessage=L''utente con {0} {1} esiste gi\u00e0. Come vuoi procedere?
federatedIdentityConfirmReauthenticateMessage=Autenticati come {0} per associare il tuo account con {1}
federatedIdentityConfirmReauthenticateMessage=Autenticati per associare il tuo account con {0}
confirmLinkIdpReviewProfile=Rivedi profilo
confirmLinkIdpContinue=Aggiungi all''account esistente
@ -191,7 +191,6 @@ couldNotObtainTokenMessage=Non posso ottenere un token dall''identity provider.
unexpectedErrorRetrievingTokenMessage=Errore inaspettato nel recupero del token dall''identity provider.
unexpectedErrorHandlingResponseMessage=Errore inaspettato nella gestione della risposta dall''identity provider.
identityProviderAuthenticationFailedMessage=Autenticazione fallita. Non posso effettuare l''autenticazione con l''identity provider.
identityProviderDifferentUserMessage=Autenticato come {0}, ma previsto per essere autenticato come {1}
couldNotSendAuthenticationRequestMessage=Impossibile inviare la richiesta di autenticazione all''identity provider.
unexpectedErrorHandlingRequestMessage=Errore inaspettato nella gestione della richiesta di autenticazione all''identity provider.
invalidAccessCodeMessage=Codice di accesso non valido.

View file

@ -182,7 +182,7 @@ federatedIdentityExistsMessage={0} {1} のユーザーは既に存在します
confirmLinkIdpTitle=既に存在するアカウントです。
federatedIdentityConfirmLinkMessage={0} {1} のユーザーは既に存在します。継続しますか?
federatedIdentityConfirmReauthenticateMessage={1} でアカウントをリンクするために {0} として認証します
#federatedIdentityConfirmReauthenticateMessage={1} でアカウントをリンクするために {0} として認証します
confirmLinkIdpReviewProfile=プロフィールの確認
confirmLinkIdpContinue=既存のアカウントに追加する
@ -240,7 +240,6 @@ couldNotObtainTokenMessage=アイデンティティ プロバイダーからト
unexpectedErrorRetrievingTokenMessage=アイデンティティ プロバイダーからのトークン取得で予期せぬエラーが発生しました。
unexpectedErrorHandlingResponseMessage=アイデンティティ プロバイダーからの応答を処理する際に予期せぬエラーが発生しました。
identityProviderAuthenticationFailedMessage=認証に失敗しました。アイデンティティ プロバイダーを使用して認証できませんでした。
identityProviderDifferentUserMessage={1} として認証されることを期待していましたが、{0} として認証されました
couldNotSendAuthenticationRequestMessage=アイデンティティ プロバイダーに認証要求を送信することができませんでした。
unexpectedErrorHandlingRequestMessage=アイデンティティ プロバイダーへの認証要求を処理する際に予期せぬエラーが発生しました。
invalidAccessCodeMessage=無効なアクセスコードです。

View file

@ -143,7 +143,7 @@ federatedIdentityExistsMessage=Naudotojas {0} {1} jau egzistuoja. Prašome prsij
confirmLinkIdpTitle=Paskyra jau egzistuoja
federatedIdentityConfirmLinkMessage=Naudotojas {0} {1} jau egzistuoja. Ar tęsti?
federatedIdentityConfirmReauthenticateMessage=Prisijunkite prie {0} norėdami susieti paskyrą su {1}
federatedIdentityConfirmReauthenticateMessage=Prisijunkite norėdami susieti paskyrą su {0}
confirmLinkIdpReviewProfile=Peržiūrėti naudotojo profilio informaciją
confirmLinkIdpContinue=Susieti su egzistuojančia paskyra
@ -194,7 +194,6 @@ couldNotObtainTokenMessage=Negaunamas prieigos raktas iš tapatybės teikėjo.
unexpectedErrorRetrievingTokenMessage=Prieigos rakšo gavimo iš tapatybės teikėjo metu įvyko netikėta klaida.
unexpectedErrorHandlingResponseMessage=Tapatybės teikėjo atsakymo apdorojimo metu įvyko netikėta klaida.
identityProviderAuthenticationFailedMessage=Autentifikacijos klaida. Nepavyksta autentifikacija su tapatybės teikėju.
identityProviderDifferentUserMessage=Autentifikuota kaip {0}, nors buvo tikimasi {1}
couldNotSendAuthenticationRequestMessage=Tapatybės teikėjui nepavyksta nusiųsti autentifikacijos užklausos.
unexpectedErrorHandlingRequestMessage=Užklausos tapatybės teikėjui formavimo metu įvyko netikėta klaida.
invalidAccessCodeMessage=Neteisingas prieigos kodas.

View file

@ -182,7 +182,7 @@ federatedIdentityExistsMessage=Gebruiker met {0} {1} bestaat al. Log in met het
confirmLinkIdpTitle=Account bestaat al
federatedIdentityConfirmLinkMessage=Gebruiker met {0} {1} bestaat al. Hoe wilt u doorgaan?
federatedIdentityConfirmReauthenticateMessage=Authenticeer als {0} om uw account te koppelen {1}
federatedIdentityConfirmReauthenticateMessage=Authenticeer om uw account te koppelen {0}
confirmLinkIdpReviewProfile=Nalopen profiel
confirmLinkIdpContinue=Voeg toe aan bestaande account
@ -240,7 +240,6 @@ couldNotObtainTokenMessage=Kon geen token bemachtigen van de identity provider.
unexpectedErrorRetrievingTokenMessage=Onverwachte fout bij het ophalen van de token van de identity provider.
unexpectedErrorHandlingResponseMessage=Onverwachte fout bij het verwerken van de respons van de identity provider.
identityProviderAuthenticationFailedMessage=Verificatie mislukt. Er kon niet worden geauthenticeerd met de identity provider.
identityProviderDifferentUserMessage=U bent geauthenticeerd als {0}, maar u werd verwacht als {1} geauthenticeerd te zijn
couldNotSendAuthenticationRequestMessage=Kan het authenticatieverzoek niet verzenden naar de identity provider.
unexpectedErrorHandlingRequestMessage=Onverwachte fout bij het verwerken van het authenticatieverzoek naar de identity provider.
invalidAccessCodeMessage=Ongeldige toegangscode.

View file

@ -141,7 +141,7 @@ federatedIdentityExistsMessage=Bruker med {0} {1} finnes allerede. Vennligst log
confirmLinkIdpTitle=Kontoen finnes allerede
federatedIdentityConfirmLinkMessage=Bruker med {0} {1} finnes allerede. Hvordan vil du fortsette?
federatedIdentityConfirmReauthenticateMessage=Bekreft at du er {0} for \u00E5 koble din konto med {1}
#federatedIdentityConfirmReauthenticateMessage=Bekreft at du er {0} for \u00E5 koble din konto med {1}
confirmLinkIdpReviewProfile=Se over og bekreft profil
confirmLinkIdpContinue=Legg til eksisterende konto
@ -192,7 +192,6 @@ couldNotObtainTokenMessage=Klarte ikke \u00E5 innhente token fra identitetslever
unexpectedErrorRetrievingTokenMessage=Uventet feil ved henting av token fra identitetsleverand\u00F8r.
unexpectedErrorHandlingResponseMessage=Uventet feil ved h\u00E5ndtering av svar fra identitetsleverand\u00F8r.
identityProviderAuthenticationFailedMessage=Autentisering feilet. Kunne ikke autentisere med identitetsleverand\u00F8r.
identityProviderDifferentUserMessage= Autentisert som {0}, men forventet \u00E5 bli identifisert som {1}
couldNotSendAuthenticationRequestMessage=Kunne ikke sende autentiseringsforesp\u00F8rsel til identitetsleverand\u00F8r.
unexpectedErrorHandlingRequestMessage=Uventet feil ved h\u00E5ndtering av autentiseringsforesp\u00F8rsel til identitetsleverand\u00F8r.
invalidAccessCodeMessage=Ugyldig tilgangskode.

View file

@ -181,7 +181,7 @@ federatedIdentityExistsMessage=Użytkownik z {0} {1} już istnieje. Zaloguj się
confirmLinkIdpTitle=Konto już istnieje
federatedIdentityConfirmLinkMessage=Użytkownik z {0} {1} już istnieje. Co chcesz zrobić?
federatedIdentityConfirmReauthenticateMessage=Uwierzytelnij się jako {0} aby połączyć swoje konto z {1}
federatedIdentityConfirmReauthenticateMessage=Uwierzytelnij się aby połączyć swoje konto z {0}
confirmLinkIdpReviewProfile=Przejrzyj profil
confirmLinkIdpContinue=Dodaj do istniejącego konta
@ -239,7 +239,6 @@ couldNotObtainTokenMessage=Nie można uzyskać tokenu od dostawcy tożsamości.
unexpectedErrorRetrievingTokenMessage=Nieoczekiwany błąd podczas pobierania tokenu od dostawcy tożsamości.
unexpectedErrorHandlingResponseMessage=Nieoczekiwany błąd podczas obsługi odpowiedzi od dostawcy tożsamości.
identityProviderAuthenticationFailedMessage=Uwierzytelnianie nie powiodło się. Nie można uwierzytelnić za pomocą dostawcy tożsamości.
identityProviderDifferentUserMessage=Uwierzytelniony jako {0} a oczekuje się uwierzytelnienia jako {1}
couldNotSendAuthenticationRequestMessage=Nie może wysyłać żądania uwierzytelniania do dostawcy tożsamości.
unexpectedErrorHandlingRequestMessage=Nieoczekiwany błąd podczas obsługi żądania uwierzytelnienia do dostawcy tożsamości.
invalidAccessCodeMessage=Nieprawidłowy kod dostępu.

View file

@ -197,7 +197,7 @@ federatedIdentityExistsMessage=Usu\u00E1rio com {0} {1} j\u00E1 existe. Por favo
confirmLinkIdpTitle=Conta j\u00E1 existente
federatedIdentityConfirmLinkMessage=Usu\u00E1rio com {0} {1} j\u00E1 existe. Como voc\u00EA quer continuar?
federatedIdentityConfirmReauthenticateMessage=Autenticar como {0} para vincular sua conta com {1}
federatedIdentityConfirmReauthenticateMessage=Autenticar para vincular sua conta com {0}
confirmLinkIdpReviewProfile=Revisar informa\u00E7\u00F5es do perfil
confirmLinkIdpContinue=Vincular \u00E0 conta existente
@ -255,7 +255,6 @@ couldNotObtainTokenMessage=N\u00E3o foi poss\u00EDvel obter token do provedor de
unexpectedErrorRetrievingTokenMessage=Erro inesperado ao recuperar token do provedor de identidade.
unexpectedErrorHandlingResponseMessage=Erro inesperado ao manusear resposta do provedor de identidade.
identityProviderAuthenticationFailedMessage=Falha na autentica\u00E7\u00E3o. N\u00E3o foi poss\u00EDvel autenticar com o provedor de identidade.
identityProviderDifferentUserMessage=Autenticado como {0}, mas era esperado ser autenticado como {1}
couldNotSendAuthenticationRequestMessage=N\u00E3o foi poss\u00EDvel enviar solicita\u00E7\u00E3o de autentica\u00E7\u00E3o para o provedor de identidade.
unexpectedErrorHandlingRequestMessage=Erro inesperado ao manusear pedido de autentica\u00E7\u00E3o para provedor de identidade.
invalidAccessCodeMessage=C\u00F3digo de acesso inv\u00E1lido.

View file

@ -143,7 +143,7 @@ federatedIdentityExistsMessage=Пользователь с {0} {1} уже сущ
confirmLinkIdpTitle=Учетная запись уже существует
federatedIdentityConfirmLinkMessage=Пользователь с {0} {1} уже сущестует. Хотите продолжить?
federatedIdentityConfirmReauthenticateMessage=Аутентифицируйтесь как {0} для того, чтобы связать Вашу учетную запись с {1}
federatedIdentityConfirmReauthenticateMessage=Аутентифицируйтесь, чтобы связать Вашу учетную запись с {0}
confirmLinkIdpReviewProfile=Обзор профиля
confirmLinkIdpContinue=Добавить в существующую учетную запись
@ -195,7 +195,6 @@ couldNotObtainTokenMessage=Не удалось получить токен от
unexpectedErrorRetrievingTokenMessage=Непредвиденная ошибка при получении токена от провайдера учетных записей.
unexpectedErrorHandlingResponseMessage=Непредвиденная ошибка при обработке ответа от провайдера учетных записей.
identityProviderAuthenticationFailedMessage=Аутентификация провалена. Невозможно аутентифицировать с поставщиком учетных записей.
identityProviderDifferentUserMessage=Аутентифицирован как {0}, но ожидается, что будет аутентифицирован как {1}
couldNotSendAuthenticationRequestMessage=Не получается выполнить запрос аутентификации к поставщику учетных записей.
unexpectedErrorHandlingRequestMessage=Непредвиденная ошибка при обработке запроса аутентификации поставщика учетных записей.
invalidAccessCodeMessage=Неверный код доступа.

View file

@ -166,7 +166,7 @@ federatedIdentityExistsMessage=Používateľ s {0} {1} už existuje. Ak chcete p
confirmLinkIdpTitle=Účet už existuje
federatedIdentityConfirmLinkMessage=Používateľ s {0} {1} už existuje. Ako chcete pokračovať?
federatedIdentityConfirmReauthenticateMessage=Overiť ako {0} prepojiť váš účet s {1}
federatedIdentityConfirmReauthenticateMessage=Overiť prepojiť váš účet s {0}
confirmLinkIdpReviewProfile=Skontrolujte profil
confirmLinkIdpContinue=Pridať do existujúceho účtu
@ -219,7 +219,6 @@ couldNotObtainTokenMessage=Nemožno získať token od poskytovateľa identity.
unexpectedErrorRetrievingTokenMessage=Neočakávaná chyba pri získavaní tokenu od poskytovateľa identity.
unexpectedErrorHandlingResponseMessage=Neočakávaná chyba pri spracovaní odpovede od poskytovateľa identity.
identityProviderAuthenticationFailedMessage=Overenie zlyhalo. Nepodarilo sa autentizovať s poskytovateľom identity.
identityProviderDifferentUserMessage=Autentifikovaný ako {0}, ale očakáva sa, že bude autentizovaný ako {1}
couldNotSendAuthenticationRequestMessage=Nemožno odoslať žiadosť o autentifikáciu poskytovateľovi identity.
unexpectedErrorHandlingRequestMessage=Neočakávaná chyba pri spracovaní žiadosti o autentifikáciu poskytovateľovi identity.
invalidAccessCodeMessage=Neplatný prístupový kód.

View file

@ -139,7 +139,7 @@ federatedIdentityExistsMessage=Användare med {0} {1} finns redan. Vänligen log
confirmLinkIdpTitle=Kontot finns redan
federatedIdentityConfirmLinkMessage=Användare med {0} {1} finns redan, Hur vill du forsätta?
federatedIdentityConfirmReauthenticateMessage=Autentisera som {0} för att länka ditt konto med {1}
federatedIdentityConfirmReauthenticateMessage=Autentisera för att länka ditt konto med {0}
confirmLinkIdpReviewProfile=Granska profil
confirmLinkIdpContinue=Lägg till i existerande konto
@ -191,7 +191,6 @@ couldNotObtainTokenMessage=Kunde inte motta element från identitetsleverantör.
unexpectedErrorRetrievingTokenMessage=Oväntat fel när element hämtas från identitetsleverantör.
unexpectedErrorHandlingResponseMessage=Oväntat fel under hantering av svar från från identitetsleverantör.
identityProviderAuthenticationFailedMessage=Autentiseringen misslyckades. Kunde inte autentisera med identitetsleverantör.
identityProviderDifferentUserMessage=Autentiserad som {0}, men väntades att vara autentiserad som {1}
couldNotSendAuthenticationRequestMessage=Kunde inte skicka autentiseringsförfrågan till identitetsleverantör.
unexpectedErrorHandlingRequestMessage=Oväntat fel under hantering av autentiseringsförfrågan till identitetsleverantör.
invalidAccessCodeMessage=Ogiltig tillträdeskod.

View file

@ -182,7 +182,7 @@ federatedIdentityExistsMessage={0} {1} kullan\u0131c\u0131 zaten var. Hesab\u013
confirmLinkIdpTitle=Bu Hesap Zaten Mevcut
federatedIdentityConfirmLinkMessage={0} {1} kullan\u0131c\u0131 zaten var. Nas\u0131l devam etmek istersin?
federatedIdentityConfirmReauthenticateMessage=Hesab\u0131n\u0131z\u0131 {1} ile ba\u011Flamak i\u00E7in {0} olarak do\u011Frulay\u0131n
#federatedIdentityConfirmReauthenticateMessage=Hesab\u0131n\u0131z\u0131 {1} ile ba\u011Flamak i\u00E7in {0} olarak do\u011Frulay\u0131n
confirmLinkIdpReviewProfile=Profili g\u00F6zden ge\u00E7ir
confirmLinkIdpContinue=Mevcut hesaba ekle
@ -240,7 +240,6 @@ couldNotObtainTokenMessage=Kimlik sa\u011Flay\u0131c\u0131dan token al\u0131nama
unexpectedErrorRetrievingTokenMessage=Kimlik sa\u011Flay\u0131c\u0131dan token al\u0131rken beklenmeyen bir hata olu\u015Ftu.
unexpectedErrorHandlingResponseMessage=Kimlik sa\u011Flay\u0131c\u0131dan yan\u0131t al\u0131n\u0131rken beklenmeyen bir hata olu\u015Ftu.
identityProviderAuthenticationFailedMessage=Kimlik do\u011Frulama ba\u015Far\u0131s\u0131z oldu. Kimlik sa\u011Flay\u0131c\u0131yla kimlik do\u011Frulamas\u0131 yap\u0131lamad\u0131.
identityProviderDifferentUserMessage={0} olarak do\u011Fruland\u0131, ancak {1} olarak do\u011Frulanmas\u0131 bekleniyordu
couldNotSendAuthenticationRequestMessage=Kimlik sa\u011Flay\u0131c\u0131ya kimlik do\u011Frulama iste\u011Fi g\u00F6nderilemedi.
unexpectedErrorHandlingRequestMessage=Kimlik sa\u011Flay\u0131c\u0131ya kimlik do\u011Frulama iste\u011Fi i\u015Flenirken beklenmeyen bir hata olu\u015Ftu.
invalidAccessCodeMessage=Ge\u00E7ersiz giri\u015F kodu.

View file

@ -143,7 +143,7 @@ federatedIdentityExistsMessage=用户 {0} {1} 已存在. 请登录账户管理
confirmLinkIdpTitle=账户已存在
federatedIdentityConfirmLinkMessage=用户{0} {1} 已存在. 怎么继续?
federatedIdentityConfirmReauthenticateMessage=以 {0} 登录来将 {1} 连接到您的账户
#federatedIdentityConfirmReauthenticateMessage=以 {0} 登录来将 {1} 连接到您的账户
confirmLinkIdpReviewProfile=审查您的信息
confirmLinkIdpContinue=添加到已知账户
@ -194,7 +194,6 @@ couldNotObtainTokenMessage=未从身份提供者获得token
unexpectedErrorRetrievingTokenMessage=从身份提供者获得Token时遇到未知错误
unexpectedErrorHandlingResponseMessage=从身份提供者获得回复时遇到未知错误
identityProviderAuthenticationFailedMessage=认证失败,无法通过身份提供者认证
identityProviderDifferentUserMessage=认证为 {0}, 但期望认证为 {1}
couldNotSendAuthenticationRequestMessage=无法向身份提供方发送认证请求
unexpectedErrorHandlingRequestMessage=在处理发向认证提供方的请求时,出现未知错误。
invalidAccessCodeMessage=无效的验证码

View file

@ -50,7 +50,7 @@
</#if>
</div>
<#elseif section = "info" >
<#if realm.password && realm.registrationAllowed && !usernameEditDisabled??>
<#if realm.password && realm.registrationAllowed && !registrationDisabled??>
<div id="kc-registration">
<span>${msg("noAccount")} <a tabindex="6" href="${url.registrationUrl}">${msg("doRegister")}</a></span>
</div>

View file

@ -62,7 +62,7 @@
</#if>
</div>
<#elseif section = "info" >
<#if realm.password && realm.registrationAllowed && !usernameEditDisabled??>
<#if realm.password && realm.registrationAllowed && !registrationDisabled??>
<div id="kc-registration">
<span>${msg("noAccount")} <a tabindex="6" href="${url.registrationUrl}">${msg("doRegister")}</a></span>
</div>

View file

@ -197,7 +197,8 @@ federatedIdentityExistsMessage=User with {0} {1} already exists. Please login to
confirmLinkIdpTitle=Account already exists
federatedIdentityConfirmLinkMessage=User with {0} {1} already exists. How do you want to continue?
federatedIdentityConfirmReauthenticateMessage=Authenticate as {0} to link your account with {1}
federatedIdentityConfirmReauthenticateMessage=Authenticate to link your account with {0}
nestedFirstBrokerFlowMessage=The {0} user {1} is not linked to any known user.
confirmLinkIdpReviewProfile=Review profile
confirmLinkIdpContinue=Add to existing account
@ -255,7 +256,6 @@ couldNotObtainTokenMessage=Could not obtain token from identity provider.
unexpectedErrorRetrievingTokenMessage=Unexpected error when retrieving token from identity provider.
unexpectedErrorHandlingResponseMessage=Unexpected error when handling response from identity provider.
identityProviderAuthenticationFailedMessage=Authentication failed. Could not authenticate with identity provider.
identityProviderDifferentUserMessage=Authenticated as {0}, but expected to be authenticated as {1}
couldNotSendAuthenticationRequestMessage=Could not send authentication request to identity provider.
unexpectedErrorHandlingRequestMessage=Unexpected error when handling authentication request to identity provider.
invalidAccessCodeMessage=Invalid access code.