keycloak-memoizeit
Changes
distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml 1(+1 -0)
distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-authz-client/main/module.xml 41(+41 -0)
services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java 14(+12 -2)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java 6(+3 -3)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java 19(+0 -19)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/OIDCAdvancedRequestParamsTest.java 166(+163 -3)
testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DefaultAuthzConfigAdapterTest.java 30(+30 -0)
testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8PhotozExampleAdapterTest.java 30(+30 -0)
Details
diff --git a/core/src/main/java/org/keycloak/util/TokenUtil.java b/core/src/main/java/org/keycloak/util/TokenUtil.java
index 6168019..f649b5e 100644
--- a/core/src/main/java/org/keycloak/util/TokenUtil.java
+++ b/core/src/main/java/org/keycloak/util/TokenUtil.java
@@ -69,6 +69,22 @@ public class TokenUtil {
}
+ public static boolean hasPrompt(String promptParam, String targetPrompt) {
+ if (promptParam == null || targetPrompt == null) {
+ return false;
+ }
+
+ String[] prompts = promptParam.split(" ");
+ for (String prompt : prompts) {
+ if (targetPrompt.equals(prompt)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+
/**
* Return refresh token or offline token
*
diff --git a/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml b/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml
index a418265..fb3bf41 100755
--- a/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml
+++ b/distribution/adapters/wf8-adapter/wf8-adapter-zip/assembly.xml
@@ -39,6 +39,7 @@
<include>org/keycloak/keycloak-wf8-subsystem/**</include>
<include>org/keycloak/keycloak-adapter-subsystem/**</include>
<include>org/keycloak/keycloak-servlet-oauth-client/**</include>
+ <include>org/keycloak/keycloak-authz-client/**</include>
</includes>
<excludes>
<exclude>**/*.war</exclude>
diff --git a/distribution/adapters/wf8-adapter/wf8-modules/build.xml b/distribution/adapters/wf8-adapter/wf8-modules/build.xml
index ef8f986..457e673 100755
--- a/distribution/adapters/wf8-adapter/wf8-modules/build.xml
+++ b/distribution/adapters/wf8-adapter/wf8-modules/build.xml
@@ -79,6 +79,11 @@
<maven-resource group="org.apache.httpcomponents" artifact="httpmime"/>
</module-def>
+ <!-- Authorization -->
+ <module-def name="org.keycloak.keycloak-authz-client">
+ <maven-resource group="org.keycloak" artifact="keycloak-authz-client"/>
+ </module-def>
+
</target>
<target name="clean-target">
diff --git a/distribution/adapters/wf8-adapter/wf8-modules/pom.xml b/distribution/adapters/wf8-adapter/wf8-modules/pom.xml
index 5dfabb2..4a40fa8 100755
--- a/distribution/adapters/wf8-adapter/wf8-modules/pom.xml
+++ b/distribution/adapters/wf8-adapter/wf8-modules/pom.xml
@@ -82,6 +82,12 @@
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
+
+ <!-- Authorization -->
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-authz-client</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml
index 1642eb3..da78bf3 100755
--- a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml
+++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml
@@ -34,6 +34,7 @@
<module name="org.keycloak.keycloak-adapter-spi"/>
<module name="org.keycloak.keycloak-core"/>
<module name="org.keycloak.keycloak-common"/>
+ <module name="org.keycloak.keycloak-authz-client"/>
</dependencies>
</module>
diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-authz-client/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-authz-client/main/module.xml
new file mode 100755
index 0000000..af2bf88
--- /dev/null
+++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-authz-client/main/module.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+
+<!--
+ ~ * 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.
+ -->
+
+<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-authz-client">
+ <resources>
+ <!-- Insert resources here -->
+ </resources>
+ <dependencies>
+ <module name="org.bouncycastle" />
+ <module name="javax.api"/>
+ <module name="javax.activation.api"/>
+ <module name="sun.jdk" optional="true" />
+ <module name="javax.ws.rs.api"/>
+ <module name="org.keycloak.keycloak-core"/>
+ <module name="org.keycloak.keycloak-common"/>
+ <module name="org.apache.httpcomponents" slot="4.3"/>
+ <module name="com.fasterxml.jackson.core.jackson-core"/>
+ <module name="com.fasterxml.jackson.core.jackson-annotations"/>
+ <module name="com.fasterxml.jackson.core.jackson-databind"/>
+ <module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
+ </dependencies>
+
+</module>
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
index dfe0b90..7df18bd 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/saml/v2/writers/BaseWriter.java
@@ -172,6 +172,8 @@ public class BaseWriter {
if (attributeValue != null) {
if (attributeValue instanceof String) {
writeStringAttributeValue((String) attributeValue);
+ } else if (attributeValue instanceof NameIDType) {
+ writeNameIDTypeAttributeValue((NameIDType) attributeValue);
} else
throw logger.writerUnsupportedAttributeValueError(attributeValue.getClass().getName());
}
@@ -179,6 +181,12 @@ public class BaseWriter {
}
}
+ public void writeNameIDTypeAttributeValue(NameIDType attributeValue) throws ProcessingException {
+ StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.ATTRIBUTE_VALUE.get(), ASSERTION_NSURI.get());
+ write((NameIDType)attributeValue, new QName(ASSERTION_NSURI.get(), JBossSAMLConstants.NAMEID.get(), ASSERTION_PREFIX));
+ StaxUtil.writeEndElement(writer);
+ }
+
public void writeStringAttributeValue(String attributeValue) throws ProcessingException {
StaxUtil.writeStartElement(writer, ASSERTION_PREFIX, JBossSAMLConstants.ATTRIBUTE_VALUE.get(), ASSERTION_NSURI.get());
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
index ca6d7e6..24d708a 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/CookieAuthenticator.java
@@ -28,6 +28,7 @@ import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.AuthenticationManager;
+import org.keycloak.util.TokenUtil;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -49,8 +50,8 @@ public class CookieAuthenticator implements Authenticator {
if (authResult == null) {
context.attempted();
} else {
- // Cookie re-authentication is skipped if authTime is too old.
- if (isAuthTimeExpired(authResult.getSession(), context.getClientSession())) {
+ // Cookie re-authentication is skipped if re-authentication is required
+ if (requireReauthentication(authResult.getSession(), context.getClientSession())) {
context.attempted();
} else {
ClientSessionModel clientSession = context.getClientSession();
@@ -83,6 +84,15 @@ public class CookieAuthenticator implements Authenticator {
}
+ protected boolean requireReauthentication(UserSessionModel userSession, ClientSessionModel clientSession) {
+ return isPromptLogin(clientSession) || isAuthTimeExpired(userSession, clientSession);
+ }
+
+ protected boolean isPromptLogin(ClientSessionModel clientSession) {
+ String prompt = clientSession.getNote(OIDCLoginProtocol.PROMPT_PARAM);
+ return TokenUtil.hasPrompt(prompt, OIDCLoginProtocol.PROMPT_VALUE_LOGIN);
+ }
+
protected boolean isAuthTimeExpired(UserSessionModel userSession, ClientSessionModel clientSession) {
String authTime = userSession.getNote(AuthenticationManager.AUTH_TIME);
String maxAge = clientSession.getNote(OIDCLoginProtocol.MAX_AGE_PARAM);
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 f754c3f..2092079 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
@@ -382,7 +382,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
this.event.event(EventType.LOGIN);
clientSession.setNote(Details.AUTH_TYPE, CODE_AUTH_TYPE);
- return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), prompt != null && prompt.equals("none"), false);
+ return handleBrowserAuthenticationRequest(clientSession, new OIDCLoginProtocol(session, realm, uriInfo, headers, event), TokenUtil.hasPrompt(prompt, OIDCLoginProtocol.PROMPT_VALUE_NONE), false);
}
private Response buildRegister() {
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 e6520db..39dc288 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocol.java
@@ -65,6 +65,11 @@ public class OIDCLoginProtocol implements LoginProtocol {
public static final String RESPONSE_MODE_PARAM = "response_mode";
+ public static final String PROMPT_VALUE_NONE = "none";
+ public static final String PROMPT_VALUE_LOGIN = "login";
+ public static final String PROMPT_VALUE_CONSENT = "consent";
+ public static final String PROMPT_VALUE_SELECT_ACCOUNT = "select_account";
+
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
protected KeycloakSession session;
diff --git a/services/src/test/java/org/keycloak/test/broker/saml/SAMLDataMarshallerTest.java b/services/src/test/java/org/keycloak/test/broker/saml/SAMLDataMarshallerTest.java
index 84354b9..9a68621 100755
--- a/services/src/test/java/org/keycloak/test/broker/saml/SAMLDataMarshallerTest.java
+++ b/services/src/test/java/org/keycloak/test/broker/saml/SAMLDataMarshallerTest.java
@@ -35,6 +35,8 @@ public class SAMLDataMarshallerTest {
private static final String TEST_ASSERTION = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">manager</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>";
+ private static final String TEST_ASSERTION_WITH_NAME_ID = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:persistent\">b2c6275838784dba219c92f53ea5493c8ef4da09</saml:NameID></saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>";
+
private static final String TEST_AUTHN_TYPE = "<saml:AuthnStatement xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement>";
@Test
@@ -68,6 +70,20 @@ public class SAMLDataMarshallerTest {
}
@Test
+ public void testParseAssertionWitNameId() throws Exception {
+ SAMLDataMarshaller serializer = new SAMLDataMarshaller();
+ AssertionType assertion = serializer.deserialize(TEST_ASSERTION_WITH_NAME_ID, AssertionType.class);
+
+ // test assertion
+ Assert.assertEquals(assertion.getID(), "ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9");
+ Assert.assertEquals(((NameIDType) assertion.getSubject().getSubType().getBaseID()).getValue(), "test-user");
+
+ // back to String
+ String serialized = serializer.serialize(assertion);
+ Assert.assertEquals(TEST_ASSERTION_WITH_NAME_ID, serialized);
+ }
+
+ @Test
public void testParseAuthnType() throws Exception {
SAMLDataMarshaller serializer = new SAMLDataMarshaller();
AuthnStatementType authnStatement = serializer.deserialize(TEST_AUTHN_TYPE, AuthnStatementType.class);
diff --git a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
index 84bcaf8..99c0245 100755
--- a/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
+++ b/testsuite/integration/src/test/resources/broker-test/test-realm-with-broker.json
@@ -178,7 +178,6 @@
"config": {
"clientId": "broker-app",
"clientSecret": "secret",
- "prompt": "login",
"authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/auth",
"tokenUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/token",
"userInfoUrl": "http://localhost:8082/auth/realms/realm-with-oidc-identity-provider/protocol/openid-connect/userinfo",
@@ -196,7 +195,6 @@
"config": {
"clientId": "broker-app",
"clientSecret": "secret",
- "prompt": "login",
"authorizationUrl": "http://localhost:8082/auth/realms/realm-with-oidc-idp-property-mappers/protocol/openid-connect/auth",
"tokenUrl": "http://localhost:8082/auth/realms/realm-with-oidc-idp-property-mappers/protocol/openid-connect/token",
"userInfoUrl": "http://localhost:8082/auth/realms/realm-with-oidc-idp-property-mappers/protocol/openid-connect/userinfo",
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
index b2a0354..32f23be 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/example/authorization/AbstractPhotozExampleAdapterTest.java
@@ -114,7 +114,7 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd
try {
this.deployer.deploy(RESOURCE_SERVER_ID);
this.clientPage.login("alice", "alice");
- this.clientPage.createAlbum("Alice Family Album");
+ this.clientPage.createAlbum("Alice-Family-Album");
this.clientPage.login("admin", "admin");
this.clientPage.navigateToAdminAlbum();
@@ -131,7 +131,7 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd
this.clientPage.login("admin", "admin");
this.clientPage.navigateToAdminAlbum();
- this.clientPage.deleteAlbum("Alice Family Album");
+ this.clientPage.deleteAlbum("Alice-Family-Album");
resources = getAuthorizationResource().resources().resources();
@@ -146,7 +146,7 @@ public abstract class AbstractPhotozExampleAdapterTest extends AbstractExampleAd
this.clientPage.login("admin", "admin");
this.clientPage.navigateToAdminAlbum();
- this.clientPage.deleteAlbum("Alice Family Album");
+ this.clientPage.deleteAlbum("Alice-Family-Album");
resources = getAuthorizationResource().resources().resources();
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
index f3ed5f6..accbd37 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTest.java
@@ -327,25 +327,6 @@ public class LoginTest extends TestRealmKeycloakTest {
events.expectLogin().user(userId).assertEvent();
}
- @Test
- public void loginPromptNone() {
- driver.navigate().to(oauth.getLoginFormUrl().toString() + "&prompt=none");
-
- assertFalse(loginPage.isCurrent());
- assertTrue(appPage.isCurrent());
-
- loginPage.open();
- loginPage.login("login-test", "password");
- Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
- events.expectLogin().user(userId).detail(Details.USERNAME, "login-test").assertEvent();
-
- driver.navigate().to(oauth.getLoginFormUrl().toString() + "&prompt=none");
- Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
-
- events.expectLogin().user(userId).removeDetail(Details.USERNAME).assertEvent();
- }
-
private void setPasswordPolicy(String policy) {
RealmRepresentation realmRep = adminClient.realm("test").toRepresentation();
realmRep.setPasswordPolicy(policy);
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 e6a72a0..bdc582c 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
@@ -19,23 +19,31 @@ package org.keycloak.testsuite.oidc;
import java.util.List;
+
+import org.jboss.arquillian.graphene.page.Page;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.keycloak.OAuth2Constants;
+import org.keycloak.OAuthErrorException;
import org.keycloak.common.util.Time;
import org.keycloak.events.Details;
+import org.keycloak.models.Constants;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
-import org.keycloak.testsuite.AbstractKeycloakTest;
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.ClientManager;
import org.keycloak.testsuite.util.OAuthClient;
-import org.keycloak.testsuite.util.RealmBuilder;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
/**
* Test for supporting advanced parameters of OIDC specs (max_age, nonce, prompt, ...)
@@ -47,6 +55,18 @@ public class OIDCAdvancedRequestParamsTest 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) {
@@ -71,6 +91,9 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
testRealms.add(realm);
}
+
+ // Max_age
+
@Test
public void testMaxAge1() {
// Open login form and login successfully
@@ -131,4 +154,141 @@ public class OIDCAdvancedRequestParamsTest extends TestRealmKeycloakTest {
Assert.assertEquals(authTime, authTimeUpdated);
}
+
+ // Prompt
+
+ @Test
+ public void promptNoneNotLogged() {
+ // Send request with prompt=none
+ driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=none");
+
+ assertFalse(loginPage.isCurrent());
+ assertTrue(appPage.isCurrent());
+
+ events.assertEmpty();
+
+ // Assert error response was sent because not logged in
+ OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ Assert.assertNull(resp.getCode());
+ Assert.assertEquals(OAuthErrorException.LOGIN_REQUIRED, resp.getError());
+
+
+ }
+
+ @Test
+ public void promptNoneSuccess() {
+ // Login user
+ loginPage.open();
+ 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);
+ int authTime = idToken.getAuthTime();
+
+ // Set time offset
+ setTimeOffset(10);
+
+ // Assert user still logged with previous authTime
+ driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=none");
+ Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+ loginEvent = events.expectLogin().removeDetail(Details.USERNAME).assertEvent();
+ idToken = sendTokenRequestAndGetIDToken(loginEvent);
+ int authTime2 = idToken.getAuthTime();
+
+ Assert.assertEquals(authTime, authTime2);
+ }
+
+
+ // Prompt=none with consent required for client
+ @Test
+ public void promptNoneConsentRequired() throws Exception {
+ // Require consent
+ ClientManager.realm(adminClient.realm("test")).clientId("test-app").consentRequired(true);
+
+ try {
+ // login to account mgmt.
+ profilePage.open();
+ assertTrue(loginPage.isCurrent());
+ loginPage.login("test-user@localhost", "password");
+ profilePage.assertCurrent();
+
+ events.expectLogin().client(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID)
+ .removeDetail(Details.REDIRECT_URI)
+ .detail(Details.USERNAME, "test-user@localhost").assertEvent();
+
+ // Assert error shown when trying prompt=none and consent not yet retrieved
+ driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=none");
+ assertTrue(appPage.isCurrent());
+ Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+ OAuthClient.AuthorizationCodeResponse resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ Assert.assertNull(resp.getCode());
+ Assert.assertEquals(OAuthErrorException.INTERACTION_REQUIRED, resp.getError());
+
+ // Confirm consent
+ driver.navigate().to(oauth.getLoginFormUrl());
+ grantPage.assertCurrent();
+ grantPage.accept();
+
+ events.expectLogin()
+ .detail(Details.USERNAME, "test-user@localhost")
+ .detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED)
+ .assertEvent();
+
+ // Consent not required anymore. Login with prompt=none should success
+ driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=none");
+ Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+ resp = new OAuthClient.AuthorizationCodeResponse(oauth);
+ Assert.assertNotNull(resp.getCode());
+ Assert.assertNull(resp.getError());
+
+ events.expectLogin()
+ .detail(Details.USERNAME, "test-user@localhost")
+ .detail(Details.CONSENT, Details.CONSENT_VALUE_PERSISTED_CONSENT)
+ .assertEvent();
+
+ } finally {
+ // revert require consent
+ ClientManager.realm(adminClient.realm("test")).clientId("test-app").consentRequired(false);
+ }
+ }
+
+
+ // prompt=login
+ @Test
+ public void promptLogin() {
+ // Login user
+ loginPage.open();
+ 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);
+ int authTime = idToken.getAuthTime();
+
+ // Set time offset
+ setTimeOffset(10);
+
+ // Assert need to re-authenticate with prompt=login
+ driver.navigate().to(oauth.getLoginFormUrl() + "&prompt=login");
+
+ loginPage.assertCurrent();
+ loginPage.login("test-user@localhost", "password");
+ Assert.assertEquals(AppPage.RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+ loginEvent = events.expectLogin().detail(Details.USERNAME, "test-user@localhost").assertEvent();
+ idToken = sendTokenRequestAndGetIDToken(loginEvent);
+ int authTimeUpdated = idToken.getAuthTime();
+
+ // Assert that authTime was updated
+ Assert.assertTrue(authTime + 10 <= authTimeUpdated);
+
+ }
+
+
+ // prompt=consent
+
}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DefaultAuthzConfigAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DefaultAuthzConfigAdapterTest.java
new file mode 100644
index 0000000..110c53e
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8DefaultAuthzConfigAdapterTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.adapter.example;
+
+import org.keycloak.testsuite.adapter.example.authorization.AbstractDefaultAuthzConfigAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-wildfly8")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class Wildfly8DefaultAuthzConfigAdapterTest extends AbstractDefaultAuthzConfigAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8PhotozExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8PhotozExampleAdapterTest.java
new file mode 100644
index 0000000..86f4e4f
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/example/Wildfly8PhotozExampleAdapterTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.adapter.example;
+
+import org.keycloak.testsuite.adapter.example.authorization.AbstractPhotozExampleAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-wildfly8")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class Wildfly8PhotozExampleAdapterTest extends AbstractPhotozExampleAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8DefaultAuthzConfigAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8DefaultAuthzConfigAdapterTest.java
new file mode 100644
index 0000000..a7f900b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8DefaultAuthzConfigAdapterTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.adapter.example;
+
+import org.keycloak.testsuite.adapter.example.authorization.AbstractDefaultAuthzConfigAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-tomcat8")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class Tomcat8DefaultAuthzConfigAdapterTest extends AbstractDefaultAuthzConfigAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8PhotozExampleAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8PhotozExampleAdapterTest.java
new file mode 100644
index 0000000..33349aa
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/src/test/java/org/keycloak/testsuite/adapter/example/Tomcat8PhotozExampleAdapterTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.adapter.example;
+
+import org.keycloak.testsuite.adapter.example.authorization.AbstractPhotozExampleAdapterTest;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-tomcat8")
+//@AdapterLibsLocationProperty("adapter.libs.wildfly")
+public class Tomcat8PhotozExampleAdapterTest extends AbstractPhotozExampleAdapterTest {
+
+}