keycloak-uncached
Changes
testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java 37(+31 -6)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java 2(+1 -1)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java 12(+6 -6)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java 4(+2 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java 43(+6 -37)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/AbstractOIDCResponseTypeTest.java 123(+123 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCBasicResponseTypeCodeTest.java 72(+72 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCHybridResponseTypeCodeIDTokenTest.java 76(+76 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCImplicitResponseTypeIDTokenTest.java 72(+72 -0)
Details
diff --git a/core/src/main/java/org/keycloak/OAuth2Constants.java b/core/src/main/java/org/keycloak/OAuth2Constants.java
index 188d759..2a7d37b 100644
--- a/core/src/main/java/org/keycloak/OAuth2Constants.java
+++ b/core/src/main/java/org/keycloak/OAuth2Constants.java
@@ -42,6 +42,10 @@ public interface OAuth2Constants {
String RESPONSE_TYPE = "response_type";
+ String ACCESS_TOKEN = "access_token";
+
+ String ID_TOKEN = "id_token";
+
String REFRESH_TOKEN = "refresh_token";
String AUTHORIZATION_CODE = "authorization_code";
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
index 95aa9a6..b08d3d8 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/endpoints/AuthorizationEndpoint.java
@@ -340,6 +340,12 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
return redirectErrorToClient(parsedResponseMode, OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, null);
}
+ if (parsedResponseType.isImplicitOrHybridFlow() && nonce == null) {
+ logger.missingParameter(OIDCLoginProtocol.NONCE_PARAM);
+ event.error(Errors.INVALID_REQUEST);
+ return redirectErrorToClient(parsedResponseMode, OAuthErrorException.INVALID_REQUEST, "Missing parameter: nonce");
+ }
+
return null;
}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
index 3105122..8271cc7 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -171,11 +171,11 @@ public class OIDCLoginProtocol implements LoginProtocol {
.build();
if (responseType.hasResponseType(OIDCResponseType.ID_TOKEN)) {
- redirectUri.addParam("id_token", res.getIdToken());
+ redirectUri.addParam(OAuth2Constants.ID_TOKEN, res.getIdToken());
}
if (responseType.hasResponseType(OIDCResponseType.TOKEN)) {
- redirectUri.addParam("access_token", res.getToken());
+ redirectUri.addParam(OAuth2Constants.ACCESS_TOKEN, res.getToken());
redirectUri.addParam("token_type", res.getTokenType());
redirectUri.addParam("session_state", res.getSessionState());
redirectUri.addParam("expires_in", String.valueOf(res.getExpiresIn()));
diff --git a/testsuite/integration/src/test/resources/log4j.properties b/testsuite/integration/src/test/resources/log4j.properties
index 327102e..5d5369c 100755
--- a/testsuite/integration/src/test/resources/log4j.properties
+++ b/testsuite/integration/src/test/resources/log4j.properties
@@ -56,6 +56,9 @@ log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=${
# Enable to view hibernate statistics
log4j.logger.org.keycloak.connections.jpa.HibernateStatsReporter=debug
+# Enable to view ldap logging
+# log4j.logger.org.keycloak.federation.ldap=trace
+
# Enable to view kerberos/spnego logging
# log4j.logger.org.keycloak.federation.kerberos=trace
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
index 8c7b290..1d632c1 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/OAuthClient.java
@@ -41,6 +41,7 @@ import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
+import org.keycloak.protocol.oidc.utils.OIDCResponseType;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.RefreshToken;
@@ -120,7 +121,7 @@ public class OAuthClient {
maxAge = null;
}
- public AuthorizationCodeResponse doLogin(String username, String password) {
+ public AuthorizationEndpointResponse doLogin(String username, String password) {
openLoginForm();
String src = driver.getPageSource();
try {
@@ -132,7 +133,7 @@ public class OAuthClient {
throw t;
}
- return new AuthorizationCodeResponse(this);
+ return new AuthorizationEndpointResponse(this);
}
public void doLoginGrant(String username, String password) {
@@ -637,7 +638,7 @@ public class OAuthClient {
return realm;
}
- public static class AuthorizationCodeResponse {
+ public static class AuthorizationEndpointResponse {
private boolean isRedirected;
private String code;
@@ -645,11 +646,25 @@ public class OAuthClient {
private String error;
private String errorDescription;
- public AuthorizationCodeResponse(OAuthClient client) {
- this(client, false);
+ // Just during OIDC implicit or hybrid flow
+ private String accessToken;
+ private String idToken;
+
+ public AuthorizationEndpointResponse(OAuthClient client) {
+ boolean fragment;
+ try {
+ fragment = client.responseType != null && OIDCResponseType.parse(client.responseType).isImplicitOrHybridFlow();
+ } catch (IllegalArgumentException iae) {
+ fragment = false;
+ }
+ init (client, fragment);
+ }
+
+ public AuthorizationEndpointResponse(OAuthClient client, boolean fragment) {
+ init(client, fragment);
}
- public AuthorizationCodeResponse(OAuthClient client, boolean fragment) {
+ private void init(OAuthClient client, boolean fragment) {
isRedirected = client.getCurrentRequest().equals(client.getRedirectUri());
Map<String, String> params = fragment ? client.getCurrentFragment() : client.getCurrentQuery();
@@ -657,6 +672,8 @@ public class OAuthClient {
state = params.get(OAuth2Constants.STATE);
error = params.get(OAuth2Constants.ERROR);
errorDescription = params.get(OAuth2Constants.ERROR_DESCRIPTION);
+ accessToken = params.get(OAuth2Constants.ACCESS_TOKEN);
+ idToken = params.get(OAuth2Constants.ID_TOKEN);
}
public boolean isRedirected() {
@@ -678,6 +695,14 @@ public class OAuthClient {
public String getErrorDescription() {
return errorDescription;
}
+
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ public String getIdToken() {
+ return idToken;
+ }
}
public static class AccessTokenResponse {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
index 4e2bdd9..ee06750 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/ClientTest.java
@@ -129,7 +129,7 @@ public class ClientTest extends AbstractAdminTest {
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest("password", "test-user@localhost", "password");
assertEquals(200, response.getStatusCode());
- OAuthClient.AuthorizationCodeResponse codeResponse = oauth.doLogin("test-user@localhost", "password");
+ OAuthClient.AuthorizationEndpointResponse codeResponse = oauth.doLogin("test-user@localhost", "password");
OAuthClient.AccessTokenResponse response2 = oauth.doAccessTokenRequest(codeResponse.getCode(), "password");
assertEquals(200, response2.getStatusCode());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java
index ece81d8..cf69f74 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/AuthorizationCodeTest.java
@@ -78,7 +78,7 @@ public class AuthorizationCodeTest extends AbstractKeycloakTest {
public void authorizationRequest() throws IOException {
oauth.state("OpenIdConnect.AuthenticationProperties=2302984sdlk");
- OAuthClient.AuthorizationCodeResponse response = oauth.doLogin("test-user@localhost", "password");
+ OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
Assert.assertTrue(response.isRedirected());
Assert.assertNotNull(response.getCode());
@@ -116,7 +116,7 @@ public class AuthorizationCodeTest extends AbstractKeycloakTest {
oauth.state("mystate");
- OAuthClient.AuthorizationCodeResponse response = oauth.doLogin("test-user@localhost", "password");
+ OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
Assert.assertTrue(response.isRedirected());
Assert.assertNotNull(response.getCode());
@@ -131,7 +131,7 @@ public class AuthorizationCodeTest extends AbstractKeycloakTest {
public void authorizationRequestNoState() throws IOException {
oauth.state(null);
- OAuthClient.AuthorizationCodeResponse response = oauth.doLogin("test-user@localhost", "password");
+ OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
Assert.assertTrue(response.isRedirected());
Assert.assertNotNull(response.getCode());
@@ -150,7 +150,7 @@ public class AuthorizationCodeTest extends AbstractKeycloakTest {
UriBuilder b = UriBuilder.fromUri(oauth.getLoginFormUrl());
driver.navigate().to(b.build().toURL());
- OAuthClient.AuthorizationCodeResponse errorResponse = new OAuthClient.AuthorizationCodeResponse(oauth, true);
+ OAuthClient.AuthorizationEndpointResponse errorResponse = new OAuthClient.AuthorizationEndpointResponse(oauth, true);
Assert.assertTrue(errorResponse.isRedirected());
Assert.assertEquals(errorResponse.getError(), OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE);
Assert.assertEquals(errorResponse.getErrorDescription(), "Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client.");
@@ -164,7 +164,7 @@ public class AuthorizationCodeTest extends AbstractKeycloakTest {
UriBuilder b = UriBuilder.fromUri(oauth.getLoginFormUrl());
driver.navigate().to(b.build().toURL());
- OAuthClient.AuthorizationCodeResponse errorResponse = new OAuthClient.AuthorizationCodeResponse(oauth);
+ OAuthClient.AuthorizationEndpointResponse errorResponse = new OAuthClient.AuthorizationEndpointResponse(oauth);
Assert.assertTrue(errorResponse.isRedirected());
Assert.assertEquals(errorResponse.getError(), OAuthErrorException.INVALID_REQUEST);
@@ -177,7 +177,7 @@ public class AuthorizationCodeTest extends AbstractKeycloakTest {
UriBuilder b = UriBuilder.fromUri(oauth.getLoginFormUrl());
driver.navigate().to(b.build().toURL());
- OAuthClient.AuthorizationCodeResponse errorResponse = new OAuthClient.AuthorizationCodeResponse(oauth);
+ OAuthClient.AuthorizationEndpointResponse errorResponse = new OAuthClient.AuthorizationEndpointResponse(oauth);
Assert.assertTrue(errorResponse.isRedirected());
Assert.assertEquals(errorResponse.getError(), OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
index 853b38b..f80e789 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OAuthRedirectUriTest.java
@@ -154,7 +154,7 @@ public class OAuthRedirectUriTest extends AbstractKeycloakTest {
@Test
public void testValid() throws IOException {
oauth.redirectUri(APP_ROOT + "/auth");
- OAuthClient.AuthorizationCodeResponse response = oauth.doLogin("test-user@localhost", "password");
+ OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response.getCode());
URL url = new URL(driver.getCurrentUrl());
@@ -175,7 +175,7 @@ public class OAuthRedirectUriTest extends AbstractKeycloakTest {
@Test
public void testWithParams() throws IOException {
oauth.redirectUri(APP_ROOT + "/auth?key=value");
- OAuthClient.AuthorizationCodeResponse response = oauth.doLogin("test-user@localhost", "password");
+ OAuthClient.AuthorizationEndpointResponse response = oauth.doLogin("test-user@localhost", "password");
Assert.assertNotNull(response.getCode());
URL url = new URL(driver.getCurrentUrl());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
index 2296908..191581e 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java
@@ -47,7 +47,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
- * Test for supporting advanced parameters of OIDC specs (max_age, nonce, prompt, ...)
+ * Test for supporting advanced parameters of OIDC specs (max_age, prompt, ...)
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@@ -169,7 +169,7 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
events.assertEmpty();
// Assert error response was sent because not logged in
- OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ OAuthClient.AuthorizationEndpointResponse resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
Assert.assertNull(resp.getCode());
Assert.assertEquals(OAuthErrorException.LOGIN_REQUIRED, resp.getError());
@@ -224,7 +224,7 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
assertTrue(appPage.isCurrent());
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
- OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ OAuthClient.AuthorizationEndpointResponse resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
Assert.assertNull(resp.getCode());
Assert.assertEquals(OAuthErrorException.INTERACTION_REQUIRED, resp.getError());
@@ -242,7 +242,7 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=none");
Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
- resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
Assert.assertNotNull(resp.getCode());
Assert.assertNull(resp.getError());
@@ -289,37 +289,6 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
}
-
- // NONCE
-
- @Test
- public void nonceNotUsed() {
- driver.navigate().to(oauth.getLoginFormUrl());
-
- loginPage.assertCurrent();
- loginPage.login("test-user@localhost", "password");
- Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
- EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
- IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
-
- Assert.assertNull(idToken.getNonce());
- }
-
- @Test
- public void nonceMatches() {
- driver.navigate().to(oauth.getLoginFormUrl() + "&nonce=abcdef123456");
-
- loginPage.assertCurrent();
- loginPage.login("test-user@localhost", "password");
- Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
- EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
- IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
-
- Assert.assertEquals("abcdef123456", idToken.getNonce());
- }
-
// DISPLAY & OTHERS
@Test
@@ -346,7 +315,7 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
assertTrue(appPage.isCurrent());
// Assert error response was sent because not logged in
- OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ OAuthClient.AuthorizationEndpointResponse resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
Assert.assertNull(resp.getCode());
Assert.assertEquals(OAuthErrorException.REQUEST_NOT_SUPPORTED, resp.getError());
}
@@ -359,7 +328,7 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
assertTrue(appPage.isCurrent());
// Assert error response was sent because not logged in
- OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ OAuthClient.AuthorizationEndpointResponse resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
Assert.assertNull(resp.getCode());
Assert.assertEquals(OAuthErrorException.REQUEST_URI_NOT_SUPPORTED, resp.getError());
}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/AbstractOIDCResponseTypeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/AbstractOIDCResponseTypeTest.java
new file mode 100644
index 0000000..047a62d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/AbstractOIDCResponseTypeTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 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.testsuite.oidc.resptype;
+
+import java.util.List;
+
+import org.jboss.arquillian.graphene.page.Page;
+import org.junit.Rule;
+import org.keycloak.OAuthErrorException;
+import org.keycloak.events.Details;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.AssertEvents;
+import org.keycloak.testsuite.TestRealmKeycloakTest;
+import org.keycloak.testsuite.admin.AbstractAdminTest;
+import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
+import org.keycloak.testsuite.pages.AppPage;
+import org.keycloak.testsuite.pages.LoginPage;
+import org.keycloak.testsuite.pages.OAuthGrantPage;
+import org.keycloak.testsuite.util.OAuthClient;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Abstract test for various values of response_type
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public abstract class AbstractOIDCResponseTypeTest extends TestRealmKeycloakTest {
+
+ @Rule
+ public AssertEvents events = new AssertEvents(this);
+
+ @Page
+ protected AppPage appPage;
+
+ @Page
+ protected LoginPage loginPage;
+
+ @Page
+ protected AccountUpdateProfilePage profilePage;
+
+ @Page
+ protected OAuthGrantPage grantPage;
+
+ @Override
+ public void configureTestRealm(RealmRepresentation testRealm) {
+ }
+
+
+ @Override
+ public void addTestRealms(List<RealmRepresentation> testRealms) {
+ RealmRepresentation realm = AbstractAdminTest.loadJson(getClass().getResourceAsStream("/testrealm.json"), RealmRepresentation.class);
+ testRealms.add(realm);
+ }
+
+
+ protected void nonceMatches() {
+ driver.navigate().to(oauth.getLoginFormUrl() + "&nonce=abcdef123456");
+
+ loginPage.assertCurrent();
+ loginPage.login("test-user@localhost", "password");
+ Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+ EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
+ List<IDToken> idTokens = retrieveIDTokens(loginEvent);
+
+ for (IDToken idToken : idTokens) {
+ Assert.assertEquals("abcdef123456", idToken.getNonce());
+ }
+ }
+
+
+ protected void nonceNotUsed() {
+ driver.navigate().to(oauth.getLoginFormUrl());
+
+ loginPage.assertCurrent();
+ loginPage.login("test-user@localhost", "password");
+ Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+ EventRepresentation loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
+
+ List<IDToken> idTokens = retrieveIDTokens(loginEvent);
+ for (IDToken idToken : idTokens) {
+ Assert.assertNull(idToken.getNonce());
+ }
+ }
+
+
+ protected void nonceNotUsedErrorExpected() {
+ driver.navigate().to(oauth.getLoginFormUrl());
+
+ assertFalse(loginPage.isCurrent());
+ assertTrue(appPage.isCurrent());
+
+ // Assert error response was sent because not logged in
+ OAuthClient.AuthorizationEndpointResponse resp = new OAuthClient.AuthorizationEndpointResponse(oauth);
+ Assert.assertNull(resp.getCode());
+ Assert.assertNull(resp.getIdToken());
+ Assert.assertEquals(OAuthErrorException.INVALID_REQUEST, resp.getError());
+ Assert.assertEquals("Missing parameter: nonce", resp.getErrorDescription());
+ }
+
+ protected abstract List<IDToken> retrieveIDTokens(EventRepresentation loginEvent);
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCBasicResponseTypeCodeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCBasicResponseTypeCodeTest.java
new file mode 100644
index 0000000..a8f51fb
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCBasicResponseTypeCodeTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 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.testsuite.oidc.resptype;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.events.Details;
+import org.keycloak.protocol.oidc.utils.OIDCResponseType;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.util.ClientManager;
+import org.keycloak.testsuite.util.OAuthClient;
+
+/**
+ * Test for response_type=code
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class OIDCBasicResponseTypeCodeTest extends AbstractOIDCResponseTypeTest {
+
+ @Before
+ public void clientConfiguration() {
+ ClientManager.realm(adminClient.realm("test")).clientId("test-app").standardFlow(true).implicitFlow(false);
+
+ oauth.clientId("test-app");
+ oauth.responseType(OIDCResponseType.CODE);
+ }
+
+
+ protected List<IDToken> retrieveIDTokens(EventRepresentation loginEvent) {
+ Assert.assertEquals(OIDCResponseType.CODE, loginEvent.getDetails().get(Details.RESPONSE_TYPE));
+
+ OAuthClient.AuthorizationEndpointResponse authzResponse = new OAuthClient.AuthorizationEndpointResponse(oauth, false);
+ Assert.assertNull(authzResponse.getAccessToken());
+ Assert.assertNull(authzResponse.getIdToken());
+
+ IDToken idToken = sendTokenRequestAndGetIDToken(loginEvent);
+
+ return Collections.singletonList(idToken);
+ }
+
+
+ @Test
+ public void nonceNotUsed() {
+ super.nonceNotUsed();
+ }
+
+
+ @Test
+ public void nonceMatches() {
+ super.nonceMatches();
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCHybridResponseTypeCodeIDTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCHybridResponseTypeCodeIDTokenTest.java
new file mode 100644
index 0000000..ff16927
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCHybridResponseTypeCodeIDTokenTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 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.testsuite.oidc.resptype;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.events.Details;
+import org.keycloak.protocol.oidc.utils.OIDCResponseType;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.util.ClientManager;
+import org.keycloak.testsuite.util.OAuthClient;
+
+/**
+ * Tests with response_type=code id_token
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class OIDCHybridResponseTypeCodeIDTokenTest extends AbstractOIDCResponseTypeTest {
+
+ @Before
+ public void clientConfiguration() {
+ ClientManager.realm(adminClient.realm("test")).clientId("test-app").standardFlow(true).implicitFlow(true);
+
+ oauth.clientId("test-app");
+ oauth.responseType(OIDCResponseType.CODE + " " + OIDCResponseType.ID_TOKEN);
+ }
+
+
+ protected List<IDToken> retrieveIDTokens(EventRepresentation loginEvent) {
+ Assert.assertEquals(OIDCResponseType.CODE + " " + OIDCResponseType.ID_TOKEN, loginEvent.getDetails().get(Details.RESPONSE_TYPE));
+
+ // IDToken from the authorization response
+ OAuthClient.AuthorizationEndpointResponse authzResponse = new OAuthClient.AuthorizationEndpointResponse(oauth, true);
+ Assert.assertNull(authzResponse.getAccessToken());
+ String idTokenStr = authzResponse.getIdToken();
+ IDToken idToken = oauth.verifyIDToken(idTokenStr);
+
+ // IDToken exchanged for the code
+ IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
+
+ return Arrays.asList(idToken, idToken2);
+ }
+
+
+ @Test
+ public void nonceNotUsedErrorExpected() {
+ super.nonceNotUsedErrorExpected();
+ }
+
+
+ @Test
+ public void nonceMatches() {
+ super.nonceMatches();
+ }
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCImplicitResponseTypeIDTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCImplicitResponseTypeIDTokenTest.java
new file mode 100644
index 0000000..4bcdc65
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/resptype/OIDCImplicitResponseTypeIDTokenTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 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.testsuite.oidc.resptype;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.events.Details;
+import org.keycloak.protocol.oidc.utils.OIDCResponseType;
+import org.keycloak.representations.IDToken;
+import org.keycloak.representations.idm.EventRepresentation;
+import org.keycloak.testsuite.Assert;
+import org.keycloak.testsuite.util.ClientManager;
+import org.keycloak.testsuite.util.OAuthClient;
+
+/**
+ * Tests with response_type=id_token
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class OIDCImplicitResponseTypeIDTokenTest extends AbstractOIDCResponseTypeTest {
+
+ @Before
+ public void clientConfiguration() {
+ ClientManager.realm(adminClient.realm("test")).clientId("test-app").standardFlow(false).implicitFlow(true);
+
+ oauth.clientId("test-app");
+ oauth.responseType(OIDCResponseType.ID_TOKEN);
+ }
+
+
+ protected List<IDToken> retrieveIDTokens(EventRepresentation loginEvent) {
+ Assert.assertEquals(OIDCResponseType.ID_TOKEN, loginEvent.getDetails().get(Details.RESPONSE_TYPE));
+
+ OAuthClient.AuthorizationEndpointResponse authzResponse = new OAuthClient.AuthorizationEndpointResponse(oauth, true);
+ Assert.assertNull(authzResponse.getAccessToken());
+ String idTokenStr = authzResponse.getIdToken();
+ IDToken idToken = oauth.verifyIDToken(idTokenStr);
+
+ return Collections.singletonList(idToken);
+ }
+
+
+ @Test
+ public void nonceNotUsedErrorExpected() {
+ super.nonceNotUsedErrorExpected();
+ }
+
+
+ @Test
+ public void nonceMatches() {
+ super.nonceMatches();
+ }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java
index 0e10c58..040bb4c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/TestRealmKeycloakTest.java
@@ -86,7 +86,7 @@ public abstract class TestRealmKeycloakTest extends AbstractKeycloakTest {
String sessionId = loginEvent.getSessionId();
String codeId = loginEvent.getDetails().get(Details.CODE_ID);
- String code = oauth.getCurrentQuery().get(OAuth2Constants.CODE);
+ String code = new OAuthClient.AuthorizationEndpointResponse(oauth).getCode();
OAuthClient.AccessTokenResponse response = oauth.doAccessTokenRequest(code, "password");
Assert.assertEquals(200, response.getStatusCode());
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientManager.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientManager.java
index 6702ec5..6bc7151 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientManager.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/ClientManager.java
@@ -67,6 +67,20 @@ public class ClientManager {
clientResource.update(app);
}
+ public ClientManagerBuilder standardFlow(Boolean enable) {
+ ClientRepresentation app = clientResource.toRepresentation();
+ app.setStandardFlowEnabled(enable);
+ clientResource.update(app);
+ return this;
+ }
+
+ public ClientManagerBuilder implicitFlow(Boolean enable) {
+ ClientRepresentation app = clientResource.toRepresentation();
+ app.setImplicitFlowEnabled(enable);
+ clientResource.update(app);
+ return this;
+ }
+
public void fullScopeAllowed(boolean enable) {
ClientRepresentation app = clientResource.toRepresentation();
app.setFullScopeAllowed(enable);