diff --git a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
index 5d2eab5..0f3a80b 100755
--- a/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AbstractSecuredLocalService.java
@@ -21,9 +21,11 @@ import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.AbstractOAuthClient;
import org.keycloak.OAuth2Constants;
+import org.keycloak.OAuthErrorException;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.util.Base64Url;
import org.keycloak.common.util.KeycloakUriBuilder;
+import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -32,6 +34,7 @@ import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.services.ForbiddenException;
import org.keycloak.services.managers.Auth;
import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.services.messages.Messages;
import org.keycloak.services.util.CookieHelper;
import org.keycloak.util.TokenUtil;
@@ -89,8 +92,14 @@ public abstract class AbstractSecuredLocalService {
@Context HttpHeaders headers) {
try {
if (error != null) {
- logger.debug("error from oauth");
- throw new ForbiddenException("error");
+ if (OAuthErrorException.ACCESS_DENIED.equals(error)) {
+ // cased by CANCELLED_BY_USER or CONSENT_DENIED
+ session.getContext().setClient(client);
+ return session.getProvider(LoginFormsProvider.class).setError(Messages.NO_ACCESS).createErrorPage(Response.Status.FORBIDDEN);
+ } else {
+ logger.debug("error from oauth");
+ throw new ForbiddenException("error");
+ }
}
if (path != null && !getValidPaths().contains(path)) {
throw new BadRequestException("Invalid path");
@@ -111,7 +120,6 @@ public abstract class AbstractSecuredLocalService {
logger.debug("state not specified");
throw new BadRequestException("state not specified");
}
-
KeycloakUriBuilder redirect = KeycloakUriBuilder.fromUri(getBaseRedirectUri());
if (path != null) {
redirect.path(path);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ConsentsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ConsentsTest.java
index 8407610..1cb3ce6 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ConsentsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ConsentsTest.java
@@ -18,8 +18,10 @@
package org.keycloak.testsuite.admin;
import org.jboss.arquillian.graphene.page.Page;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
@@ -31,13 +33,16 @@ import org.keycloak.representations.idm.UserSessionRepresentation;
import org.keycloak.testsuite.AbstractKeycloakTest;
import org.keycloak.testsuite.Assert;
import org.keycloak.testsuite.pages.ConsentPage;
+import org.keycloak.testsuite.pages.ErrorPage;
import org.keycloak.testsuite.pages.LoginPage;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import static org.junit.Assert.assertEquals;
import static org.keycloak.testsuite.admin.ApiUtil.createUserWithAdminClient;
+import static org.keycloak.testsuite.admin.ApiUtil.findClientByClientId;
import static org.keycloak.testsuite.admin.ApiUtil.resetUserPassword;
/**
@@ -149,6 +154,9 @@ public class ConsentsTest extends AbstractKeycloakTest {
@Page
protected ConsentPage consentPage;
+ @Page
+ protected ErrorPage errorPage;
+
@Override
public void addTestRealms(List<RealmRepresentation> testRealms) {
RealmRepresentation providerRealm = createProviderRealm();
@@ -223,6 +231,12 @@ public class ConsentsTest extends AbstractKeycloakTest {
}
}
+ @After
+ public void cleanUser() {
+ String userId = adminClient.realm(providerRealmName()).users().search(getUserLogin()).get(0).getId();
+ adminClient.realm(providerRealmName()).users().delete(userId);
+ }
+
@Test
public void testConsents() {
driver.navigate().to(getAccountUrl(consumerRealmName()));
@@ -295,6 +309,41 @@ public class ConsentsTest extends AbstractKeycloakTest {
Assert.assertEquals("There should be no active session", 0, sessions.size());
}
+ @Test
+ public void testConsentCancel() {
+ // setup account client to require consent
+ RealmResource providerRealm = adminClient.realm(providerRealmName());
+ ClientResource accountClient = findClientByClientId(providerRealm, "account");
+
+ ClientRepresentation clientRepresentation = accountClient.toRepresentation();
+ clientRepresentation.setConsentRequired(true);
+ accountClient.update(clientRepresentation);
+
+ // setup correct realm
+ accountPage.setAuthRealm(providerRealmName());
+
+ // navigate to account console and login
+ accountPage.navigateTo();
+ loginPage.form().login(getUserLogin(), getUserPassword());
+
+ consentPage.assertCurrent();
+
+ consentPage.cancel();
+
+ // check an error page after cancelling the consent
+ errorPage.assertCurrent();
+ assertEquals("No access", errorPage.getError());
+
+ // follow the link "back to application"
+ errorPage.clickBackToApplication();
+
+ loginPage.form().login(getUserLogin(), getUserPassword());
+ consentPage.confirm();
+
+ // successful login
+ accountPage.assertCurrent();
+ }
+
private String getAccountUrl(String realmName) {
return getAuthRoot() + "/auth/realms/" + realmName + "/account";
}
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/actions/TermsAndConditionsTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/actions/TermsAndConditionsTest.java
index f9ee517..0795e6f 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/actions/TermsAndConditionsTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/authentication/actions/TermsAndConditionsTest.java
@@ -28,10 +28,13 @@ import org.keycloak.testsuite.auth.page.login.Registration;
import org.keycloak.testsuite.auth.page.login.TermsAndConditions;
import org.keycloak.testsuite.console.AbstractConsoleTest;
import org.keycloak.testsuite.console.page.authentication.RequiredActions;
+import org.keycloak.testsuite.pages.ErrorPage;
import java.util.ArrayList;
import java.util.List;
+import static org.junit.Assert.assertEquals;
+
/**
*
*/
@@ -48,12 +51,19 @@ public class TermsAndConditionsTest extends AbstractConsoleTest {
private static final String HOMER = "Homer";
private static final String HOMER_PASS = "Mmm donuts.";
+
+ private static final String FLANDERS = "Flanders";
+
+ private static final String FLANDERS_PASS = "Okily Dokily";
@Page
private TermsAndConditions termsAndConditionsPage;
@Page
private Registration registrationPage;
+
+ @Page
+ protected ErrorPage errorPage;
@Override
public void beforeConsoleTest() {
@@ -75,7 +85,7 @@ public class TermsAndConditionsTest extends AbstractConsoleTest {
testRealms.add(testRealmRep);
}
- @Test
+ @Test
public void testExistingUser() {
// create user
String userId = createUser(REALM, HOMER, HOMER_PASS);
@@ -107,7 +117,7 @@ public class TermsAndConditionsTest extends AbstractConsoleTest {
setRequiredActionEnabled(REALM, RequiredActions.TERMS_AND_CONDITIONS, false, false);
}
- @Test
+ @Test
public void testAdminCreatedUser() {
// enable terms
setRequiredActionEnabled(REALM, RequiredActions.TERMS_AND_CONDITIONS, true, false);
@@ -125,7 +135,7 @@ public class TermsAndConditionsTest extends AbstractConsoleTest {
setRequiredActionEnabled(REALM, RequiredActions.TERMS_AND_CONDITIONS, false, false);
}
- @Test
+ @Test
public void testSelfRegisteredUser() {
// enable self-registration
RealmResource realmResource = adminClient.realm(REALM);
@@ -162,5 +172,35 @@ public class TermsAndConditionsTest extends AbstractConsoleTest {
// disable terms
setRequiredActionEnabled(REALM, RequiredActions.TERMS_AND_CONDITIONS, false, false);
}
-
+
+ @Test
+ public void testTermsAndConditionsOnAccountPage() {
+ String userId = createUser(REALM, FLANDERS, FLANDERS_PASS);
+
+ setRequiredActionEnabled(REALM, RequiredActions.TERMS_AND_CONDITIONS, true, false);
+ setRequiredActionEnabled(REALM, userId, RequiredActions.TERMS_AND_CONDITIONS, true);
+
+ // login and decline the terms -- an error page should be shown
+ testRealmAccountPage.navigateTo();
+ loginPage.form().login(FLANDERS, FLANDERS_PASS);
+ termsAndConditionsPage.assertCurrent();
+ termsAndConditionsPage.declineTerms();
+
+ // check an error page after declining the terms
+ errorPage.assertCurrent();
+ assertEquals("No access", errorPage.getError());
+
+ // follow the link "back to application"
+ errorPage.clickBackToApplication();
+
+ // login again and accept the terms for now
+ loginPage.form().login(FLANDERS, FLANDERS_PASS);
+ termsAndConditionsPage.assertCurrent();
+ termsAndConditionsPage.acceptTerms();
+ testRealmAccountPage.assertCurrent();
+ testRealmAccountPage.logOut();
+
+ // disable terms
+ setRequiredActionEnabled(REALM, RequiredActions.TERMS_AND_CONDITIONS, false, false);
+ }
}
\ No newline at end of file