keycloak-aplcache
Changes
testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java 2(+1 -1)
Details
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-oauth-grant.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-oauth-grant.ftl
index edc7ef7..045ba9b 100755
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-oauth-grant.ftl
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-oauth-grant.ftl
@@ -25,7 +25,7 @@
<ul>
<#list oauth.resourceRolesRequested[resourceRole] as role>
<li>
- <span>${role.description}</span>
+ <span><#if role.description??>${role.description}<#else>${role.name}</#if></span>
</li>
</#list>
</ul>
diff --git a/model/api/src/main/java/org/keycloak/models/Constants.java b/model/api/src/main/java/org/keycloak/models/Constants.java
index b0af34c..57002e5 100755
--- a/model/api/src/main/java/org/keycloak/models/Constants.java
+++ b/model/api/src/main/java/org/keycloak/models/Constants.java
@@ -12,5 +12,7 @@ public interface Constants {
String IDENTITY_REQUESTER_ROLE = "KEYCLOAK_IDENTITY_REQUESTER";
String WILDCARD_ROLE = "*";
- String ACCOUNT_MANAGEMENT_APPLICATION = "Account Management";
+ String ACCOUNT_APPLICATION = "Account";
+ String ACCOUNT_PROFILE_ROLE = "KEYCLOAK_ACCOUNT_PROFILE";
+ String ACCOUNT_MANAGE_ROLE = "KEYCLOAK_ACCOUNT_MANAGE";
}
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index 5fe4475..bc50831 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -173,7 +173,7 @@ public class AuthenticationManager {
return null;
}
- Auth auth = new Auth();
+ Auth auth = new Auth(token);
UserModel user = realm.getUser(token.getPrincipal());
if (user == null || !user.isEnabled()) {
@@ -220,7 +220,7 @@ public class AuthenticationManager {
throw new NotAuthorizedException("token_expired");
}
- Auth auth = new Auth();
+ Auth auth = new Auth(token);
UserModel user = realm.getUser(token.getPrincipal());
if (user == null || !user.isEnabled()) {
@@ -309,9 +309,18 @@ public class AuthenticationManager {
}
public static class Auth {
+ private SkeletonKeyToken token;
private UserModel user;
private UserModel client;
+ public Auth(SkeletonKeyToken token) {
+ this.token = token;
+ }
+
+ public SkeletonKeyToken getToken() {
+ return token;
+ }
+
public UserModel getUser() {
return user;
}
diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
index 14220b2..52f88f1 100755
--- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java
@@ -107,9 +107,11 @@ public class RealmManager {
}
private void enableAccountManagement(RealmModel realm) {
- ApplicationModel application = realm.getApplicationById(Constants.ACCOUNT_MANAGEMENT_APPLICATION);
+ ApplicationModel application = realm.getApplicationById(Constants.ACCOUNT_APPLICATION);
if (application == null) {
- application = realm.addApplication(Constants.ACCOUNT_MANAGEMENT_APPLICATION);
+ application = realm.addApplication(Constants.ACCOUNT_APPLICATION);
+ application.addRole(Constants.ACCOUNT_PROFILE_ROLE);
+ application.addRole(Constants.ACCOUNT_MANAGE_ROLE);
UserCredentialModel password = new UserCredentialModel();
password.setType(UserCredentialModel.PASSWORD);
@@ -124,7 +126,7 @@ public class RealmManager {
}
private void disableAccountManagement(RealmModel realm) {
- ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APPLICATION);
+ ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
if (application != null) {
application.setEnabled(false); // TODO Should we delete the application instead?
}
@@ -424,7 +426,7 @@ public class RealmManager {
rep.setSmtpServer(realm.getSmtpConfig());
rep.setSocialProviders(realm.getSocialConfig());
- ApplicationModel accountManagementApplication = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APPLICATION);
+ ApplicationModel accountManagementApplication = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
rep.setAccountManagement(accountManagementApplication != null && accountManagementApplication.isEnabled());
List<RoleModel> defaultRoles = realm.getDefaultRoles();
diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
index 3c1cfa0..4b6f79e 100755
--- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java
@@ -11,10 +11,7 @@ import org.keycloak.representations.SkeletonKeyToken;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -54,6 +51,9 @@ public class TokenManager {
if (scope.size() > 0) {
Set<String> scopeRequest = null;
if (scopeMap != null) {
+ if (scopeRequest == null) {
+ scopeRequest = new HashSet<String>();
+ }
scopeRequest.addAll(scopeMap.get("realm"));
if (scopeRequest.contains(Constants.WILDCARD_ROLE)) scopeRequest = null;
}
@@ -73,6 +73,9 @@ public class TokenManager {
if (scope.size() > 0) {
Set<String> scopeRequest = null;
if (scopeMap != null) {
+ if (scopeRequest == null) {
+ scopeRequest = new HashSet<String>();
+ }
scopeRequest.addAll(scopeMap.get(resource.getName()));
if (scopeRequest.contains(Constants.WILDCARD_ROLE)) scopeRequest = null;
}
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index ac4fabf..2abcf99 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -22,16 +22,12 @@
package org.keycloak.services.resources;
import java.net.URI;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
-import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Providers;
-import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.jose.jws.JWSInput;
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
import org.jboss.resteasy.logging.Logger;
@@ -39,15 +35,13 @@ import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.AbstractOAuthClient;
import org.keycloak.jaxrs.JaxrsOAuthClient;
import org.keycloak.models.*;
+import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.representations.idm.CredentialRepresentation;
-import org.keycloak.representations.idm.UserRepresentation;
-import org.keycloak.services.email.EmailSender;
import org.keycloak.services.managers.AccessCodeEntry;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.messages.Messages;
-import org.keycloak.models.UserModel.RequiredAction;
import org.keycloak.services.resources.flows.Flows;
import org.keycloak.services.resources.flows.FormFlows;
import org.keycloak.services.resources.flows.Pages;
@@ -99,13 +93,13 @@ public class AccountService {
}
}
- @Path("")
+ @Path("/")
@OPTIONS
public Response accountPreflight() {
return Cors.add(request, Response.ok()).auth().preflight().build();
}
- @Path("")
+ @Path("/")
@GET
public Response accountPage() {
List<MediaType> types = headers.getAcceptableMediaTypes();
@@ -113,6 +107,10 @@ public class AccountService {
return forwardToPage(null, Pages.ACCOUNT);
} else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
AuthenticationManager.Auth auth = getAuth(true);
+ if (!hasAccess(auth, Constants.ACCOUNT_PROFILE_ROLE)) {
+ throw new ForbiddenException();
+ }
+
return Cors.add(request, Response.ok(RealmManager.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
} else {
return Response.notAcceptable(Variant.VariantListBuilder.newInstance().mediaTypes(MediaType.TEXT_HTML_TYPE, MediaType.APPLICATION_JSON_TYPE).build()).build();
@@ -143,7 +141,7 @@ public class AccountService {
return forwardToPage("access", Pages.ACCESS);
}
- @Path("")
+ @Path("/")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
@@ -330,7 +328,7 @@ public class AccountService {
String authUrl = Urls.realmLoginPage(uriInfo.getBaseUri(), realm.getId()).toString();
oauth.setAuthUrl(authUrl);
- oauth.setClientId(Constants.ACCOUNT_MANAGEMENT_APPLICATION);
+ oauth.setClientId(Constants.ACCOUNT_APPLICATION);
URI accountUri = Urls.accountPageBuilder(uriInfo.getBaseUri()).path(AccountService.class, "loginRedirect").build(realm.getId());
@@ -346,4 +344,27 @@ public class AccountService {
return auth;
}
+ private boolean hasAccess(AuthenticationManager.Auth auth, String requiredRole) {
+ UserModel client = auth.getClient();
+
+ if (realm.hasRole(client, Constants.APPLICATION_ROLE)) {
+ return true;
+ }
+
+ SkeletonKeyToken token = auth.getToken();
+ SkeletonKeyToken.Access access = token.getResourceAccess(application.getName());
+
+ if (access != null) {
+ if (access.isUserInRole(Constants.ACCOUNT_MANAGE_ROLE)) {
+ return true;
+ }
+
+ if (access.isUserInRole(Constants.ACCOUNT_PROFILE_ROLE)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
}
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 54fd5a5..0e1bc0f 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -69,7 +69,7 @@ public class RealmsResource {
throw new NotFoundException();
}
- ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_MANAGEMENT_APPLICATION);
+ ApplicationModel application = realm.getApplicationNameMap().get(Constants.ACCOUNT_APPLICATION);
if (application == null || !application.isEnabled()) {
logger.debug("account management not enabled");
throw new NotFoundException();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
index cdcef48..cc5144d 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/ProfileTest.java
@@ -18,6 +18,7 @@ import org.keycloak.testsuite.Constants;
import org.keycloak.testsuite.OAuthClient;
import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.keycloak.testsuite.rule.KeycloakRule;
import org.keycloak.testsuite.rule.WebResource;
import org.keycloak.testsuite.rule.WebRule;
@@ -30,6 +31,7 @@ import java.io.IOException;
import java.net.URI;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
@@ -47,6 +49,14 @@ public class ProfileTest {
user.setAttribute("key1", "value1");
user.setAttribute("key2", "value2");
+ ApplicationModel accountApp = appRealm.getApplicationNameMap().get(org.keycloak.models.Constants.ACCOUNT_APPLICATION);
+
+ accountApp.grantRole(user, accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE));
+ accountApp.grantRole(user, accountApp.getRole(org.keycloak.models.Constants.ACCOUNT_MANAGE_ROLE));
+
+ UserModel thirdParty = appRealm.getUser("third-party");
+ accountApp.addScopeMapping(thirdParty, org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
+
for (ApplicationModel app : appRealm.getApplications()) {
if (app.getName().equals("test-app")) {
app.getApplicationUser().addWebOrigin("http://localtest.me:8081");
@@ -70,6 +80,9 @@ public class ProfileTest {
@WebResource
protected LoginPage loginPage;
+ @WebResource
+ protected OAuthGrantPage grantPage;
+
@Test
public void getProfile() throws Exception {
oauth.doLogin("test-user@localhost", "password");
@@ -139,6 +152,35 @@ public class ProfileTest {
assertEquals(403, response.getStatusLine().getStatusCode());
}
+ @Test
+ public void getProfileOAuthClient() throws Exception {
+ oauth.addScope(org.keycloak.models.Constants.ACCOUNT_APPLICATION, org.keycloak.models.Constants.ACCOUNT_PROFILE_ROLE);
+ oauth.clientId("third-party");
+ oauth.doLoginGrant("test-user@localhost", "password");
+
+ grantPage.accept();
+
+ String token = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get("code"), "password").getAccessToken();
+ HttpResponse response = doGetProfile(token, null);
+
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ JSONObject profile = new JSONObject(IOUtils.toString(response.getEntity().getContent()));
+
+ assertEquals("test-user@localhost", profile.getString("username"));
+ }
+
+ @Test
+ public void getProfileOAuthClientNoScope() throws Exception {
+ oauth.addScope(org.keycloak.models.Constants.ACCOUNT_APPLICATION);
+ oauth.clientId("third-party");
+ oauth.doLoginGrant("test-user@localhost", "password");
+
+ String token = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get("code"), "password").getAccessToken();
+ HttpResponse response = doGetProfile(token, null);
+
+ assertEquals(403, response.getStatusLine().getStatusCode());
+ }
+
private URI getAccountURI() {
return UriBuilder.fromUri(Constants.AUTH_SERVER_ROOT + "/rest/realms/" + oauth.getRealm() + "/account").build();
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java
index 51ba944..d591829 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionMultipleActionsTest.java
@@ -76,7 +76,7 @@ public class RequiredActionMultipleActionsTest {
protected LoginUpdateProfilePage updateProfilePage;
@Test
- public void updateProfileAndPassword() {
+ public void updateProfileAndPassword() throws Exception {
loginPage.open();
loginPage.login("test-user@localhost", "password");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java
index f4cb070..76757f4 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionResetPasswordTest.java
@@ -81,7 +81,7 @@ public class RequiredActionResetPasswordTest {
protected LoginPasswordUpdatePage changePasswordPage;
@Test
- public void tempPassword() {
+ public void tempPassword() throws Exception {
loginPage.open();
loginPage.login("test-user@localhost", "password");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
index 54451f4..2ff938b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java
@@ -93,7 +93,7 @@ public class LoginTotpTest {
}
@Test
- public void loginWithTotpFailure() {
+ public void loginWithTotpFailure() throws Exception {
loginPage.open();
loginPage.login("test-user@localhost", "password");
@@ -106,7 +106,7 @@ public class LoginTotpTest {
}
@Test
- public void loginWithTotpSuccess() {
+ public void loginWithTotpSuccess() throws Exception {
loginPage.open();
loginPage.login("test-user@localhost", "password");
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java
index 0513f67..e5d7ef6 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/OAuthGrantTest.java
@@ -22,14 +22,15 @@
package org.keycloak.testsuite.oauth;
import java.io.IOException;
+import java.util.Map;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.testsuite.OAuthClient;
-import org.keycloak.testsuite.OAuthGrantServlet;
import org.keycloak.testsuite.pages.LoginPage;
import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.keycloak.testsuite.rule.KeycloakRule;
@@ -45,11 +46,6 @@ public class OAuthGrantTest {
@ClassRule
public static KeycloakRule keycloakRule = new KeycloakRule();
- @BeforeClass
- public static void before() {
- keycloakRule.deployServlet("grant", "/grant", OAuthGrantServlet.class);
- }
-
@Rule
public WebRule webRule = new WebRule(this);
@@ -65,28 +61,13 @@ public class OAuthGrantTest {
@WebResource
protected OAuthGrantPage grantPage;
- private static String GRANT_APP_URL = "http://localhost:8081/grant/";
-
- private static String ACCESS_GRANTED = "Access rights granted.";
- private static String ACCESS_NOT_GRANTED = "Access rights not granted.";
-
private static String ROLE_USER = "Have User privileges";
private static String ROLE_CUSTOMER = "Have Customer User privileges";
- private static String GRANT_ROLE = "user";
- private static String GRANT_APP = "test-app";
- private static String GRANT_APP_ROLE = "customer-user";
-
@Test
public void oauthGrantAcceptTest() throws IOException {
-
- driver.navigate().to(GRANT_APP_URL);
-
- Assert.assertFalse(driver.getPageSource().contains(ACCESS_GRANTED));
- Assert.assertFalse(driver.getPageSource().contains(ACCESS_NOT_GRANTED));
-
- loginPage.isCurrent();
- loginPage.login("test-user@localhost", "password");
+ oauth.clientId("third-party");
+ oauth.doLoginGrant("test-user@localhost", "password");
grantPage.assertCurrent();
Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
@@ -94,23 +75,50 @@ public class OAuthGrantTest {
grantPage.accept();
- Assert.assertTrue(driver.getPageSource().contains(ACCESS_GRANTED));
- Assert.assertFalse(driver.getPageSource().contains(ACCESS_NOT_GRANTED));
+ Assert.assertTrue(oauth.getCurrentQuery().containsKey("code"));
+ OAuthClient.AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get("code"), "password");
+
+ SkeletonKeyToken token = oauth.verifyToken(accessToken.getAccessToken());
- Assert.assertTrue(driver.getPageSource().contains("Role:"+ GRANT_ROLE +"."));
- Assert.assertTrue(driver.getPageSource().contains("App:"+ GRANT_APP +";"+ GRANT_APP_ROLE +"."));
+ SkeletonKeyToken.Access realmAccess = token.getRealmAccess();
+ Assert.assertEquals(1, realmAccess.getRoles().size());
+ Assert.assertTrue(realmAccess.isUserInRole("user"));
+
+ Map<String,SkeletonKeyToken.Access> resourceAccess = token.getResourceAccess();
+ Assert.assertEquals(1, resourceAccess.size());
+ Assert.assertEquals(1, resourceAccess.get("test-app").getRoles().size());
+ Assert.assertTrue(resourceAccess.get("test-app").isUserInRole("customer-user"));
}
@Test
- public void oauthGrantCancelTest() throws IOException {
+ public void oauthGrantAcceptTestWithScope() throws IOException {
+ oauth.addScope("test-app", "customer-user");
+ oauth.clientId("third-party");
+ oauth.doLoginGrant("test-user@localhost", "password");
- driver.navigate().to(GRANT_APP_URL);
+ grantPage.assertCurrent();
+ Assert.assertTrue(driver.getPageSource().contains(ROLE_CUSTOMER));
+
+ grantPage.accept();
+
+ Assert.assertTrue(oauth.getCurrentQuery().containsKey("code"));
+ OAuthClient.AccessTokenResponse accessToken = oauth.doAccessTokenRequest(oauth.getCurrentQuery().get("code"), "password");
- Assert.assertFalse(driver.getPageSource().contains(ACCESS_GRANTED));
- Assert.assertFalse(driver.getPageSource().contains(ACCESS_NOT_GRANTED));
+ SkeletonKeyToken token = oauth.verifyToken(accessToken.getAccessToken());
- loginPage.isCurrent();
- loginPage.login("test-user@localhost", "password");
+ SkeletonKeyToken.Access realmAccess = token.getRealmAccess();
+ Assert.assertNull(realmAccess);
+
+ Map<String,SkeletonKeyToken.Access> resourceAccess = token.getResourceAccess();
+ Assert.assertEquals(1, resourceAccess.size());
+ Assert.assertEquals(1, resourceAccess.get("test-app").getRoles().size());
+ Assert.assertTrue(resourceAccess.get("test-app").isUserInRole("customer-user"));
+ }
+
+ @Test
+ public void oauthGrantCancelTest() throws IOException {
+ oauth.clientId("third-party");
+ oauth.doLoginGrant("test-user@localhost", "password");
grantPage.assertCurrent();
Assert.assertTrue(driver.getPageSource().contains(ROLE_USER));
@@ -118,7 +126,7 @@ public class OAuthGrantTest {
grantPage.cancel();
- Assert.assertFalse(driver.getPageSource().contains(ACCESS_GRANTED));
- Assert.assertTrue(driver.getPageSource().contains(ACCESS_NOT_GRANTED));
+ Assert.assertTrue(oauth.getCurrentQuery().containsKey("error"));
+ Assert.assertEquals("access_denied", oauth.getCurrentQuery().get("error"));
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
index dcda888..bff07dd 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/OAuthClient.java
@@ -32,6 +32,7 @@ import java.util.Map;
import javax.ws.rs.core.UriBuilder;
+import com.google.api.client.repackaged.org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
@@ -41,11 +42,16 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
+import org.jboss.resteasy.jose.Base64Url;
+import org.jboss.resteasy.jwt.JsonSerialization;
import org.jboss.resteasy.security.PemUtils;
import org.json.JSONObject;
import org.junit.Assert;
import org.keycloak.RSATokenVerifier;
+import org.keycloak.VerificationException;
+import org.keycloak.representations.SkeletonKeyScope;
import org.keycloak.representations.SkeletonKeyToken;
+import org.keycloak.testsuite.pages.OAuthGrantPage;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
@@ -68,17 +74,21 @@ public class OAuthClient {
private String redirectUri = "http://localhost:8081/app/auth";
- private String scope;
+ private SkeletonKeyScope scope;
private String state;
private PublicKey realmPublicKey;
- public OAuthClient(WebDriver driver) throws Exception {
+ public OAuthClient(WebDriver driver) {
this.driver = driver;
- JSONObject realmJson = new JSONObject(IOUtils.toString(getClass().getResourceAsStream("/testrealm.json")));
- realmPublicKey = PemUtils.decodePublicKey(realmJson.getString("publicKey"));
+ try {
+ JSONObject realmJson = new JSONObject(IOUtils.toString(getClass().getResourceAsStream("/testrealm.json")));
+ realmPublicKey = PemUtils.decodePublicKey(realmJson.getString("publicKey"));
+ } catch (Exception e) {
+ throw new AssertionError("Failed to retrieve realm public key", e);
+ }
}
public AuthorizationCodeResponse doLogin(String username, String password) {
@@ -91,7 +101,15 @@ public class OAuthClient {
return new AuthorizationCodeResponse(this);
}
- public AccessTokenResponse doAccessTokenRequest(String code, String password) throws Exception {
+ public void doLoginGrant(String username, String password) {
+ openLoginForm();
+
+ driver.findElement(By.id("username")).sendKeys(username);
+ driver.findElement(By.id("password")).sendKeys(password);
+ driver.findElement(By.cssSelector("input[type=\"submit\"]")).click();
+ }
+
+ public AccessTokenResponse doAccessTokenRequest(String code, String password) {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(getAccessTokenUrl());
@@ -115,27 +133,19 @@ public class OAuthClient {
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, Charset.forName("UTF-8"));
post.setEntity(formEntity);
- return new AccessTokenResponse(client.execute(post));
- }
-
- public SkeletonKeyToken verifyToken(String token) throws Exception {
- return RSATokenVerifier.verifyToken(token, realmPublicKey, realm);
- }
-
- public boolean isAuthorizationResponse() {
- return getCurrentRequest().equals(redirectUri) && getCurrentQuery().containsKey("code");
- }
-
- public String getState() {
- return state;
- }
-
- public String getClientId() {
- return clientId;
+ try {
+ return new AccessTokenResponse(client.execute(post));
+ } catch (Exception e) {
+ throw new AssertionError("Failed to retrieve access token", e);
+ }
}
- public String getResponseType() {
- return responseType;
+ public SkeletonKeyToken verifyToken(String token) {
+ try {
+ return RSATokenVerifier.verifyToken(token, realmPublicKey, realm);
+ } catch (VerificationException e) {
+ throw new AssertionError("Failed to verify token", e);
+ }
}
public String getCurrentRequest() {
@@ -175,10 +185,6 @@ public class OAuthClient {
return redirectUri;
}
- public String getScope() {
- return scope;
- }
-
public String getLoginFormUrl() {
UriBuilder b = UriBuilder.fromUri(baseUrl + "/realms/" + realm + "/tokens/login");
if (responseType != null) {
@@ -191,7 +197,12 @@ public class OAuthClient {
b.queryParam("redirect_uri", redirectUri);
}
if (scope != null) {
- b.queryParam("scope", scope);
+ try {
+
+ b.queryParam("scope", Base64Url.encode(JsonSerialization.toByteArray(scope, false)));
+ } catch (Exception e) {
+ throw new AssertionError("Failed to serialize scope", e);
+ }
}
if (state != null) {
b.queryParam("state", state);
@@ -224,8 +235,11 @@ public class OAuthClient {
return this;
}
- public OAuthClient scope(String scope) {
- this.scope = scope;
+ public OAuthClient addScope(String resource, String... roles) {
+ if (scope == null) {
+ scope = new SkeletonKeyScope();
+ }
+ scope.addAll(resource, roles);
return this;
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractPage.java
index 1183ece..c17b86a 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AbstractPage.java
@@ -41,6 +41,6 @@ public abstract class AbstractPage {
abstract boolean isCurrent();
- abstract void open();
+ abstract void open() throws Exception;
}