KEYCLOAK-10854: App-initiated actions Phase I
This commit is contained in:
parent
6c79bdee41
commit
bc818367a1
25 changed files with 142 additions and 101 deletions
|
@ -21,5 +21,5 @@ package org.keycloak.authentication;
|
|||
* @author Stan Silvert
|
||||
*/
|
||||
public enum InitiatedActionSupport {
|
||||
SUPPORTED, NOT_SUPPORTED, CONSENT_REQUIRED
|
||||
SUPPORTED, NOT_SUPPORTED
|
||||
}
|
||||
|
|
|
@ -41,7 +41,8 @@ public interface RequiredActionContext {
|
|||
CHALLENGE,
|
||||
SUCCESS,
|
||||
IGNORE,
|
||||
FAILURE
|
||||
FAILURE,
|
||||
CANCELED_AIA
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,5 +139,11 @@ public interface RequiredActionContext {
|
|||
*
|
||||
*/
|
||||
void ignore();
|
||||
|
||||
/**
|
||||
* Mark application-initiated action as canceled by the user.
|
||||
*
|
||||
*/
|
||||
void cancelAIA();
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
|
||||
package org.keycloak.authentication;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||
|
||||
/**
|
||||
* RequiredAction provider. Required actions are one-time actions that a user must perform before they are logged in.
|
||||
|
@ -36,6 +38,18 @@ public interface RequiredActionProvider extends Provider {
|
|||
return InitiatedActionSupport.NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to let the action know that an application-initiated action
|
||||
* was canceled.
|
||||
*
|
||||
* @param session The Keycloak session.
|
||||
* @param authSession The authentication session.
|
||||
*
|
||||
*/
|
||||
default void initiatedActionCanceled(KeycloakSession session, AuthenticationSessionModel authSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called every time a user authenticates. This checks to see if this required action should be triggered.
|
||||
* The implementation of this method is responsible for setting the required action on the UserModel.
|
||||
|
|
|
@ -45,7 +45,6 @@ import org.keycloak.migration.migrators.MigrateTo4_0_0;
|
|||
import org.keycloak.migration.migrators.MigrateTo4_2_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo4_6_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo6_0_0;
|
||||
import org.keycloak.migration.migrators.MigrateTo7_0_0;
|
||||
import org.keycloak.migration.migrators.Migration;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -82,8 +81,7 @@ public class MigrationModelManager {
|
|||
new MigrateTo4_0_0(),
|
||||
new MigrateTo4_2_0(),
|
||||
new MigrateTo4_6_0(),
|
||||
new MigrateTo6_0_0(),
|
||||
new MigrateTo7_0_0()
|
||||
new MigrateTo6_0_0()
|
||||
};
|
||||
|
||||
public static void migrate(KeycloakSession session) {
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2019 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.migration.migrators;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.migration.ModelVersion;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
||||
/**
|
||||
* Implements the migration necessary for version 6.0.0.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class MigrateTo7_0_0 implements Migration {
|
||||
|
||||
public static final ModelVersion VERSION = new ModelVersion("7.0.0");
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MigrateTo7_0_0.class);
|
||||
|
||||
@Override
|
||||
public ModelVersion getVersion() {
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrate(KeycloakSession session) {
|
||||
session.realms().getRealms().stream().forEach(r -> {
|
||||
migrateRealm(session, r, false);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrateImport(KeycloakSession session, RealmModel realm, RealmRepresentation rep, boolean skipUserDependent) {
|
||||
migrateRealm(session, realm, true);
|
||||
}
|
||||
|
||||
protected void migrateRealm(KeycloakSession session, RealmModel realm, boolean jsn) {
|
||||
ClientModel account = realm.getClientByClientId("account");
|
||||
if (account != null) {
|
||||
RoleModel role = account.addRole(AccountRoles.INITIATE_ACTION);
|
||||
role.setDescription("${role_" + AccountRoles.INITIATE_ACTION + "}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,6 @@ public interface AccountRoles {
|
|||
String INITIATE_ACTION = "initiate-action";
|
||||
String MANAGE_ACCOUNT_LINKS = "manage-account-links";
|
||||
|
||||
String[] ALL = {VIEW_PROFILE, MANAGE_ACCOUNT, INITIATE_ACTION};
|
||||
String[] ALL = {VIEW_PROFILE, MANAGE_ACCOUNT};
|
||||
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ public final class Constants {
|
|||
public static final String KEY = "key";
|
||||
public static final String KC_ACTION = "kc_action";
|
||||
public static final String IS_AIA_REQUEST = "IS_AIA_REQUEST";
|
||||
public static final String AIA_SILENT_CANCEL = "silent_cancel";
|
||||
|
||||
public static final String SKIP_LINK = "skipLink";
|
||||
public static final String TEMPLATE_ATTR_ACTION_URI = "actionUri";
|
||||
|
|
|
@ -43,6 +43,14 @@ public interface LoginProtocol extends Provider {
|
|||
* Login cancelled by the user
|
||||
*/
|
||||
CANCELLED_BY_USER,
|
||||
/**
|
||||
* Applications-initiated action was canceled by the user
|
||||
*/
|
||||
CANCELLED_AIA,
|
||||
/**
|
||||
* Applications-initiated action was canceled by the user. Do not send error.
|
||||
*/
|
||||
CANCELLED_AIA_SILENT,
|
||||
/**
|
||||
* Consent denied by the user
|
||||
*/
|
||||
|
|
|
@ -136,6 +136,11 @@ public class RequiredActionContextResult implements RequiredActionContext {
|
|||
public void ignore() {
|
||||
status = Status.IGNORE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelAIA() {
|
||||
status = Status.CANCELED_AIA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getActionUrl(String code) {
|
||||
|
|
|
@ -269,9 +269,18 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
|||
|
||||
String redirect = authSession.getRedirectUri();
|
||||
String state = authSession.getClientNote(OIDCLoginProtocol.STATE_PARAM);
|
||||
OIDCRedirectUriBuilder redirectUri = OIDCRedirectUriBuilder.fromUri(redirect, responseMode).addParam(OAuth2Constants.ERROR, translateError(error));
|
||||
if (state != null)
|
||||
OIDCRedirectUriBuilder redirectUri = OIDCRedirectUriBuilder.fromUri(redirect, responseMode);
|
||||
|
||||
if (error != Error.CANCELLED_AIA_SILENT) {
|
||||
redirectUri.addParam(OAuth2Constants.ERROR, translateError(error));
|
||||
}
|
||||
if (error == Error.CANCELLED_AIA) {
|
||||
redirectUri.addParam(OAuth2Constants.ERROR_DESCRIPTION, "User cancelled aplication-initiated action.");
|
||||
}
|
||||
if (state != null) {
|
||||
redirectUri.addParam(OAuth2Constants.STATE, state);
|
||||
}
|
||||
|
||||
new AuthenticationSessionManager(session).removeAuthenticationSession(realm, authSession, true);
|
||||
return redirectUri.build();
|
||||
}
|
||||
|
@ -279,6 +288,8 @@ public class OIDCLoginProtocol implements LoginProtocol {
|
|||
private String translateError(Error error) {
|
||||
switch (error) {
|
||||
case CANCELLED_BY_USER:
|
||||
case CANCELLED_AIA:
|
||||
return OAuthErrorException.INTERACTION_REQUIRED;
|
||||
case CONSENT_DENIED:
|
||||
return OAuthErrorException.ACCESS_DENIED;
|
||||
case PASSIVE_INTERACTION_REQUIRED:
|
||||
|
|
|
@ -225,6 +225,7 @@ public class SamlProtocol implements LoginProtocol {
|
|||
private JBossSAMLURIConstants translateErrorToSAMLStatus(Error error) {
|
||||
switch (error) {
|
||||
case CANCELLED_BY_USER:
|
||||
case CANCELLED_AIA:
|
||||
case CONSENT_DENIED:
|
||||
return JBossSAMLURIConstants.STATUS_REQUEST_DENIED;
|
||||
case PASSIVE_INTERACTION_REQUIRED:
|
||||
|
|
|
@ -45,7 +45,6 @@ import org.keycloak.events.Errors;
|
|||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.forms.login.LoginFormsProvider;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.ActionTokenKeyModel;
|
||||
import org.keycloak.models.ActionTokenStoreProvider;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
|
@ -66,6 +65,7 @@ import org.keycloak.protocol.LoginProtocol;
|
|||
import org.keycloak.protocol.LoginProtocol.Error;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.services.ForbiddenException;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
import org.keycloak.services.Urls;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
|
@ -96,6 +96,7 @@ import java.util.Objects;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
|
||||
import static org.keycloak.protocol.oidc.endpoints.AuthorizationEndpoint.LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX;
|
||||
|
||||
|
@ -132,6 +133,7 @@ public class AuthenticationManager {
|
|||
private static final TokenTypeCheck VALIDATE_IDENTITY_COOKIE = new TokenTypeCheck(TokenUtil.TOKEN_TYPE_KEYCLOAK_ID);
|
||||
private static final String AIA_REQUEST = LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + Constants.KC_ACTION;
|
||||
public static final String IS_AIA_REQUEST = LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + Constants.IS_AIA_REQUEST;
|
||||
public static final String IS_SILENT_CANCEL = LOGIN_SESSION_NOTE_ADDITIONAL_REQ_PARAMS_PREFIX + Constants.AIA_SILENT_CANCEL;
|
||||
|
||||
public static boolean isSessionValid(RealmModel realm, UserSessionModel userSession) {
|
||||
if (userSession == null) {
|
||||
|
@ -1144,6 +1146,11 @@ public class AuthenticationManager {
|
|||
public void ignore() {
|
||||
throw new RuntimeException("Not allowed to call ignore() within evaluateTriggers()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelAIA() {
|
||||
throw new RuntimeException("Not allowed to call cancelAIA() within evaluateTriggers()");
|
||||
}
|
||||
};
|
||||
|
||||
evaluateApplicationInitiatedActionTrigger(session, provider, model, authSession);
|
||||
|
@ -1166,11 +1173,10 @@ public class AuthenticationManager {
|
|||
// make sure you are evaluating the action that was requested
|
||||
if (!aia.equalsIgnoreCase(model.getProviderId())) return;
|
||||
|
||||
if (session.getContext().getClient().getRole(AccountRoles.INITIATE_ACTION) == null) {
|
||||
logger.error("Client must have initiate-action role to perform application-initiated action.");
|
||||
return;
|
||||
if (session.getContext().getClient().getRole(AccountRoles.MANAGE_ACCOUNT) == null) {
|
||||
throw new ForbiddenException("Client must have manage-account role to perform application-initiated actions.");
|
||||
}
|
||||
|
||||
|
||||
authSession.addRequiredAction(model.getProviderId());
|
||||
authSession.removeClientNote(AIA_REQUEST); // keep this from being executed twice
|
||||
authSession.setClientNote(IS_AIA_REQUEST, "true");
|
||||
|
|
|
@ -102,6 +102,7 @@ import java.util.Map;
|
|||
|
||||
import static org.keycloak.authentication.actiontoken.DefaultActionToken.ACTION_TOKEN_BASIC_CHECKS;
|
||||
import static org.keycloak.services.managers.AuthenticationManager.IS_AIA_REQUEST;
|
||||
import static org.keycloak.services.managers.AuthenticationManager.IS_SILENT_CANCEL;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
|
@ -993,7 +994,8 @@ public class LoginActionsService {
|
|||
Response response;
|
||||
|
||||
if (isCancelAppInitiatedAction(authSession, context)) {
|
||||
context.failure();
|
||||
provider.initiatedActionCanceled(session, authSession);
|
||||
context.cancelAIA();
|
||||
} else {
|
||||
provider.processAction(context);
|
||||
}
|
||||
|
@ -1014,15 +1016,11 @@ public class LoginActionsService {
|
|||
} else if (context.getStatus() == RequiredActionContext.Status.CHALLENGE) {
|
||||
response = context.getChallenge();
|
||||
} else if (context.getStatus() == RequiredActionContext.Status.FAILURE) {
|
||||
LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, authSession.getProtocol());
|
||||
protocol.setRealm(context.getRealm())
|
||||
.setHttpHeaders(context.getHttpRequest().getHttpHeaders())
|
||||
.setUriInfo(context.getUriInfo())
|
||||
.setEventBuilder(event);
|
||||
|
||||
event.detail(Details.CUSTOM_REQUIRED_ACTION, action);
|
||||
response = protocol.sendError(authSession, Error.CONSENT_DENIED);
|
||||
event.error(Errors.REJECTED_BY_USER);
|
||||
response = interruptionResponse(context, authSession, action, Error.CONSENT_DENIED);
|
||||
} else if (isSilentAIACancel(authSession, context)) {
|
||||
response = interruptionResponse(context, authSession, action, Error.CANCELLED_AIA_SILENT);
|
||||
} else if (context.getStatus() == RequiredActionContext.Status.CANCELED_AIA) {
|
||||
response = interruptionResponse(context, authSession, action, Error.CANCELLED_AIA);
|
||||
} else {
|
||||
throw new RuntimeException("Unreachable");
|
||||
}
|
||||
|
@ -1030,6 +1028,19 @@ public class LoginActionsService {
|
|||
return BrowserHistoryHelper.getInstance().saveResponseAndRedirect(session, authSession, response, true, request);
|
||||
}
|
||||
|
||||
private Response interruptionResponse(RequiredActionContextResult context, AuthenticationSessionModel authSession, String action, Error error) {
|
||||
LoginProtocol protocol = context.getSession().getProvider(LoginProtocol.class, authSession.getProtocol());
|
||||
protocol.setRealm(context.getRealm())
|
||||
.setHttpHeaders(context.getHttpRequest().getHttpHeaders())
|
||||
.setUriInfo(context.getUriInfo())
|
||||
.setEventBuilder(event);
|
||||
|
||||
event.detail(Details.CUSTOM_REQUIRED_ACTION, action);
|
||||
|
||||
event.error(Errors.REJECTED_BY_USER);
|
||||
return protocol.sendError(authSession, error);
|
||||
}
|
||||
|
||||
private boolean isCancelAppInitiatedAction(AuthenticationSessionModel authSession, RequiredActionContextResult context) {
|
||||
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
|
||||
|
||||
|
@ -1038,5 +1049,13 @@ public class LoginActionsService {
|
|||
|
||||
return isAIARequest && userRequestedCancelAIA;
|
||||
}
|
||||
|
||||
private boolean isSilentAIACancel(AuthenticationSessionModel authSession, RequiredActionContextResult context) {
|
||||
String silentCancel = authSession.getClientNote(IS_SILENT_CANCEL);
|
||||
boolean isSilentCancel = "true".equalsIgnoreCase(silentCancel);
|
||||
boolean isAIACancel = isCancelAppInitiatedAction(authSession, context);
|
||||
|
||||
return isSilentCancel && isAIACancel;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,8 +50,13 @@ public abstract class AbstractAppInitiatedActionTest extends AbstractTestRealmKe
|
|||
}
|
||||
|
||||
protected void doAIA() {
|
||||
doAIA(false);
|
||||
}
|
||||
|
||||
protected void doAIA(boolean silentCancel) {
|
||||
UriBuilder builder = OIDCLoginProtocolService.authUrl(authServerPage.createUriBuilder());
|
||||
String uri = builder.queryParam("kc_action", this.aiaAction)
|
||||
.queryParam("silent_cancel", Boolean.toString(silentCancel))
|
||||
.queryParam("response_type", "code")
|
||||
.queryParam("client_id", "test-app")
|
||||
.queryParam("scope", "openid")
|
||||
|
@ -64,4 +69,16 @@ public abstract class AbstractAppInitiatedActionTest extends AbstractTestRealmKe
|
|||
protected void assertRedirectSuccess() {
|
||||
Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
|
||||
}
|
||||
|
||||
protected void assertCancelMessage() {
|
||||
String url = this.driver.getCurrentUrl();
|
||||
Assert.assertTrue("Expected 'error=interaction_required' in url", url.contains("error=interaction_required"));
|
||||
Assert.assertTrue("Expected 'error_description=User+cancelled+aplication-initiated+action.' in url", url.contains("error_description=User+cancelled+aplication-initiated+action."));
|
||||
}
|
||||
|
||||
protected void assertSilentCancelMessage() {
|
||||
String url = this.driver.getCurrentUrl();
|
||||
Assert.assertFalse("Expected no 'error=' in url", url.contains("error="));
|
||||
Assert.assertFalse("Expected no 'error_description=' in url", url.contains("error_description="));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public class AppInitiatedActionCancelTest extends AbstractAppInitiatedActionTest
|
|||
updateProfilePage.assertCurrent();
|
||||
updateProfilePage.cancel();
|
||||
assertRedirectSuccess();
|
||||
assertCancelMessage();
|
||||
|
||||
appPage.logout();
|
||||
|
||||
|
@ -58,4 +59,14 @@ public class AppInitiatedActionCancelTest extends AbstractAppInitiatedActionTest
|
|||
loginPage.login("test-user@localhost", "password");
|
||||
updateProfilePage.assertCurrent();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void silentCancelUpdateProfile() {
|
||||
doAIA(true);
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
updateProfilePage.assertCurrent();
|
||||
updateProfilePage.cancel();
|
||||
assertRedirectSuccess();
|
||||
assertSilentCancelMessage();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,7 @@ public class AppInitiatedActionResetPasswordTest extends AbstractAppInitiatedAct
|
|||
changePasswordPage.cancel();
|
||||
|
||||
assertRedirectSuccess();
|
||||
assertCancelMessage();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
package org.keycloak.testsuite.actions;
|
||||
|
||||
import java.util.List;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.testsuite.pages.ErrorPage;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -28,6 +30,9 @@ import org.keycloak.representations.idm.RoleRepresentation;
|
|||
*/
|
||||
public class AppInitiatedActionRoleTest extends AbstractAppInitiatedActionTest {
|
||||
|
||||
@Page
|
||||
protected ErrorPage errorPage;
|
||||
|
||||
public AppInitiatedActionRoleTest() {
|
||||
super("update_profile");
|
||||
}
|
||||
|
@ -36,15 +41,15 @@ public class AppInitiatedActionRoleTest extends AbstractAppInitiatedActionTest {
|
|||
public void configureTestRealm(RealmRepresentation testRealm) {
|
||||
List<RoleRepresentation> roleList = testRealm.getRoles().getClient().get("test-app");
|
||||
|
||||
RoleRepresentation initiateActionRole = null;
|
||||
RoleRepresentation manageAccountRole = null;
|
||||
for (RoleRepresentation role : roleList) {
|
||||
if (role.getName().equals(AccountRoles.INITIATE_ACTION)) {
|
||||
initiateActionRole = role;
|
||||
if (role.getName().equals(AccountRoles.MANAGE_ACCOUNT)) {
|
||||
manageAccountRole = role;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
roleList.remove(initiateActionRole);
|
||||
roleList.remove(manageAccountRole);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -52,6 +57,6 @@ public class AppInitiatedActionRoleTest extends AbstractAppInitiatedActionTest {
|
|||
loginPage.open();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
doAIA();
|
||||
assertRedirectSuccess(); // update profile screen does not appear
|
||||
errorPage.assertCurrent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ public class AppInitiatedActionTotpSetupTest extends AbstractAppInitiatedActionT
|
|||
totpPage.cancel();
|
||||
|
||||
assertRedirectSuccess();
|
||||
assertCancelMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -133,6 +133,7 @@ public class AppInitiatedActionUpdateProfileTest extends AbstractAppInitiatedAct
|
|||
updateProfilePage.cancel();
|
||||
|
||||
assertRedirectSuccess();
|
||||
assertCancelMessage();
|
||||
|
||||
// assert nothing was updated in persistent store
|
||||
UserRepresentation user = ActionUtil.findUserWithAdminClient(adminClient, "test-user@localhost");
|
||||
|
|
|
@ -123,7 +123,7 @@ public class AddUserTest extends AbstractKeycloakTest {
|
|||
}
|
||||
|
||||
List<RoleRepresentation> accountRoles = userResource.roles().clientLevel(accountId).listAll();
|
||||
assertRoles(accountRoles, "initiate-action", "view-profile", "manage-account");
|
||||
assertRoles(accountRoles, "view-profile", "manage-account");
|
||||
} finally {
|
||||
userResource.remove();
|
||||
}
|
||||
|
|
|
@ -438,7 +438,7 @@ public class ClientTest extends AbstractAdminTest {
|
|||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listAll(), AccountRoles.VIEW_PROFILE);
|
||||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listEffective(), AccountRoles.VIEW_PROFILE);
|
||||
|
||||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listAvailable(), AccountRoles.INITIATE_ACTION, AccountRoles.MANAGE_ACCOUNT, AccountRoles.MANAGE_ACCOUNT_LINKS);
|
||||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listAvailable(), AccountRoles.MANAGE_ACCOUNT, AccountRoles.MANAGE_ACCOUNT_LINKS);
|
||||
|
||||
Assert.assertNames(scopesResource.getAll().getRealmMappings(), "role1");
|
||||
Assert.assertNames(scopesResource.getAll().getClientMappings().get(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID).getMappings(), AccountRoles.VIEW_PROFILE);
|
||||
|
@ -453,7 +453,7 @@ public class ClientTest extends AbstractAdminTest {
|
|||
Assert.assertNames(scopesResource.realmLevel().listEffective());
|
||||
Assert.assertNames(scopesResource.realmLevel().listAvailable(), "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION, "role1", "role2");
|
||||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listAll());
|
||||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listAvailable(), AccountRoles.INITIATE_ACTION, AccountRoles.VIEW_PROFILE, AccountRoles.MANAGE_ACCOUNT, AccountRoles.MANAGE_ACCOUNT_LINKS);
|
||||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listAvailable(), AccountRoles.VIEW_PROFILE, AccountRoles.MANAGE_ACCOUNT, AccountRoles.MANAGE_ACCOUNT_LINKS);
|
||||
Assert.assertNames(scopesResource.clientLevel(accountMgmtId).listEffective());
|
||||
}
|
||||
|
||||
|
|
|
@ -1409,7 +1409,7 @@ public class UserTest extends AbstractAdminTest {
|
|||
assertNames(all.getRealmMappings(), "realm-role", "realm-composite", "user", "offline_access", Constants.AUTHZ_UMA_AUTHORIZATION);
|
||||
assertEquals(2, all.getClientMappings().size());
|
||||
assertNames(all.getClientMappings().get("myclient").getMappings(), "client-role", "client-composite");
|
||||
assertNames(all.getClientMappings().get("account").getMappings(), "initiate-action", "manage-account", "view-profile");
|
||||
assertNames(all.getClientMappings().get("account").getMappings(), "manage-account", "view-profile");
|
||||
|
||||
// Remove realm role
|
||||
RoleRepresentation realmRoleRep = realm.roles().get("realm-role").toRepresentation();
|
||||
|
|
|
@ -129,7 +129,7 @@ public class KcAdmSessionTest extends AbstractAdmCliTest {
|
|||
|
||||
realmMappings = StreamSupport.stream(clientRoles.get("account").get("mappings").spliterator(), false)
|
||||
.map(o -> o.get("name").asText()).sorted().collect(Collectors.toList());
|
||||
Assert.assertEquals(Arrays.asList("initiate-action", "manage-account", "view-profile"), realmMappings);
|
||||
Assert.assertEquals(Arrays.asList("manage-account", "view-profile"), realmMappings);
|
||||
|
||||
realmMappings = StreamSupport.stream(clientRoles.get("realm-management").get("mappings").spliterator(), false)
|
||||
.map(o -> o.get("name").asText()).sorted().collect(Collectors.toList());
|
||||
|
|
|
@ -416,9 +416,9 @@
|
|||
],
|
||||
"client" : {
|
||||
"test-app" : [
|
||||
{
|
||||
"name" : "initiate-action",
|
||||
"description": "Allow application-initiated actions"
|
||||
{
|
||||
"name": "manage-account",
|
||||
"description": "Allows application-initiated actions."
|
||||
},
|
||||
{
|
||||
"name": "customer-user",
|
||||
|
|
|
@ -79,7 +79,6 @@ role_manage-clients=Manage clients
|
|||
role_manage-events=Manage events
|
||||
role_view-profile=View profile
|
||||
role_manage-account=Manage account
|
||||
role_initiate-action=Initiate action
|
||||
role_manage-account-links=Manage account links
|
||||
role_read-token=Read token
|
||||
role_offline-access=Offline access
|
||||
|
|
Loading…
Reference in a new issue