Remove all adapter-core code moved to util (#30012)
* Remove all tests that are only executed for undertow app server * Remove installation steps for OIDC adapter in wildfly/eap app server * Remove the util adapters package except HttpClientBuilder * Remove HttpClientBuilder and use plain apache http client Closes #29912 Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
parent
f6f3b385c5
commit
0cd0d03c08
132 changed files with 72 additions and 13301 deletions
|
@ -377,59 +377,6 @@
|
|||
</configuration>
|
||||
</execution>
|
||||
|
||||
<execution>
|
||||
<!--OIDC: wf10, wf9-->
|
||||
<id>adapter-install-offline-standalone</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skip>${skip.adapter.offline.installation}</skip>
|
||||
<executable>${cli.executable}</executable>
|
||||
<workingDirectory>${cli.working.dir}</workingDirectory>
|
||||
<environmentVariables>
|
||||
<JAVA_HOME>${app.server.java.home}</JAVA_HOME>
|
||||
</environmentVariables>
|
||||
<arguments>
|
||||
<argument>${cli.jboss-cli.arg}</argument>
|
||||
<argument>--file=${app.server.jboss.home}/bin/adapter-install-offline.cli</argument>
|
||||
<!--
|
||||
following attribute is required just for windows
|
||||
see ${common.resources}/win/run-jboss-cli.bat
|
||||
!! the ordering is important, if you need to change it edit run-jboss-cli.bat !!
|
||||
-->
|
||||
<argument>${cli.win.working.dir}</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<!--OIDC: wf10, wf9-->
|
||||
<id>adapter-install-offline-standalone-ha</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<skip>${skip.adapter.offline.installation}</skip>
|
||||
<executable>${cli.executable}</executable>
|
||||
<workingDirectory>${cli.working.dir}</workingDirectory>
|
||||
<environmentVariables>
|
||||
<JAVA_HOME>${app.server.java.home}</JAVA_HOME>
|
||||
</environmentVariables>
|
||||
<arguments>
|
||||
<argument>${cli.jboss-cli.arg}</argument>
|
||||
<argument>--file=${app.server.jboss.home}/bin/adapter-install-offline.cli</argument>
|
||||
<!--
|
||||
following attribute is required just for windows
|
||||
see ${common.resources}/win/run-jboss-cli.bat
|
||||
!! the ordering is important, if you need to change it edit run-jboss-cli.bat !!
|
||||
-->
|
||||
<argument>${cli.win.working.dir}</argument>
|
||||
<argument>-Dserver.config=standalone-ha.xml</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<!--SAML: wf10, wf9-->
|
||||
<id>adapter-install-saml-offline-standalone</id>
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
You need to create a client in Keycloak. The configuration options when creating the client should be:
|
||||
|
||||
* Client ID: You choose
|
||||
* Access Type: confidential
|
||||
* Root URL: Root URL for where you're hosting the application (for example http://localhost:8080)
|
||||
* Valie Redirect URIs: /app-profile-jee/*
|
||||
* Base URL: /app-profile-jee/
|
||||
* Admin URL: /app-profile-jee/
|
||||
|
||||
Then, build the WAR with Maven and install as per the Adapter configuration for your server as described in the Keycloak documentation.
|
|
@ -1,56 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-test-apps</artifactId>
|
||||
<version>999.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>keycloak-test-app-profile-jee</artifactId>
|
||||
|
||||
<name>Keycloak Test App Profile JEE</name>
|
||||
<description/>
|
||||
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_4.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>app-profile-jee</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.wildfly.plugins</groupId>
|
||||
<artifactId>wildfly-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>false</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @author tags. All rights reserved.
|
||||
*
|
||||
* 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.quickstart.profilejee;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.constants.ServiceUrlConstants;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
/**
|
||||
* Controller simplifies access to the server environment from the JSP.
|
||||
*
|
||||
* @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
|
||||
*/
|
||||
public class Controller {
|
||||
|
||||
public void handleLogout(HttpServletRequest req) throws ServletException {
|
||||
if (req.getParameter("logout") != null) {
|
||||
req.logout();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLoggedIn(HttpServletRequest req) {
|
||||
return getSession(req) != null;
|
||||
}
|
||||
|
||||
public boolean showToken(HttpServletRequest req) {
|
||||
return req.getParameter("showToken") != null;
|
||||
}
|
||||
|
||||
public IDToken getIDToken(HttpServletRequest req) {
|
||||
return getSession(req).getIdToken();
|
||||
}
|
||||
|
||||
public String getAccountUri(HttpServletRequest req) {
|
||||
KeycloakSecurityContext session = getSession(req);
|
||||
String baseUrl = getAuthServerBaseUrl(req);
|
||||
String realm = session.getRealm();
|
||||
return KeycloakUriBuilder.fromUri(baseUrl).path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH)
|
||||
.queryParam("referrer", "app-profile-jee").build(realm).toString();
|
||||
|
||||
}
|
||||
|
||||
private String getAuthServerBaseUrl(HttpServletRequest req) {
|
||||
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) req.getServletContext().getAttribute(AdapterDeploymentContext.class.getName());
|
||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(null);
|
||||
return deployment.getAuthServerBaseUrl();
|
||||
}
|
||||
|
||||
public String getTokenString(HttpServletRequest req) throws IOException {
|
||||
return JsonSerialization.writeValueAsPrettyString(getIDToken(req));
|
||||
}
|
||||
|
||||
private KeycloakSecurityContext getSession(HttpServletRequest req) {
|
||||
return (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"realm": "Test",
|
||||
"auth-server-url": "/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "app-profile-jee",
|
||||
"credentials": {
|
||||
"secret": "4f36f31a-be9d-4f92-b982-425301bac5df"
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @author tags. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
-->
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>app-profile-jee</module-name>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Protected</web-resource-name>
|
||||
<url-pattern>/profile.jsp</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
|
||||
</web-app>
|
|
@ -1,47 +0,0 @@
|
|||
<%--
|
||||
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @author tags. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
--%>
|
||||
|
||||
<%@page contentType="text/html" pageEncoding="ISO-8859-1"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Keycloak Example App</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="styles.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<jsp:useBean id="controller" class="org.keycloak.quickstart.profilejee.Controller" scope="request"/>
|
||||
<% controller.handleLogout(request); %>
|
||||
|
||||
<c:set var="isLoggedIn" value="<%=controller.isLoggedIn(request)%>"/>
|
||||
<c:if test="${isLoggedIn}">
|
||||
<c:redirect url="profile.jsp"/>
|
||||
</c:if>
|
||||
|
||||
<div class="wrapper" id="welcome">
|
||||
<div class="menu">
|
||||
<button onclick="location.href = 'profile.jsp'" type="button">Login</button>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="message">Please login</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,79 +0,0 @@
|
|||
<%--
|
||||
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @author tags. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
--%>
|
||||
|
||||
<%@page contentType="text/html" pageEncoding="ISO-8859-1"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Keycloak Example App</title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<jsp:useBean id="controller" class="org.keycloak.quickstart.profilejee.Controller" scope="request"/>
|
||||
<c:set var="idToken" value="<%=controller.getIDToken(request)%>"/>
|
||||
<c:set var="tokenString" value="<%=controller.getTokenString(request)%>"/>
|
||||
<c:set var="accountUri" value="<%=controller.getAccountUri(request)%>"/>
|
||||
<c:set var="showToken" value="<%=controller.showToken(request)%>"/>
|
||||
|
||||
<div class="wrapper" id="profile">
|
||||
<div class="menu">
|
||||
<c:if test="${!showToken}">
|
||||
<button onclick="location.href = 'profile.jsp?showToken=true'">Token</button>
|
||||
</c:if>
|
||||
<c:if test="${showToken}">
|
||||
<button onclick="location.href = 'profile.jsp'">Profile</button>
|
||||
</c:if>
|
||||
<button onclick="location.href = 'index.jsp?logout=true'" type="button">Logout</button>
|
||||
<button onclick="location.href = '${accountUri}'" type="button">Account</button>
|
||||
</div>
|
||||
|
||||
<c:if test="${showToken}">
|
||||
<div class="content">
|
||||
<div id="token-content" class="message">${tokenString}</div>
|
||||
<!-- <script>document.write(JSON.stringify(JSON.parse('${tokenString}'), null, ' '));</script>-->
|
||||
</div>
|
||||
</c:if>
|
||||
|
||||
<c:if test="${!showToken}">
|
||||
<div class="content">
|
||||
<div id="profile-content" class="message">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td class="label">First name</td>
|
||||
<td><span id="firstName">${idToken.givenName}</span></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="label">Last name</td>
|
||||
<td><span id="lastName">${idToken.familyName}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label">Username</td>
|
||||
<td><span id="username">${idToken.preferredUsername}</span></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="label">Email</td>
|
||||
<td><span id="email">${idToken.email}</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</c:if>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,101 +0,0 @@
|
|||
|
||||
body {
|
||||
background-color: #333;
|
||||
font-family: sans-serif;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: sans-serif;
|
||||
font-size: 30px;
|
||||
width: 200px;
|
||||
|
||||
background-color: #0085cf;
|
||||
background-image: linear-gradient(to bottom, #00a8e1 0%, #0085cf 100%);
|
||||
background-repeat: repeat-x;
|
||||
|
||||
border: 2px solid #ccc;
|
||||
color: #fff;
|
||||
-webkit-border-radius: 30px;
|
||||
|
||||
text-transform: uppercase;
|
||||
|
||||
-webkit-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5);
|
||||
-moz-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5);
|
||||
box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #006ba6;
|
||||
background-image: none;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
background-color: #eee;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.menu {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
-webkit-border-radius: 10px;
|
||||
|
||||
-webkit-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5);
|
||||
-moz-box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5);
|
||||
box-shadow: 2px 2px 10px 0px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.content .message {
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 40px;
|
||||
-webkit-border-radius: 10px;
|
||||
}
|
||||
|
||||
#token .content .message {
|
||||
font-size: 20px;
|
||||
overflow: scroll;
|
||||
padding: 5px;
|
||||
white-space: pre;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #a21e22;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
tr.even {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
td.label {
|
||||
font-weight: bold;
|
||||
width: 250px;
|
||||
}
|
|
@ -21,7 +21,6 @@
|
|||
<module>servlet-policy-enforcer</module>
|
||||
<module>servlets</module>
|
||||
<module>servlets-jakarta</module>
|
||||
<module>app-profile-jee</module>
|
||||
<module>cors</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -19,18 +19,13 @@ package org.keycloak.testsuite.adapter.filter;
|
|||
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.rotation.JWKPublicKeyLocator;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.common.util.reflections.Reflections;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Filter to handle "special" requests to perform actions on adapter side (for example setting time offset )
|
||||
|
@ -40,7 +35,6 @@ import java.lang.reflect.Field;
|
|||
public class AdapterActionsFilter implements Filter {
|
||||
|
||||
public static final String TIME_OFFSET_PARAM = "timeOffset";
|
||||
public static final String RESET_DEPLOYMENT_PARAM = "resetDeployment";
|
||||
|
||||
private static final Logger log = Logger.getLogger(AdapterActionsFilter.class);
|
||||
|
||||
|
@ -56,28 +50,12 @@ public class AdapterActionsFilter implements Filter {
|
|||
|
||||
//Accept timeOffset as argument to enforce timeouts
|
||||
String timeOffsetParam = request.getParameter(TIME_OFFSET_PARAM);
|
||||
String resetDeploymentParam = request.getParameter(RESET_DEPLOYMENT_PARAM);
|
||||
|
||||
if (timeOffsetParam != null && !timeOffsetParam.isEmpty()) {
|
||||
int timeOffset = Integer.parseInt(timeOffsetParam);
|
||||
log.infof("Time offset updated to %d for application %s", timeOffset, servletReq.getRequestURI());
|
||||
Time.setOffset(timeOffset);
|
||||
writeResponse(servletResp, "Offset set successfully");
|
||||
} else if (resetDeploymentParam != null && !resetDeploymentParam.isEmpty()) {
|
||||
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getServletContext().getAttribute(AdapterDeploymentContext.class.getName());
|
||||
|
||||
Field field = Reflections.findDeclaredField(AdapterDeploymentContext.class, "deployment");
|
||||
Reflections.setAccessible(field);
|
||||
KeycloakDeployment deployment = (KeycloakDeployment) Reflections.getFieldValue(field, deploymentContext);
|
||||
|
||||
Time.setOffset(0);
|
||||
deployment.setNotBefore(0);
|
||||
if (deployment.getPublicKeyLocator() instanceof JWKPublicKeyLocator) {
|
||||
deployment.setPublicKeyLocator(new JWKPublicKeyLocator());
|
||||
}
|
||||
|
||||
log.infof("Restarted PublicKeyLocator, notBefore and timeOffset for application %s", servletReq.getRequestURI());
|
||||
writeResponse(servletResp, "Restarted PublicKeyLocator, notBefore and timeOffset successfully");
|
||||
} else {
|
||||
// Continue request
|
||||
chain.doFilter(request, response);
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.JWSInputException;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public abstract class AbstractShowTokensServlet extends HttpServlet {
|
||||
|
||||
private static final String LINK = "<a href=\"%s\" id=\"%s\">%s</a>";
|
||||
|
||||
protected String renderTokens(HttpServletRequest req) throws ServletException, IOException {
|
||||
RefreshableKeycloakSecurityContext ctx = (RefreshableKeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
String accessTokenPretty = JsonSerialization.writeValueAsPrettyString(ctx.getToken());
|
||||
RefreshToken refreshToken;
|
||||
try {
|
||||
refreshToken = new JWSInput(ctx.getRefreshToken()).readJsonContent(RefreshToken.class);
|
||||
} catch (JWSInputException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
String refreshTokenPretty = JsonSerialization.writeValueAsPrettyString(refreshToken);
|
||||
|
||||
return new StringBuilder("<span id=\"accessToken\">" + accessTokenPretty + "</span>")
|
||||
.append("<span id=\"refreshToken\">" + refreshTokenPretty + "</span>")
|
||||
.append("<span id=\"accessTokenString\">" + ctx.getTokenString() + "</span>")
|
||||
.append("<span id=\"refreshTokenString\">" + ctx.getRefreshToken() + "</span>")
|
||||
.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,193 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.junit.Assert;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.HttpClientBuilder;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.util.BasicAuthHelper;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@WebServlet("/exchange-linking")
|
||||
public class LinkAndExchangeServlet extends HttpServlet {
|
||||
|
||||
private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException{
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean first = true;
|
||||
for(Map.Entry<String, String> entry : params.entrySet()){
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
result.append("&");
|
||||
|
||||
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
|
||||
result.append("=");
|
||||
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public AccessTokenResponse doTokenExchange(String realm, String token, String requestedIssuer,
|
||||
String clientId, String clientSecret) throws Exception {
|
||||
|
||||
try (CloseableHttpClient client = (CloseableHttpClient) new HttpClientBuilder().disableTrustManager().build()) {
|
||||
String exchangeUrl = KeycloakUriBuilder.fromUri(ServletTestUtils.getAuthServerUrlBase())
|
||||
.path("/auth/realms/{realm}/protocol/openid-connect/token").build(realm).toString();
|
||||
|
||||
HttpPost post = new HttpPost(exchangeUrl);
|
||||
HashMap<String, String> parameters = new HashMap<>();
|
||||
|
||||
if (clientSecret != null) {
|
||||
String authorization = BasicAuthHelper.createHeader(clientId, clientSecret);
|
||||
post.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED.toString());
|
||||
post.setHeader(HttpHeaders.AUTHORIZATION, authorization);
|
||||
} else {
|
||||
parameters.put("client_id", clientId);
|
||||
}
|
||||
|
||||
parameters.put(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE);
|
||||
parameters.put(OAuth2Constants.SUBJECT_TOKEN, token);
|
||||
parameters.put(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
|
||||
parameters.put(OAuth2Constants.REQUESTED_ISSUER, requestedIssuer);
|
||||
|
||||
post.setEntity(new StringEntity(getPostDataString(parameters)));
|
||||
HttpResponse response = client.execute(post);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
|
||||
if (statusCode == 200 || statusCode == 400) {
|
||||
return JsonSerialization.readValue(EntityUtils.toString(response.getEntity()), AccessTokenResponse.class);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown error!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.setHeader("Cache-Control", "no-cache");
|
||||
if (request.getRequestURI().endsWith("/link") && request.getParameter("response") == null) {
|
||||
String provider = request.getParameter("provider");
|
||||
String realm = request.getParameter("realm");
|
||||
KeycloakSecurityContext session = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
AccessToken token = session.getToken();
|
||||
String tokenString = session.getTokenString();
|
||||
|
||||
String clientId = token.getIssuedFor();
|
||||
String linkUrl = null;
|
||||
try {
|
||||
AccessTokenResponse response = doTokenExchange(realm, tokenString, provider, clientId, "password");
|
||||
String error = response.getError();
|
||||
if (error != null) {
|
||||
System.out.println("*** error : " + error);
|
||||
System.out.println("*** link-url: " + response.getOtherClaims().get("account-link-url"));
|
||||
linkUrl = (String)response.getOtherClaims().get("account-link-url");
|
||||
} else {
|
||||
Assert.assertNotNull(response.getToken());
|
||||
resp.setStatus(200);
|
||||
resp.setContentType("text/html");
|
||||
PrintWriter pw = resp.getWriter();
|
||||
pw.printf("<html><head><title>%s</title></head><body>", "Client Linking");
|
||||
pw.println("Account Linked");
|
||||
pw.print("</body></html>");
|
||||
pw.flush();
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String redirectUri = KeycloakUriBuilder.fromUri(request.getRequestURL().toString())
|
||||
.replaceQuery(null)
|
||||
.queryParam("response", "true")
|
||||
.queryParam("realm", realm)
|
||||
.queryParam("provider", provider).build().toString();
|
||||
String accountLinkUrl = KeycloakUriBuilder.fromUri(linkUrl)
|
||||
.queryParam("redirect_uri", redirectUri).build().toString();
|
||||
resp.setStatus(302);
|
||||
resp.setHeader("Location", accountLinkUrl);
|
||||
} else if (request.getRequestURI().endsWith("/link") && request.getParameter("response") != null) {
|
||||
resp.setStatus(200);
|
||||
resp.setContentType("text/html");
|
||||
PrintWriter pw = resp.getWriter();
|
||||
pw.printf("<html><head><title>%s</title></head><body>", "Client Linking");
|
||||
String error = request.getParameter("link_error");
|
||||
if (error != null) {
|
||||
pw.println("Link error: " + error);
|
||||
} else {
|
||||
pw.println("Account Linked");
|
||||
}
|
||||
pw.println("trying exchange");
|
||||
try {
|
||||
String provider = request.getParameter("provider");
|
||||
String realm = request.getParameter("realm");
|
||||
KeycloakSecurityContext session = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
AccessToken token = session.getToken();
|
||||
String clientId = token.getIssuedFor();
|
||||
String tokenString = session.getTokenString();
|
||||
AccessTokenResponse response = doTokenExchange(realm, tokenString, provider, clientId, "password");
|
||||
error = (String)response.getOtherClaims().get("error");
|
||||
if (error == null) {
|
||||
if (response.getToken() != null) pw.println("Exchange token received");
|
||||
} else {
|
||||
pw.print("Error with exchange: " + error);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
pw.print("</body></html>");
|
||||
pw.flush();
|
||||
} else {
|
||||
resp.setStatus(200);
|
||||
resp.setContentType("text/html");
|
||||
PrintWriter pw = resp.getWriter();
|
||||
pw.printf("<html><head><title>%s</title></head><body>", "Client Linking");
|
||||
pw.println("Unknown request: " + request.getRequestURL().toString());
|
||||
pw.print("</body></html>");
|
||||
pw.flush();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Juraci Paixão Kröhling <juraci at kroehling.de>
|
||||
*/
|
||||
public class MultiTenantResolver implements KeycloakConfigResolver {
|
||||
|
||||
@Override
|
||||
public KeycloakDeployment resolve(HttpFacade.Request request) {
|
||||
|
||||
String path = request.getURI();
|
||||
int multitenantIndex = path.indexOf("multi-tenant/");
|
||||
if (multitenantIndex == -1) {
|
||||
throw new IllegalStateException("Not able to resolve realm from the request path!");
|
||||
}
|
||||
|
||||
String realm = path.substring(path.indexOf("multi-tenant/")).split("/")[1];
|
||||
if (realm.contains("?")) {
|
||||
realm = realm.split("\\?")[0];
|
||||
}
|
||||
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("/" + realm + "-keycloak.json");
|
||||
|
||||
if (is == null) {
|
||||
throw new IllegalStateException("Not able to find the file /" + realm + "-keycloak.json");
|
||||
}
|
||||
|
||||
KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(is);
|
||||
return deployment;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package org.keycloak.testsuite.adapter.servlet;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class OfflineTokenServlet extends AbstractShowTokensServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
|
||||
if (req.getRequestURI().endsWith("logout")) {
|
||||
|
||||
UriBuilder redirectUriBuilder = UriBuilder.fromUri(ServletTestUtils.getUrlBase() + "/offline-client");
|
||||
if (req.getParameter(OAuth2Constants.SCOPE) != null) {
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, req.getParameter(OAuth2Constants.SCOPE));
|
||||
}
|
||||
String redirectUri = redirectUriBuilder.build().toString();
|
||||
|
||||
String serverLogoutRedirect = UriBuilder.fromUri(ServletTestUtils.getAuthServerUrlBase() + "/auth/realms/test/protocol/openid-connect/logout")
|
||||
.queryParam("redirect_uri", redirectUri)
|
||||
.build().toString();
|
||||
|
||||
resp.sendRedirect(serverLogoutRedirect);
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder response = new StringBuilder("<html><head><title>Offline token servlet</title></head><body><pre>");
|
||||
|
||||
String tokens = renderTokens(req);
|
||||
response = response.append(tokens);
|
||||
|
||||
response.append("</pre></body></html>");
|
||||
resp.getWriter().println(response.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* @author mhajas
|
||||
*/
|
||||
@WebServlet("/serialization-servlet")
|
||||
public class SerializationServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
PrintWriter pw = resp.getWriter();
|
||||
// Serialize
|
||||
ByteArrayOutputStream bso = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bso);
|
||||
oos.writeObject(req.getUserPrincipal());
|
||||
oos.close();
|
||||
|
||||
// Deserialize
|
||||
byte[] bytes = bso.toByteArray();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
ObjectInputStream ois = new ObjectInputStream(bis) {
|
||||
@Override
|
||||
public Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
return Class.forName(desc.getName(), true, SerializationServlet.class.getClassLoader());
|
||||
} catch (Exception e) { }
|
||||
|
||||
// Fall back (e.g. for primClasses)
|
||||
return super.resolveClass(desc);
|
||||
}
|
||||
};
|
||||
|
||||
KeycloakPrincipal principal;
|
||||
try {
|
||||
principal = (KeycloakPrincipal) ois.readObject();
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
pw.write("Deserialization failed");
|
||||
return;
|
||||
}
|
||||
|
||||
KeycloakSecurityContext ctx = principal.getKeycloakSecurityContext();
|
||||
if (!(ctx instanceof RefreshableKeycloakSecurityContext)) {
|
||||
pw.write("Context was not instance of RefreshableKeycloakSecurityContext");
|
||||
}
|
||||
|
||||
pw.write("Serialization/Deserialization was successful");
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class TokenMinTTLServlet extends AbstractShowTokensServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
StringBuilder response = new StringBuilder("<html><head><title>Token Min TTL Servlet</title></head><body><pre>");
|
||||
|
||||
String tokens = renderTokens(req);
|
||||
response = response.append(tokens);
|
||||
|
||||
response.append("</pre></body></html>");
|
||||
resp.getWriter().println(response.toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,18 +1,24 @@
|
|||
package org.keycloak.testsuite.util;
|
||||
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.WebTarget;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Enumeration;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.keycloak.common.util.Base64Url;
|
||||
|
@ -66,7 +72,7 @@ public class MutualTLSUtils {
|
|||
try {
|
||||
keystore = KeystoreUtil.loadKeyStore(keyStorePath, keyStorePassword);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,20 +82,33 @@ public class MutualTLSUtils {
|
|||
try {
|
||||
truststore = KeystoreUtil.loadKeyStore(trustStorePath, trustStorePassword);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (keystore != null || truststore != null)
|
||||
return (CloseableHttpClient) new org.keycloak.adapters.HttpClientBuilder()
|
||||
.keyStore(keystore, keyStorePassword)
|
||||
.trustStore(truststore)
|
||||
.hostnameVerification(org.keycloak.adapters.HttpClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
.build();
|
||||
if (keystore != null || truststore != null) {
|
||||
return newCloseableHttpClientSSL(keystore, keyStorePassword, truststore);
|
||||
}
|
||||
|
||||
return HttpClientBuilder.create().build();
|
||||
}
|
||||
|
||||
public static CloseableHttpClient newCloseableHttpClientSSL(KeyStore keystore, String keyStorePassword, KeyStore truststore) {
|
||||
try {
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmfactory.init(keystore, keyStorePassword.toCharArray());
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(truststore);
|
||||
sslContext.init(kmfactory.getKeyManagers(), tmf.getTrustManagers(), null);
|
||||
SSLConnectionSocketFactory sf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
|
||||
|
||||
return HttpClientBuilder.create().setSSLSocketFactory(sf).build();
|
||||
} catch (NoSuchAlgorithmException|KeyStoreException|KeyManagementException|UnrecoverableKeyException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getThumbprintFromDefaultClientCert() throws KeyStoreException, CertificateEncodingException {
|
||||
return getThumbprintFromClientCert(DEFAULT_KEYSTOREPATH, DEFAULT_KEYSTOREPASSWORD);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ import org.keycloak.OAuth2Constants;
|
|||
import org.keycloak.TokenVerifier;
|
||||
import org.keycloak.broker.provider.util.SimpleHttp;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.common.util.KeystoreUtil;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
import org.keycloak.crypto.Algorithm;
|
||||
import org.keycloak.crypto.AsymmetricSignatureSignerContext;
|
||||
|
@ -92,7 +91,6 @@ import java.net.URISyntaxException;
|
|||
import java.net.URLEncoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Collections;
|
||||
|
@ -441,26 +439,7 @@ public class OAuthClient {
|
|||
|
||||
public static CloseableHttpClient newCloseableHttpClientSSL(String keyStorePath,
|
||||
String keyStorePassword, String trustStorePath, String trustStorePassword) {
|
||||
KeyStore keystore = null;
|
||||
// load the keystore containing the client certificate - keystore type is probably jks or pkcs12
|
||||
try {
|
||||
keystore = KeystoreUtil.loadKeyStore(keyStorePath, keyStorePassword);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// load the truststore
|
||||
KeyStore truststore = null;
|
||||
try {
|
||||
truststore = KeystoreUtil.loadKeyStore(trustStorePath, trustStorePassword);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return (CloseableHttpClient) new org.keycloak.adapters.HttpClientBuilder()
|
||||
.keyStore(keystore, keyStorePassword)
|
||||
.trustStore(truststore)
|
||||
.hostnameVerification(org.keycloak.adapters.HttpClientBuilder.HostnameVerificationPolicy.ANY)
|
||||
.build();
|
||||
return MutualTLSUtils.newCloseableHttpClient(keyStorePath, keyStorePassword, trustStorePath, trustStorePassword);
|
||||
}
|
||||
|
||||
public CloseableHttpResponse doPreflightRequest() {
|
||||
|
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.authz.example;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployer;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.junit.BeforeClass;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceServerRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.UserPolicyRepresentation;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||
import org.keycloak.testsuite.pages.InfoPage;
|
||||
import org.keycloak.testsuite.pages.LogoutConfirmPage;
|
||||
import org.keycloak.testsuite.util.UIUtils;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.keycloak.common.Profile.Feature.AUTHORIZATION;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadJson;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public abstract class AbstractBaseServletAuthzAdapterTest extends AbstractExampleAdapterTest {
|
||||
|
||||
protected static final String REALM_NAME = "servlet-authz";
|
||||
protected static final String RESOURCE_SERVER_ID = "servlet-authz-app";
|
||||
|
||||
@ArquillianResource
|
||||
private Deployer deployer;
|
||||
|
||||
@Page
|
||||
protected LogoutConfirmPage logoutConfirmPage;
|
||||
|
||||
@Page
|
||||
protected InfoPage infoPage;
|
||||
|
||||
@BeforeClass
|
||||
public static void enabled() {
|
||||
ProfileAssume.assumeFeatureEnabled(AUTHORIZATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(
|
||||
loadRealm(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/servlet-authz-realm.json")));
|
||||
}
|
||||
|
||||
protected void performTests(ExceptionRunnable assertion) {
|
||||
performTests(() -> importResourceServerSettings(), assertion);
|
||||
}
|
||||
|
||||
protected void performTests(ExceptionRunnable beforeDeploy, ExceptionRunnable assertion) {
|
||||
try {
|
||||
beforeDeploy.run();
|
||||
deployer.deploy(RESOURCE_SERVER_ID);
|
||||
assertion.run();
|
||||
} catch (FileNotFoundException cause) {
|
||||
throw new RuntimeException("Failed to import authorization settings", cause);
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Error while executing tests", cause);
|
||||
} finally {
|
||||
deployer.undeploy(RESOURCE_SERVER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean hasLink(String text) {
|
||||
return getLink(text) != null;
|
||||
}
|
||||
|
||||
protected boolean hasText(String text) {
|
||||
return this.driver.getPageSource().contains(text);
|
||||
}
|
||||
|
||||
protected WebElement getLink(String text) {
|
||||
return this.driver.findElement(By.xpath("//a[text() = '" + text + "']"));
|
||||
}
|
||||
|
||||
protected void importResourceServerSettings() throws FileNotFoundException {
|
||||
getAuthorizationResource().importSettings(loadJson(new FileInputStream(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/servlet-authz-app-authz-service.json")), ResourceServerRepresentation.class));
|
||||
}
|
||||
|
||||
protected AuthorizationResource getAuthorizationResource() {
|
||||
return getClientResource(RESOURCE_SERVER_ID).authorization();
|
||||
}
|
||||
|
||||
protected ClientResource getClientResource(String clientId) {
|
||||
ClientsResource clients = this.realmsResouce().realm(REALM_NAME).clients();
|
||||
ClientRepresentation resourceServer = clients.findByClientId(clientId).get(0);
|
||||
return clients.get(resourceServer.getId());
|
||||
}
|
||||
|
||||
private void logOut() {
|
||||
navigateTo();
|
||||
UIUtils.clickLink(driver.findElement(By.xpath("//a[text() = 'Sign Out']")));
|
||||
|
||||
logoutConfirmPage.assertCurrent();
|
||||
logoutConfirmPage.confirmLogout();
|
||||
infoPage.assertCurrent();
|
||||
}
|
||||
|
||||
|
||||
protected void login(String username, String password) {
|
||||
try {
|
||||
navigateTo();
|
||||
if (this.driver.getCurrentUrl().startsWith(getResourceServerUrl().toString())) {
|
||||
logOut();
|
||||
navigateTo();
|
||||
}
|
||||
|
||||
this.loginPage.form().login(username, password);
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Login failed", cause);
|
||||
}
|
||||
}
|
||||
|
||||
protected void navigateTo() {
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/");
|
||||
waitForPageToLoad();
|
||||
}
|
||||
|
||||
protected void assertWasDenied() {
|
||||
waitUntilElement(By.tagName("body")).text().contains("You can not access this resource.");
|
||||
}
|
||||
|
||||
protected void assertWasNotDenied() {
|
||||
waitUntilElement(By.tagName("body")).text().not().contains("You can not access this resource.");
|
||||
}
|
||||
|
||||
protected URL getResourceServerUrl() {
|
||||
try {
|
||||
return new URL(this.appServerContextRootPage + "/" + RESOURCE_SERVER_ID);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException("Could not obtain resource server url.", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void navigateToDynamicMenuPage() {
|
||||
navigateTo();
|
||||
UIUtils.clickLink(getLink("Dynamic Menu"));
|
||||
}
|
||||
|
||||
protected void navigateToUserPremiumPage() {
|
||||
navigateTo();
|
||||
UIUtils.clickLink(getLink("User Premium"));
|
||||
}
|
||||
|
||||
protected void navigateToAdminPage() {
|
||||
navigateTo();
|
||||
UIUtils.clickLink(getLink("Administration"));
|
||||
}
|
||||
|
||||
protected void updatePermissionPolicies(String permissionName, String... policyNames) {
|
||||
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
|
||||
if (permissionName.equalsIgnoreCase(policy.getName())) {
|
||||
StringBuilder policies = new StringBuilder("[");
|
||||
|
||||
for (String policyName : policyNames) {
|
||||
if (policies.length() > 1) {
|
||||
policies.append(",");
|
||||
}
|
||||
policies.append("\"").append(policyName).append("\"");
|
||||
|
||||
}
|
||||
|
||||
policies.append("]");
|
||||
|
||||
policy.getConfig().put("applyPolicies", policies.toString());
|
||||
getAuthorizationResource().policies().policy(policy.getId()).update(policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void createUserPolicy(String name, String... userNames) {
|
||||
UserPolicyRepresentation policy = new UserPolicyRepresentation();
|
||||
|
||||
policy.setName(name);
|
||||
|
||||
for (String userName : userNames) {
|
||||
policy.addUser(userName);
|
||||
}
|
||||
|
||||
assertFalse(policy.getUsers().isEmpty());
|
||||
|
||||
Response response = getAuthorizationResource().policies().user().create(policy);
|
||||
response.close();
|
||||
}
|
||||
|
||||
protected interface ExceptionRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
}
|
|
@ -1,371 +0,0 @@
|
|||
/*
|
||||
* 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.authz.example;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.ClientPoliciesResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.admin.client.resource.ResourcesResource;
|
||||
import org.keycloak.admin.client.resource.RolePoliciesResource;
|
||||
import org.keycloak.admin.client.resource.RoleScopeResource;
|
||||
import org.keycloak.admin.client.resource.RolesResource;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.admin.client.resource.UsersResource;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.RolePolicyRepresentation;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public abstract class AbstractServletAuthzAdapterTest extends AbstractBaseServletAuthzAdapterTest {
|
||||
|
||||
@Test
|
||||
public void testCanNotAccessWhenEnforcing() throws Exception {
|
||||
performTests(() -> {
|
||||
importResourceServerSettings();
|
||||
ResourcesResource resources = getAuthorizationResource().resources();
|
||||
ResourceRepresentation resource = resources.findByName("Protected Resource").get(0);
|
||||
|
||||
resource.setUri("/index.jsp");
|
||||
|
||||
resources.resource(resource.getId()).update(resource);
|
||||
}, () -> {
|
||||
login("jdoe", "jdoe");
|
||||
driver.navigate().to(getResourceServerUrl().toString() + "/enforcing/resource");
|
||||
assertWasDenied();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegularUserPermissions() throws Exception {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
assertTrue(hasLink("User Premium"));
|
||||
assertTrue(hasLink("Administration"));
|
||||
assertTrue(hasText("urn:servlet-authz:page:main:actionForUser"));
|
||||
assertFalse(hasText("urn:servlet-authz:page:main:actionForAdmin"));
|
||||
assertFalse(hasText("urn:servlet-authz:page:main:actionForPremiumUser"));
|
||||
|
||||
navigateToDynamicMenuPage();
|
||||
assertTrue(hasText("Do user thing"));
|
||||
assertFalse(hasText("Do user premium thing"));
|
||||
assertFalse(hasText("Do administration thing"));
|
||||
|
||||
navigateToUserPremiumPage();
|
||||
assertWasDenied();
|
||||
|
||||
navigateToAdminPage();
|
||||
assertWasDenied();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserPremiumPermissions() throws Exception {
|
||||
performTests(() -> {
|
||||
login("jdoe", "jdoe");
|
||||
assertWasNotDenied();
|
||||
assertTrue(hasLink("User Premium"));
|
||||
assertTrue(hasLink("Administration"));
|
||||
assertTrue(hasText("urn:servlet-authz:page:main:actionForUser"));
|
||||
assertTrue(hasText("urn:servlet-authz:page:main:actionForPremiumUser"));
|
||||
assertFalse(hasText("urn:servlet-authz:page:main:actionForAdmin"));
|
||||
|
||||
navigateToDynamicMenuPage();
|
||||
assertTrue(hasText("Do user thing"));
|
||||
assertTrue(hasText("Do user premium thing"));
|
||||
assertFalse(hasText("Do administration thing"));
|
||||
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
|
||||
navigateToAdminPage();
|
||||
assertWasDenied();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdminPermissions() throws Exception {
|
||||
performTests(() -> {
|
||||
login("admin", "admin");
|
||||
assertWasNotDenied();
|
||||
assertTrue(hasLink("User Premium"));
|
||||
assertTrue(hasLink("Administration"));
|
||||
assertTrue(hasText("urn:servlet-authz:page:main:actionForUser"));
|
||||
assertTrue(hasText("urn:servlet-authz:page:main:actionForAdmin"));
|
||||
assertFalse(hasText("urn:servlet-authz:page:main:actionForPremiumUser"));
|
||||
|
||||
navigateToDynamicMenuPage();
|
||||
assertTrue(hasText("Do user thing"));
|
||||
assertTrue(hasText("Do administration thing"));
|
||||
assertFalse(hasText("Do user premium thing"));
|
||||
|
||||
navigateToUserPremiumPage();
|
||||
assertWasDenied();
|
||||
|
||||
navigateToAdminPage();
|
||||
assertWasNotDenied();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGrantPremiumAccessToUser() throws Exception {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
navigateToUserPremiumPage();
|
||||
assertWasDenied();
|
||||
|
||||
updatePermissionPolicies("Premium Resource Permission", "Any User Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
|
||||
updatePermissionPolicies("Premium Resource Permission", "Only Premium User Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
|
||||
navigateToUserPremiumPage();
|
||||
assertWasDenied();
|
||||
|
||||
createUserPolicy("Temporary Premium Access Policy", "alice");
|
||||
|
||||
updatePermissionPolicies("Premium Resource Permission", "Temporary Premium Access Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGrantAdministrativePermissions() throws Exception {
|
||||
performTests(() -> {
|
||||
login("jdoe", "jdoe");
|
||||
|
||||
navigateToAdminPage();
|
||||
assertWasDenied();
|
||||
|
||||
RealmResource realmResource = realmsResouce().realm(REALM_NAME);
|
||||
UsersResource usersResource = realmResource.users();
|
||||
List<UserRepresentation> users = usersResource.search("jdoe", null, null, null, null, null);
|
||||
|
||||
assertFalse(users.isEmpty());
|
||||
|
||||
UserResource userResource = usersResource.get(users.get(0).getId());
|
||||
|
||||
RoleRepresentation adminRole = realmResource.roles().get("admin").toRepresentation();
|
||||
userResource.roles().realmLevel().add(Arrays.asList(adminRole));
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
|
||||
navigateToAdminPage();
|
||||
assertWasNotDenied();
|
||||
});
|
||||
}
|
||||
|
||||
//KEYCLOAK-3830
|
||||
@Test
|
||||
@Ignore // Ignored because: KEYCLOAK-7941
|
||||
public void testAccessPublicResource() throws Exception {
|
||||
performTests(() -> {
|
||||
driver.navigate().to(getResourceServerUrl() + "/public-html.html");
|
||||
WaitUtils.waitForPageToLoad();
|
||||
assertTrue(hasText("This is public resource that should be accessible without login."));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequiredRole() throws Exception {
|
||||
performTests(() -> {
|
||||
login("jdoe", "jdoe");
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
|
||||
RolesResource rolesResource = getClientResource(RESOURCE_SERVER_ID).roles();
|
||||
|
||||
rolesResource.create(new RoleRepresentation("required-role", "", false));
|
||||
|
||||
RolePolicyRepresentation policy = new RolePolicyRepresentation();
|
||||
|
||||
policy.setName("Required Role Policy");
|
||||
policy.addRole("user_premium", false);
|
||||
policy.addRole(RESOURCE_SERVER_ID + "/required-role", false);
|
||||
|
||||
RolePoliciesResource rolePolicy = getAuthorizationResource().policies().role();
|
||||
|
||||
rolePolicy.create(policy);
|
||||
policy = rolePolicy.findByName(policy.getName());
|
||||
|
||||
updatePermissionPolicies("Premium Resource Permission", policy.getName());
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
|
||||
policy.getRoles().clear();
|
||||
policy.addRole("user_premium", false);
|
||||
policy.addRole(RESOURCE_SERVER_ID + "/required-role", true);
|
||||
|
||||
rolePolicy.findById(policy.getId()).update(policy);
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
navigateToUserPremiumPage();
|
||||
assertWasDenied();
|
||||
|
||||
UsersResource users = realmsResouce().realm(REALM_NAME).users();
|
||||
UserRepresentation user = users.search("jdoe").get(0);
|
||||
|
||||
RoleScopeResource roleScopeResource = users.get(user.getId()).roles().clientLevel(getClientResource(RESOURCE_SERVER_ID).toRepresentation().getId());
|
||||
RoleRepresentation requiredRole = rolesResource.get("required-role").toRepresentation();
|
||||
roleScopeResource.add(Arrays.asList(requiredRole));
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
|
||||
policy.getRoles().clear();
|
||||
policy.addRole("user_premium", false);
|
||||
policy.addRole(RESOURCE_SERVER_ID + "/required-role", false);
|
||||
|
||||
rolePolicy.findById(policy.getId()).update(policy);
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
|
||||
roleScopeResource.remove(Arrays.asList(requiredRole));
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
navigateToUserPremiumPage();
|
||||
assertWasNotDenied();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlySpecificClient() throws Exception {
|
||||
performTests(() -> {
|
||||
login("jdoe", "jdoe");
|
||||
assertWasNotDenied();
|
||||
|
||||
ClientPolicyRepresentation policy = new ClientPolicyRepresentation();
|
||||
|
||||
policy.setName("Only Client Policy");
|
||||
policy.addClient("admin-cli");
|
||||
|
||||
ClientPoliciesResource policyResource = getAuthorizationResource().policies().client();
|
||||
Response response = policyResource.create(policy);
|
||||
response.close();
|
||||
policy = policyResource.findByName(policy.getName());
|
||||
|
||||
updatePermissionPolicies("Protected Resource Permission", policy.getName());
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
assertWasDenied();
|
||||
|
||||
policy.addClient("servlet-authz-app");
|
||||
policyResource.findById(policy.getId()).update(policy);
|
||||
|
||||
login("jdoe", "jdoe");
|
||||
assertWasNotDenied();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessResourceWithAnyScope() throws Exception {
|
||||
performTests(() -> {
|
||||
login("jdoe", "jdoe");
|
||||
driver.navigate().to(getResourceServerUrl() + "/protected/scopes.jsp");
|
||||
WaitUtils.waitForPageToLoad();
|
||||
assertTrue(hasText("Granted"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleURLsForResourceRealmConfig() throws Exception {
|
||||
performTests(() -> {
|
||||
login("jdoe", "jdoe");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource1/index1.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource1 index1.jsp");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource1/index2.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource1 index2.jsp");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/pattern1/page.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource2/pattern1");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/pattern2/page.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource2/pattern2");
|
||||
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/test.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("keycloak-7269/test");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/test.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("keycloak-7269/sub-resource2/test");
|
||||
|
||||
updatePermissionPolicies("Permission for multiple url resource", "Deny Policy");
|
||||
login("jdoe", "jdoe");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource1/index1.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().not().contains("sub-resource1 index1.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("You can not access this resource.");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource1/index2.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().not().contains("sub-resource1 index2.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("You can not access this resource.");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/pattern1/page.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().not().contains("sub-resource2/pattern1");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("You can not access this resource.");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/pattern2/page.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().not().contains("sub-resource2/pattern2");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("You can not access this resource.");
|
||||
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/test.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("keycloak-7269/test");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/test.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("keycloak-7269/sub-resource2/test");
|
||||
|
||||
updatePermissionPolicies("Permission for multiple url resource", "All Users Policy");
|
||||
login("jdoe", "jdoe");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource1/index1.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource1 index1.jsp");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource1/index2.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource1 index2.jsp");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/pattern1/page.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource2/pattern1");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/pattern2/page.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("sub-resource2/pattern2");
|
||||
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/test.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("keycloak-7269/test");
|
||||
driver.navigate().to(getResourceServerUrl() + "/keycloak-7269/sub-resource2/test.jsp");
|
||||
waitUntilElement(By.tagName("h2")).text().contains("keycloak-7269/sub-resource2/test");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,620 +0,0 @@
|
|||
/*
|
||||
* 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.authz.example;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.common.Profile.Feature.AUTHORIZATION;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployer;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import org.keycloak.admin.client.resource.ResourcePermissionsResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||
import org.keycloak.testsuite.pages.InfoPage;
|
||||
import org.keycloak.testsuite.pages.LogoutConfirmPage;
|
||||
import org.keycloak.testsuite.util.ServerURLs;
|
||||
import org.keycloak.testsuite.util.UIUtils;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class AbstractServletPolicyEnforcerTest extends AbstractExampleAdapterTest {
|
||||
|
||||
protected static final String REALM_NAME = "servlet-policy-enforcer-authz";
|
||||
protected static final String RESOURCE_SERVER_ID = "servlet-policy-enforcer";
|
||||
|
||||
@ArquillianResource
|
||||
private Deployer deployer;
|
||||
|
||||
@Page
|
||||
protected LogoutConfirmPage logoutConfirmPage;
|
||||
|
||||
@Page
|
||||
protected InfoPage infoPage;
|
||||
|
||||
@BeforeClass
|
||||
public static void enabled() {
|
||||
ProfileAssume.assumeFeatureEnabled(AUTHORIZATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(
|
||||
loadRealm(new File(TEST_APPS_HOME_DIR + "/servlet-policy-enforcer/servlet-policy-enforcer-authz-realm.json")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern1() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 1 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 1 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/b");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern2() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern3() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/b/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 2 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 3 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/resource-b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/b/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern4() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource-c");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 4 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource-c");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 4 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource-c");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern5() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/a/a/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/b/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 5 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/a/resource-d");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/a/b/resource-d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 5 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/a/b/resource-d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern6() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 6 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 6 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/b");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern7() throws Exception {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/f/b");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 7 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/f/b");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 7 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/c/f/d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern8() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 8 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 8 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern9() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/file/*.suffix");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 9 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/file/*.suffix");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 9 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/file/*.suffix");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern10() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
|
||||
navigateTo("/resource/a/i/b/c/d/e");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/resource/a/i/b/c/");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 10 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/i/b/c/d/e");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/resource/a/i/b/c/d");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 10 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/resource/a/i/b/c/d");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPattern11UsingResourceInstancePermission() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/api/v1/resource-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/api/v1/resource-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
ResourceRepresentation resource = new ResourceRepresentation("/api/v1/resource-c");
|
||||
|
||||
resource.setUri(resource.getName());
|
||||
|
||||
getAuthorizationResource().resources().create(resource);
|
||||
|
||||
createResourcePermission(resource.getName() + " permission", resource.getName(), "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies(resource.getName() + " permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies(resource.getName() + " permission", "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo(resource.getUri());
|
||||
assertFalse(wasDenied());
|
||||
|
||||
navigateTo("/api/v1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api/v1/");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/api/");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathWithPatternSlashAllAndResourceInstance() {
|
||||
performTests(() -> {
|
||||
ResourceRepresentation resource = new ResourceRepresentation("Pattern 15 Instance");
|
||||
|
||||
resource.setType("pattern-15");
|
||||
resource.setUri("/keycloak-7148/1");
|
||||
resource.setOwner("alice");
|
||||
|
||||
getAuthorizationResource().resources().create(resource).close();
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7148/1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2/sub-b");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 15 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7148/1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7148/1/sub-a/2/sub-b");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
// does not exist
|
||||
navigateTo("/keycloak-7148/2");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPriorityOfURIForResource() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 12 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 12 Permission", "Default Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/realm_uri");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak_json_uri");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathOrderWithAllPaths() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 13 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 14 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-6623");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-6623/sub-resource/resource");
|
||||
assertTrue(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleUriForResourceJSONConfig() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 16 Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 16 Permission", "Default Policy");
|
||||
navigateTo("/keycloak-7269/sub-resource1");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource1/whatever/specialSuffix");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-7269/sub-resource2/w/h/a/t/e/v/e/r");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverloadedTemplateUri() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Deny Policy");
|
||||
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertTrue(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
|
||||
updatePermissionPolicies("Pattern 17 Permission", "Deny Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertTrue(wasDenied());
|
||||
|
||||
updatePermissionPolicies("Pattern 17 Entities Permission", "Default Policy");
|
||||
updatePermissionPolicies("Pattern 17 Permission", "Default Policy");
|
||||
login("alice", "alice");
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/entities");
|
||||
assertFalse(wasDenied());
|
||||
navigateTo("/keycloak-8823/resource/v1/subresource/123/someother");
|
||||
assertFalse(wasDenied());
|
||||
});
|
||||
}
|
||||
|
||||
private void navigateTo(String path) {
|
||||
this.driver.navigate().to(getResourceServerUrl() + path);
|
||||
}
|
||||
|
||||
private void performTests(ExceptionRunnable assertion) {
|
||||
performTests(() -> {}, assertion);
|
||||
}
|
||||
|
||||
private void performTests(ExceptionRunnable beforeDeploy, ExceptionRunnable assertion) {
|
||||
try {
|
||||
beforeDeploy.run();
|
||||
deployer.deploy(RESOURCE_SERVER_ID);
|
||||
assertion.run();
|
||||
} catch (FileNotFoundException cause) {
|
||||
throw new RuntimeException("Failed to import authorization settings", cause);
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Error while executing tests", cause);
|
||||
} finally {
|
||||
deployer.undeploy(RESOURCE_SERVER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
private AuthorizationResource getAuthorizationResource() {
|
||||
return getClientResource(RESOURCE_SERVER_ID).authorization();
|
||||
}
|
||||
|
||||
private ClientResource getClientResource(String clientId) {
|
||||
ClientsResource clients = this.realmsResouce().realm(REALM_NAME).clients();
|
||||
ClientRepresentation resourceServer = clients.findByClientId(clientId).get(0);
|
||||
return clients.get(resourceServer.getId());
|
||||
}
|
||||
|
||||
private void logOut() {
|
||||
navigateTo();
|
||||
UIUtils.clickLink(driver.findElement(By.xpath("//a[text() = 'Sign Out']")));
|
||||
|
||||
logoutConfirmPage.assertCurrent();
|
||||
logoutConfirmPage.confirmLogout();
|
||||
infoPage.assertCurrent();
|
||||
}
|
||||
|
||||
private void login(String username, String password) {
|
||||
try {
|
||||
navigateTo();
|
||||
if (this.driver.getCurrentUrl().startsWith(getResourceServerUrl().toString())) {
|
||||
logOut();
|
||||
navigateTo();
|
||||
}
|
||||
this.loginPage.form().login(username, password);
|
||||
navigateTo();
|
||||
assertFalse(wasDenied());
|
||||
} catch (Exception cause) {
|
||||
throw new RuntimeException("Login failed", cause);
|
||||
}
|
||||
}
|
||||
|
||||
private void navigateTo() {
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/");
|
||||
waitForPageToLoad();
|
||||
}
|
||||
|
||||
private boolean wasDenied() {
|
||||
return this.driver.getPageSource().contains("You can not access this resource");
|
||||
}
|
||||
|
||||
private URL getResourceServerUrl() {
|
||||
try {
|
||||
return new URL(ServerURLs.getAppServerContextRoot() + "/" + RESOURCE_SERVER_ID);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException("Could not obtain resource server url.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePermissionPolicies(String permissionName, String... policyNames) {
|
||||
ResourcePermissionsResource permissions = getAuthorizationResource().permissions().resource();
|
||||
ResourcePermissionRepresentation permission = permissions.findByName(permissionName);
|
||||
|
||||
permission.addPolicy(policyNames);
|
||||
|
||||
permissions.findById(permission.getId()).update(permission);
|
||||
}
|
||||
|
||||
private void createResourcePermission(String name, String resourceName, String... policyNames) {
|
||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||
|
||||
permission.setName(name);
|
||||
permission.addResource(resourceName);
|
||||
permission.addPolicy(policyNames);
|
||||
|
||||
getAuthorizationResource().permissions().resource().create(permission);
|
||||
}
|
||||
|
||||
private interface ExceptionRunnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* 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.authz.example;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployer;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.AuthorizationResource;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ClientsResource;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||
import org.keycloak.testsuite.ProfileAssume;
|
||||
import org.keycloak.testsuite.adapter.AbstractExampleAdapterTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.util.ServerURLs;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.keycloak.common.Profile.Feature.AUTHORIZATION;
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class DefaultAuthzConfigAdapterTest extends AbstractExampleAdapterTest {
|
||||
|
||||
private static final String REALM_NAME = "hello-world-authz";
|
||||
private static final String RESOURCE_SERVER_ID = "hello-world-authz-service";
|
||||
|
||||
@ArquillianResource
|
||||
private Deployer deployer;
|
||||
|
||||
@BeforeClass
|
||||
public static void enabled() {
|
||||
ProfileAssume.assumeFeatureEnabled(AUTHORIZATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(
|
||||
loadRealm(new File(TEST_APPS_HOME_DIR + "/hello-world-authz-service/hello-world-authz-realm.json")));
|
||||
}
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultAuthzConfig() throws Exception {
|
||||
try {
|
||||
configureAuthorizationServices();
|
||||
this.deployer.deploy(RESOURCE_SERVER_ID);
|
||||
|
||||
login();
|
||||
|
||||
assertTrue(this.driver.getPageSource().contains("Your permissions are"));
|
||||
assertTrue(this.driver.getPageSource().contains("Default Resource"));
|
||||
|
||||
boolean hasDefaultPermission = false;
|
||||
boolean hasDefaultPolicy = false;
|
||||
|
||||
for (PolicyRepresentation policy : getAuthorizationResource().policies().policies()) {
|
||||
if ("Default Policy".equals(policy.getName())) {
|
||||
hasDefaultPolicy = true;
|
||||
}
|
||||
if ("Default Permission".equals(policy.getName())) {
|
||||
hasDefaultPermission = true;
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(hasDefaultPermission);
|
||||
assertTrue(hasDefaultPolicy);
|
||||
} finally {
|
||||
this.deployer.undeploy(RESOURCE_SERVER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
private void login() throws MalformedURLException {
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/");
|
||||
this.loginPage.form().login("alice", "alice");
|
||||
}
|
||||
|
||||
private URL getResourceServerUrl() throws MalformedURLException {
|
||||
return new URL(ServerURLs.getAppServerContextRoot() + "/" + RESOURCE_SERVER_ID);
|
||||
}
|
||||
|
||||
private void configureAuthorizationServices() {
|
||||
ClientsResource clients = realmsResouce().realm(REALM_NAME).clients();
|
||||
ClientRepresentation client = clients.findByClientId(RESOURCE_SERVER_ID).get(0);
|
||||
|
||||
client.setAuthorizationServicesEnabled(false);
|
||||
|
||||
// disables authorization services and remove authorization configuration from the client app
|
||||
clients.get(client.getId()).update(client);
|
||||
|
||||
client.setAuthorizationServicesEnabled(true);
|
||||
|
||||
// enable authorization services in order to generate the default config and continue with tests
|
||||
clients.get(client.getId()).update(client);
|
||||
}
|
||||
|
||||
private AuthorizationResource getAuthorizationResource() throws FileNotFoundException {
|
||||
return getClientResource(RESOURCE_SERVER_ID).authorization();
|
||||
}
|
||||
|
||||
private ClientResource getClientResource(String clientId) {
|
||||
ClientsResource clients = this.realmsResouce().realm(REALM_NAME).clients();
|
||||
ClientRepresentation resourceServer = clients.findByClientId(clientId).get(0);
|
||||
return clients.get(resourceServer.getId());
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* 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.authz.example;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.arquillian.AppServerTestEnricher;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class PermissiveModeAdapterTest extends AbstractBaseServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID)
|
||||
.addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/servlet-authz-realm.json"), "keycloak-permissive-authz-service.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanAccessWhenPermissive() throws Exception {
|
||||
performTests(() -> {
|
||||
login("jdoe", "jdoe");
|
||||
driver.navigate().to(getResourceServerUrl() + "/enforcing/resource");
|
||||
|
||||
assertThat(driver.getTitle(), is(equalTo("Error")));
|
||||
assertThat(driver.getPageSource(), containsString("Not Found"));
|
||||
|
||||
driver.navigate().to(getResourceServerUrl() + "/protected/admin");
|
||||
assertWasDenied();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.authz.example;
|
||||
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.util.AdminClientUtil;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ServletAuthzCIPAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID)
|
||||
.addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/keycloak-claim-information-point-authz-service.json"), "keycloak.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReuseBodyAfterClaimProcessing() {
|
||||
performTests(() -> {
|
||||
OAuthClient.AccessTokenResponse response = oauth.realm("servlet-authz").clientId("servlet-authz-app")
|
||||
.doGrantAccessTokenRequest("secret", "alice", "alice");
|
||||
Client client = AdminClientUtil.createResteasyClient();
|
||||
Map<String, String> body = new HashMap();
|
||||
|
||||
body.put("test", "test-value");
|
||||
|
||||
Response post = client.target(getResourceServerUrl() + "/protected/filter/body")
|
||||
.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, "Bearer " + response.getAccessToken())
|
||||
.post(Entity.entity(body, MediaType.APPLICATION_JSON_TYPE));
|
||||
|
||||
body = post.readEntity(Map.class);
|
||||
|
||||
Assert.assertEquals("test-value", body.get("test"));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.authz.example;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ServletAuthzCacheDisabledAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID)
|
||||
.addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/keycloak-cache-disabled-authz-service.json"), "keycloak.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateNewResource() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/new-resource");
|
||||
assertWasNotDenied();
|
||||
|
||||
ResourceRepresentation resource = new ResourceRepresentation();
|
||||
|
||||
resource.setName("New Resource");
|
||||
resource.setUri("/new-resource");
|
||||
|
||||
getAuthorizationResource().resources().create(resource);
|
||||
|
||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||
|
||||
permission.setName(resource.getName() + " Permission");
|
||||
permission.addResource(resource.getName());
|
||||
permission.addPolicy("Deny Policy");
|
||||
|
||||
permission = getAuthorizationResource().permissions().resource().create(permission).readEntity(ResourcePermissionRepresentation.class);
|
||||
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/new-resource");
|
||||
assertWasDenied();
|
||||
|
||||
permission = getAuthorizationResource().permissions().resource().findById(permission.getId()).toRepresentation();
|
||||
|
||||
permission.removePolicy("Deny Policy");
|
||||
permission.addPolicy("Any User Policy");
|
||||
|
||||
getAuthorizationResource().permissions().resource().findById(permission.getId()).update(permission);
|
||||
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/new-resource");
|
||||
assertWasNotDenied();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.authz.example;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.idm.authorization.ResourcePermissionRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ServletAuthzCacheLifespanAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID)
|
||||
.addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/keycloak-cache-lifespan-authz-service.json"), "keycloak.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateNewResourceWaitExpiration() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/new-resource");
|
||||
assertWasNotDenied();
|
||||
|
||||
ResourceRepresentation resource = new ResourceRepresentation();
|
||||
|
||||
resource.setName("New Resource");
|
||||
resource.setUri("/new-resource");
|
||||
|
||||
getAuthorizationResource().resources().create(resource);
|
||||
|
||||
ResourcePermissionRepresentation permission = new ResourcePermissionRepresentation();
|
||||
|
||||
permission.setName(resource.getName() + " Permission");
|
||||
permission.addResource(resource.getName());
|
||||
permission.addPolicy("Deny Policy");
|
||||
|
||||
getAuthorizationResource().permissions().resource().create(permission).readEntity(ResourcePermissionRepresentation.class);
|
||||
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/new-resource");
|
||||
assertWasNotDenied();
|
||||
|
||||
//Thread.sleep(5000);
|
||||
setTimeOffset(30);
|
||||
setTimeOffsetOfAdapter(30);
|
||||
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/new-resource");
|
||||
assertWasDenied();
|
||||
|
||||
resetTimeOffset();
|
||||
setTimeOffsetOfAdapter(0);
|
||||
});
|
||||
}
|
||||
|
||||
public void setTimeOffsetOfAdapter(int offset) {
|
||||
this.driver.navigate().to(getResourceServerUrl() + "/timeOffset.jsp?offset=" + String.valueOf(offset));
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.authz.example;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ServletAuthzLazyLoadPathsAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID)
|
||||
.addAsWebInfResource(new File(TEST_APPS_HOME_DIR + "/servlet-authz-app/keycloak-lazy-load-authz-service.json"), "keycloak.json");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathPEPDisabled() {
|
||||
performTests(() -> {
|
||||
login("alice", "alice");
|
||||
assertWasNotDenied();
|
||||
|
||||
navigateTo();
|
||||
getLink("PEP Disabled").click();
|
||||
|
||||
hasText("Policy enforcement is disabled. Access granted: true");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.authz.example;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ServletAuthzNoLazyLoadPathsAdapterTest extends AbstractServletAuthzAdapterTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() throws IOException {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* 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.authz.example;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ServletPolicyEnforcerLifespanTest extends AbstractServletPolicyEnforcerTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID,
|
||||
webArchive -> webArchive.addAsWebInfResource(
|
||||
new File(TEST_APPS_HOME_DIR
|
||||
+ "/servlet-policy-enforcer/servlet-policy-enforcer-lifespan-authz-service.json"),
|
||||
"keycloak.json"));
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* 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.authz.example;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ServletPolicyEnforcerTest extends AbstractServletPolicyEnforcerTest {
|
||||
|
||||
@Deployment(name = RESOURCE_SERVER_ID, managed = false)
|
||||
public static WebArchive deployment() {
|
||||
return exampleDeployment(RESOURCE_SERVER_ID);
|
||||
}
|
||||
}
|
|
@ -1,909 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.container.test.api.OperateOnDeployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.authorization.model.Policy;
|
||||
import org.keycloak.authorization.model.ResourceServer;
|
||||
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
|
||||
import org.keycloak.broker.oidc.mappers.UserAttributeMapper;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.exportimport.ExportImportConfig;
|
||||
import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.IdentityProviderMapperModel;
|
||||
import org.keycloak.models.IdentityProviderMapperSyncMode;
|
||||
import org.keycloak.models.IdentityProviderModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.protocol.oidc.OIDCConfigAttributes;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.protocol.oidc.mappers.HardcodedClaim;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.DecisionStrategy;
|
||||
import org.keycloak.services.resources.admin.permissions.AdminPermissionManagement;
|
||||
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.arquillian.annotation.DisableFeature;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.arquillian.annotation.UncaughtServerErrorExpected;
|
||||
import org.keycloak.testsuite.broker.BrokerTestTools;
|
||||
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
||||
import org.keycloak.testsuite.pages.ErrorPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.LoginUpdateProfilePage;
|
||||
import org.keycloak.testsuite.util.AdminClientUtil;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.util.BasicAuthHelper;
|
||||
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.client.WebTarget;
|
||||
import jakarta.ws.rs.core.Form;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWithAdminClient;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
@EnableFeature(value = Profile.Feature.TOKEN_EXCHANGE, skipRestart = true)
|
||||
@EnableFeature(value = Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, skipRestart = true)
|
||||
public class BrokerLinkAndTokenExchangeTest extends AbstractServletsAdapterTest {
|
||||
public static final String CHILD_IDP = "child";
|
||||
public static final String PARENT_IDP = "parent-idp";
|
||||
public static final String PARENT_USERNAME = "parent";
|
||||
public static final String PARENT2_USERNAME = "parent2";
|
||||
public static final String PARENT3_USERNAME = "parent3";
|
||||
public static final String UNAUTHORIZED_CHILD_CLIENT = "unauthorized-child-client";
|
||||
public static final String PARENT_CLIENT = "parent-client";
|
||||
|
||||
@Deployment(name = ClientApp.DEPLOYMENT_NAME)
|
||||
protected static WebArchive accountLink() {
|
||||
return servletDeployment(ClientApp.DEPLOYMENT_NAME, LinkAndExchangeServlet.class, ServletTestUtils.class);
|
||||
}
|
||||
|
||||
@Page
|
||||
protected LoginUpdateProfilePage loginUpdateProfilePage;
|
||||
|
||||
@Page
|
||||
private LoginPage loginPage;
|
||||
|
||||
@Page
|
||||
protected ErrorPage errorPage;
|
||||
|
||||
public static class ClientApp extends AbstractPageWithInjectedUrl {
|
||||
|
||||
public static final String DEPLOYMENT_NAME = "exchange-linking";
|
||||
|
||||
@ArquillianResource
|
||||
@OperateOnDeployment(DEPLOYMENT_NAME)
|
||||
private URL url;
|
||||
|
||||
@Override
|
||||
public URL getInjectedUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Page
|
||||
private ClientApp appPage;
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
|
||||
@Override
|
||||
public void beforeAuthTest() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation realm = new RealmRepresentation();
|
||||
realm.setRealm(CHILD_IDP);
|
||||
realm.setEnabled(true);
|
||||
realm.setEventsEnabled(true);
|
||||
ClientRepresentation servlet = new ClientRepresentation();
|
||||
servlet.setClientId(ClientApp.DEPLOYMENT_NAME);
|
||||
servlet.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
String uri = "/" + ClientApp.DEPLOYMENT_NAME;
|
||||
if (!isRelative()) {
|
||||
uri = appServerContextRootPage.toString() + uri;
|
||||
}
|
||||
servlet.setEnabled(true);
|
||||
servlet.setAdminUrl(uri);
|
||||
servlet.setDirectAccessGrantsEnabled(true);
|
||||
servlet.setBaseUrl(uri);
|
||||
servlet.setRedirectUris(new LinkedList<>());
|
||||
servlet.getRedirectUris().add(uri + "/*");
|
||||
servlet.setSecret("password");
|
||||
servlet.setFullScopeAllowed(true);
|
||||
|
||||
Map<String, String> attributes = Optional.ofNullable(servlet.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put(OIDCConfigAttributes.EXCLUDE_ISSUER_FROM_AUTH_RESPONSE, Boolean.TRUE.toString());
|
||||
servlet.setAttributes(attributes);
|
||||
|
||||
realm.setClients(new LinkedList<>());
|
||||
realm.getClients().add(servlet);
|
||||
|
||||
ClientRepresentation unauthorized = new ClientRepresentation();
|
||||
unauthorized.setEnabled(true);
|
||||
unauthorized.setClientId(UNAUTHORIZED_CHILD_CLIENT);
|
||||
unauthorized.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
unauthorized.setDirectAccessGrantsEnabled(true);
|
||||
unauthorized.setSecret("password");
|
||||
unauthorized.setFullScopeAllowed(true);
|
||||
realm.getClients().add(unauthorized);
|
||||
|
||||
testRealms.add(realm);
|
||||
|
||||
realm = new RealmRepresentation();
|
||||
realm.setRealm(PARENT_IDP);
|
||||
realm.setEnabled(true);
|
||||
ClientRepresentation parentApp = new ClientRepresentation();
|
||||
parentApp.setEnabled(true);
|
||||
parentApp.setClientId(PARENT_CLIENT);
|
||||
parentApp.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
parentApp.setDirectAccessGrantsEnabled(true);
|
||||
parentApp.setSecret("password");
|
||||
parentApp.setFullScopeAllowed(true);
|
||||
realm.setClients(new LinkedList<>());
|
||||
realm.getClients().add(parentApp);
|
||||
testRealms.add(realm);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFeature(value = Profile.Feature.TOKEN_EXCHANGE, skipRestart = true)
|
||||
@UncaughtServerErrorExpected
|
||||
public void testFeatureDisabled() throws Exception {
|
||||
checkFeature(Response.Status.BAD_REQUEST.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeatureEnabled() throws Exception {
|
||||
checkFeature(Response.Status.OK.getStatusCode());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws Exception {
|
||||
addIdpUser();
|
||||
addChildUser();
|
||||
createBroker();
|
||||
}
|
||||
|
||||
public void addIdpUser() {
|
||||
RealmResource realm = adminClient.realms().realm(PARENT_IDP);
|
||||
UserRepresentation user = new UserRepresentation();
|
||||
user.setUsername(PARENT_USERNAME);
|
||||
user.setEnabled(true);
|
||||
createUserAndResetPasswordWithAdminClient(realm, user, "password");
|
||||
user = new UserRepresentation();
|
||||
user.setUsername(PARENT2_USERNAME);
|
||||
user.setEnabled(true);
|
||||
createUserAndResetPasswordWithAdminClient(realm, user, "password");
|
||||
user = new UserRepresentation();
|
||||
user.setUsername(PARENT3_USERNAME);
|
||||
user.setFirstName("first name");
|
||||
user.setLastName("last name");
|
||||
user.setEmail("email@keycloak.org");
|
||||
user.setEnabled(true);
|
||||
createUserAndResetPasswordWithAdminClient(realm, user, "password");
|
||||
}
|
||||
|
||||
private String childUserId = null;
|
||||
|
||||
public void addChildUser() {
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
UserRepresentation user = new UserRepresentation();
|
||||
user.setUsername("child");
|
||||
user.setEnabled(true);
|
||||
childUserId = createUserAndResetPasswordWithAdminClient(realm, user, "password");
|
||||
UserRepresentation user2 = new UserRepresentation();
|
||||
user2.setUsername("child2");
|
||||
user2.setEnabled(true);
|
||||
String user2Id = createUserAndResetPasswordWithAdminClient(realm, user2, "password");
|
||||
|
||||
// have to add a role as undertow default auth manager doesn't like "*". todo we can remove this eventually as undertow fixes this in later versions
|
||||
realm.roles().create(new RoleRepresentation("user", null, false));
|
||||
RoleRepresentation role = realm.roles().get("user").toRepresentation();
|
||||
List<RoleRepresentation> roles = new LinkedList<>();
|
||||
roles.add(role);
|
||||
realm.users().get(childUserId).roles().realmLevel().add(roles);
|
||||
realm.users().get(user2Id).roles().realmLevel().add(roles);
|
||||
ClientRepresentation brokerService = realm.clients().findByClientId(Constants.BROKER_SERVICE_CLIENT_ID).get(0);
|
||||
role = realm.clients().get(brokerService.getId()).roles().get(Constants.READ_TOKEN_ROLE).toRepresentation();
|
||||
roles.clear();
|
||||
roles.add(role);
|
||||
realm.users().get(childUserId).roles().clientLevel(brokerService.getId()).add(roles);
|
||||
realm.users().get(user2Id).roles().clientLevel(brokerService.getId()).add(roles);
|
||||
|
||||
}
|
||||
|
||||
public static void setupRealm(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName(CHILD_IDP);
|
||||
ClientModel client = realm.getClientByClientId(ClientApp.DEPLOYMENT_NAME);
|
||||
IdentityProviderModel idp = realm.getIdentityProviderByAlias(PARENT_IDP);
|
||||
Assert.assertNotNull(idp);
|
||||
|
||||
ClientModel directExchanger = realm.addClient("direct-exchanger");
|
||||
directExchanger.setClientId("direct-exchanger");
|
||||
directExchanger.setPublicClient(false);
|
||||
directExchanger.setDirectAccessGrantsEnabled(true);
|
||||
directExchanger.setEnabled(true);
|
||||
directExchanger.setSecret("secret");
|
||||
directExchanger.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
directExchanger.setFullScopeAllowed(false);
|
||||
|
||||
|
||||
AdminPermissionManagement management = AdminPermissions.management(session, realm);
|
||||
management.idps().setPermissionsEnabled(idp, true);
|
||||
ClientPolicyRepresentation clientRep = new ClientPolicyRepresentation();
|
||||
clientRep.setName("toIdp");
|
||||
clientRep.addClient(client.getId());
|
||||
clientRep.addClient(directExchanger.getId());
|
||||
ResourceServer server = management.realmResourceServer();
|
||||
Policy clientPolicy = management.authz().getStoreFactory().getPolicyStore().create(server, clientRep);
|
||||
management.idps().exchangeToPermission(idp).addAssociatedPolicy(clientPolicy);
|
||||
|
||||
|
||||
// permission for user impersonation for a client
|
||||
|
||||
ClientPolicyRepresentation clientImpersonateRep = new ClientPolicyRepresentation();
|
||||
clientImpersonateRep.setName("clientImpersonators");
|
||||
clientImpersonateRep.addClient(directExchanger.getId());
|
||||
server = management.realmResourceServer();
|
||||
Policy clientImpersonatePolicy = management.authz().getStoreFactory().getPolicyStore().create(server, clientImpersonateRep);
|
||||
management.users().setPermissionsEnabled(true);
|
||||
management.users().adminImpersonatingPermission().addAssociatedPolicy(clientImpersonatePolicy);
|
||||
management.users().adminImpersonatingPermission().setDecisionStrategy(DecisionStrategy.AFFIRMATIVE);
|
||||
|
||||
}
|
||||
public static void turnOffTokenStore(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName(CHILD_IDP);
|
||||
IdentityProviderModel idp = realm.getIdentityProviderByAlias(PARENT_IDP);
|
||||
idp.setStoreToken(false);
|
||||
realm.updateIdentityProvider(idp);
|
||||
|
||||
}
|
||||
public static void turnOnTokenStore(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName(CHILD_IDP);
|
||||
IdentityProviderModel idp = realm.getIdentityProviderByAlias(PARENT_IDP);
|
||||
idp.setStoreToken(true);
|
||||
realm.updateIdentityProvider(idp);
|
||||
}
|
||||
|
||||
public void createBroker() {
|
||||
createParentChild();
|
||||
testingClient.server().run(BrokerLinkAndTokenExchangeTest::setupRealm);
|
||||
}
|
||||
|
||||
public void createParentChild() {
|
||||
BrokerTestTools.createKcOidcBroker(adminClient, CHILD_IDP, PARENT_IDP);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testAccountLink() throws Exception {
|
||||
testingClient.server().run(BrokerLinkAndTokenExchangeTest::turnOnTokenStore);
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
String servletUri = appPage.getInjectedUrl().toString();
|
||||
UriBuilder linkBuilder = UriBuilder.fromUri(servletUri)
|
||||
.path("link");
|
||||
String linkUrl = linkBuilder.clone()
|
||||
.queryParam("realm", CHILD_IDP)
|
||||
.queryParam("provider", PARENT_IDP).build().toString();
|
||||
System.out.println("linkUrl: " + linkUrl);
|
||||
navigateTo(linkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
Assert.assertTrue(driver.getPageSource().contains(PARENT_IDP));
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue(loginPage.isCurrent(PARENT_IDP));
|
||||
loginPage.login(PARENT_USERNAME, "password");
|
||||
System.out.println("After linking: " + driver.getCurrentUrl());
|
||||
System.out.println(driver.getPageSource());
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(linkBuilder.toTemplate()));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Account Linked"));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Exchange token received"));
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertFalse(links.isEmpty());
|
||||
|
||||
|
||||
// do exchange
|
||||
|
||||
String accessToken = oauth.doGrantAccessTokenRequest(CHILD_IDP, "child", "password", null, ClientApp.DEPLOYMENT_NAME, "password").getAccessToken();
|
||||
Client httpClient = AdminClientUtil.createResteasyClient();
|
||||
try {
|
||||
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
|
||||
|
||||
Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||
|
||||
));
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
response.close();
|
||||
String externalToken = tokenResponse.getToken();
|
||||
Assert.assertNotNull(externalToken);
|
||||
Assert.assertTrue(tokenResponse.getExpiresIn() > 0);
|
||||
setTimeOffset((int) tokenResponse.getExpiresIn() + 1);
|
||||
|
||||
// test that token refresh happens
|
||||
|
||||
// get access token again because we may have timed out
|
||||
accessToken = oauth.doGrantAccessTokenRequest(CHILD_IDP, "child", "password", null, ClientApp.DEPLOYMENT_NAME, "password").getAccessToken();
|
||||
response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||
|
||||
));
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
response.close();
|
||||
Assert.assertNotEquals(externalToken, tokenResponse.getToken());
|
||||
|
||||
// test direct exchange
|
||||
response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader("direct-exchanger", "secret"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.REQUESTED_SUBJECT, "child")
|
||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||
|
||||
));
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
response.close();
|
||||
Assert.assertNotEquals(externalToken, tokenResponse.getToken());
|
||||
|
||||
|
||||
resetTimeOffset();
|
||||
logoutAll();
|
||||
|
||||
|
||||
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
} finally {
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected WebTarget childTokenExchangeWebTarget(Client httpClient) {
|
||||
return httpClient.target(OAuthClient.AUTH_SERVER_ROOT)
|
||||
.path("/realms")
|
||||
.path(CHILD_IDP)
|
||||
.path("protocol/openid-connect/token");
|
||||
|
||||
}
|
||||
protected WebTarget childLogoutWebTarget(Client httpClient) {
|
||||
return httpClient.target(OAuthClient.AUTH_SERVER_ROOT)
|
||||
.path("/realms")
|
||||
.path(CHILD_IDP)
|
||||
.path("protocol/openid-connect/logout");
|
||||
|
||||
}
|
||||
protected String parentJwksUrl() {
|
||||
return UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)
|
||||
.path("/realms")
|
||||
.path(PARENT_IDP)
|
||||
.path("protocol/openid-connect")
|
||||
.path(OIDCLoginProtocolService.class, "certs").build().toString();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testAccountLinkNoTokenStore() {
|
||||
testingClient.server().run(BrokerLinkAndTokenExchangeTest::turnOffTokenStore);
|
||||
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
UriBuilder linkBuilder = UriBuilder.fromUri(appPage.getInjectedUrl().toString())
|
||||
.path("link");
|
||||
String linkUrl = linkBuilder.clone()
|
||||
.queryParam("realm", CHILD_IDP)
|
||||
.queryParam("provider", PARENT_IDP).build().toString();
|
||||
System.out.println("linkUrl: " + linkUrl);
|
||||
navigateTo(linkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
Assert.assertTrue(driver.getPageSource().contains(PARENT_IDP));
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue("Unexpected page. Current Page URL: " + driver.getCurrentUrl(),loginPage.isCurrent(PARENT_IDP));
|
||||
loginPage.login(PARENT_USERNAME, "password");
|
||||
System.out.println("After linking: " + driver.getCurrentUrl());
|
||||
System.out.println(driver.getPageSource());
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(linkBuilder.toTemplate()));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Account Linked"));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Exchange token received"));
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertFalse(links.isEmpty());
|
||||
|
||||
|
||||
logoutAll();
|
||||
|
||||
|
||||
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* KEYCLOAK-6026
|
||||
*/
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testExportImport() throws Exception {
|
||||
testExternalExchange();
|
||||
|
||||
try {
|
||||
testingClient.testing().exportImport().setProvider(SingleFileExportProviderFactory.PROVIDER_ID);
|
||||
String targetFilePath = testingClient.testing().exportImport().getExportImportTestDirectory() + File.separator + "singleFile-full.json";
|
||||
testingClient.testing().exportImport().setFile(targetFilePath);
|
||||
testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_EXPORT);
|
||||
testingClient.testing().exportImport().setRealmName(CHILD_IDP);
|
||||
testingClient.testing().exportImport().runExport();
|
||||
|
||||
adminClient.realms().realm(CHILD_IDP).remove();
|
||||
testingClient.testing().exportImport().setAction(ExportImportConfig.ACTION_IMPORT);
|
||||
|
||||
testingClient.testing().exportImport().runImport();
|
||||
} finally {
|
||||
testingClient.testing().exportImport().clear();
|
||||
}
|
||||
|
||||
testExternalExchange();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UncaughtServerErrorExpected
|
||||
public void testExternalExchange() throws Exception {
|
||||
RealmResource childRealm = adminClient.realms().realm(CHILD_IDP);
|
||||
|
||||
String accessToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT2_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
Client httpClient = AdminClientUtil.createResteasyClient();
|
||||
try {
|
||||
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||
System.out.println("Exchange url: " + exchangeUrl.getUri().toString());
|
||||
|
||||
checkFeature(200);
|
||||
|
||||
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
||||
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(true));
|
||||
rep.getConfig().put(OIDCIdentityProviderConfig.USE_JWKS_URL, String.valueOf(true));
|
||||
rep.getConfig().put(OIDCIdentityProviderConfig.JWKS_URL, parentJwksUrl());
|
||||
String parentIssuer = UriBuilder.fromUri(OAuthClient.AUTH_SERVER_ROOT)
|
||||
.path("/realms")
|
||||
.path(PARENT_IDP)
|
||||
.build().toString();
|
||||
rep.getConfig().put("issuer", parentIssuer);
|
||||
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
||||
|
||||
String exchangedUserId;
|
||||
String exchangedUsername;
|
||||
|
||||
{
|
||||
// test signature validation
|
||||
Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||
.param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
|
||||
));
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
String idToken = tokenResponse.getIdToken();
|
||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||
AccessToken token = jws.readJsonContent(AccessToken.class);
|
||||
response.close();
|
||||
|
||||
exchangedUserId = token.getSubject();
|
||||
exchangedUsername = token.getPreferredUsername();
|
||||
|
||||
System.out.println("exchangedUserId: " + exchangedUserId);
|
||||
System.out.println("exchangedUsername: " + exchangedUsername);
|
||||
|
||||
|
||||
// test that we can exchange back to external token
|
||||
response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, tokenResponse.getToken())
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.REQUESTED_ISSUER, PARENT_IDP)
|
||||
|
||||
));
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
Assert.assertEquals(accessToken, tokenResponse.getToken());
|
||||
response.close();
|
||||
|
||||
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
// test logout
|
||||
response = childLogoutWebTarget(httpClient)
|
||||
.queryParam("id_token_hint", idToken)
|
||||
.request()
|
||||
.get();
|
||||
response.close();
|
||||
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
|
||||
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
||||
Assert.assertEquals(1, links.size());
|
||||
}
|
||||
{
|
||||
// check that we can request an exchange again and that the previously linked user is obtained
|
||||
Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||
.param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
|
||||
));
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
String idToken = tokenResponse.getIdToken();
|
||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||
AccessToken token = jws.readJsonContent(AccessToken.class);
|
||||
response.close();
|
||||
|
||||
String exchanged2UserId = token.getSubject();
|
||||
String exchanged2Username = token.getPreferredUsername();
|
||||
|
||||
// assert that we get the same linked account as was previously imported
|
||||
|
||||
Assert.assertEquals(exchangedUserId, exchanged2UserId);
|
||||
Assert.assertEquals(exchangedUsername, exchanged2Username);
|
||||
|
||||
// test logout
|
||||
response = childLogoutWebTarget(httpClient)
|
||||
.queryParam("id_token_hint", idToken)
|
||||
.request()
|
||||
.get();
|
||||
response.close();
|
||||
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
|
||||
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
||||
Assert.assertEquals(1, links.size());
|
||||
}
|
||||
{
|
||||
// check that we can exchange without specifying an SUBJECT_ISSUER
|
||||
Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
|
||||
));
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
String idToken = tokenResponse.getIdToken();
|
||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||
AccessToken token = jws.readJsonContent(AccessToken.class);
|
||||
response.close();
|
||||
|
||||
String exchanged2UserId = token.getSubject();
|
||||
String exchanged2Username = token.getPreferredUsername();
|
||||
|
||||
// assert that we get the same linked account as was previously imported
|
||||
|
||||
Assert.assertEquals(exchangedUserId, exchanged2UserId);
|
||||
Assert.assertEquals(exchangedUsername, exchanged2Username);
|
||||
|
||||
// test logout
|
||||
response = childLogoutWebTarget(httpClient)
|
||||
.queryParam("id_token_hint", idToken)
|
||||
.request()
|
||||
.get();
|
||||
response.close();
|
||||
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
|
||||
List<FederatedIdentityRepresentation> links = childRealm.users().get(exchangedUserId).getFederatedIdentity();
|
||||
Assert.assertEquals(1, links.size());
|
||||
}
|
||||
// cleanup remove the user
|
||||
childRealm.users().get(exchangedUserId).remove();
|
||||
|
||||
{
|
||||
// test unauthorized client gets 403
|
||||
try (Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(UNAUTHORIZED_CHILD_CLIENT, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||
|
||||
))) {
|
||||
Assert.assertEquals(403, response.getStatus());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* KEYCLOAK-14577, see also KEYCLOAK-10932
|
||||
*/
|
||||
@Test
|
||||
public void testExternalExchange_extractIdentityFromProfile() throws Exception {
|
||||
RealmResource childRealm = adminClient.realms().realm(CHILD_IDP);
|
||||
|
||||
String accessToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT3_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
Client httpClient = AdminClientUtil.createResteasyClient();
|
||||
try {
|
||||
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
||||
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(false));
|
||||
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
||||
|
||||
AccessToken token;
|
||||
try (Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||
.param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
))) {
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
|
||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||
token = jws.readJsonContent(AccessToken.class);
|
||||
}
|
||||
|
||||
Assert.assertNotNull(token);
|
||||
Assert.assertNotNull(token.getSubject());
|
||||
Assert.assertEquals(PARENT3_USERNAME, token.getPreferredUsername());
|
||||
Assert.assertEquals("first name", token.getGivenName());
|
||||
Assert.assertEquals("last name", token.getFamilyName());
|
||||
Assert.assertEquals("email@keycloak.org", token.getEmail());
|
||||
|
||||
// cleanup remove the user
|
||||
childRealm.users().get(token.getSubject()).remove();
|
||||
} finally {
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExternalExchangeCreateNewUserUsingMappers() throws Exception {
|
||||
RealmResource parentRealm = adminClient.realms().realm(PARENT_IDP);
|
||||
ProtocolMapperRepresentation claimMapper = new ProtocolMapperRepresentation();
|
||||
claimMapper.setName("custom-claim-hardcoded-mapper");
|
||||
claimMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
claimMapper.setProtocolMapper(HardcodedClaim.PROVIDER_ID);
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "claim-from-idp");
|
||||
config.put(HardcodedClaim.CLAIM_VALUE, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
|
||||
claimMapper.setConfig(config);
|
||||
ClientRepresentation client = parentRealm.clients().findByClientId(PARENT_CLIENT).get(0);
|
||||
ClientResource clientResource = parentRealm.clients().get(client.getId());
|
||||
clientResource.getProtocolMappers().createMapper(claimMapper).close();
|
||||
|
||||
RealmResource childRealm = adminClient.realms().realm(CHILD_IDP);
|
||||
IdentityProviderMapperRepresentation attributeMapper = new IdentityProviderMapperRepresentation();
|
||||
attributeMapper.setName("attribute-mapper");
|
||||
attributeMapper.setIdentityProviderMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
attributeMapper.setIdentityProviderAlias(PARENT_IDP);
|
||||
attributeMapper.setConfig(ImmutableMap.<String,String>builder()
|
||||
.put(IdentityProviderMapperModel.SYNC_MODE, IdentityProviderMapperSyncMode.INHERIT.toString())
|
||||
.put(UserAttributeMapper.CLAIM, "claim-from-idp")
|
||||
.put(UserAttributeMapper.USER_ATTRIBUTE, "claim-to-broker")
|
||||
.build());
|
||||
childRealm.identityProviders().get(PARENT_IDP).addMapper(attributeMapper).close();
|
||||
|
||||
String idToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT3_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
try (Client httpClient = AdminClientUtil.createResteasyClient()) {
|
||||
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
||||
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(false));
|
||||
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
||||
|
||||
AccessToken token;
|
||||
try (Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, idToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||
.param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
))) {
|
||||
Assert.assertEquals(200, response.getStatus());
|
||||
|
||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
JWSInput jws = new JWSInput(tokenResponse.getToken());
|
||||
token = jws.readJsonContent(AccessToken.class);
|
||||
}
|
||||
|
||||
UserRepresentation newUser = childRealm.users().search(PARENT3_USERNAME).get(0);
|
||||
Assert.assertNotNull(newUser.getAttributes());
|
||||
Assert.assertTrue(newUser.getAttributes().containsKey("claim-to-broker"));
|
||||
events.expect(EventType.REGISTER)
|
||||
.realm(childRealm.toRepresentation())
|
||||
.client("exchange-linking")
|
||||
.user(newUser)
|
||||
.detail(Details.IDENTITY_PROVIDER, PARENT_IDP)
|
||||
.assertEvent(childRealm.getEvents().get(1));
|
||||
|
||||
// cleanup remove the user
|
||||
childRealm.users().get(token.getSubject()).remove();
|
||||
}
|
||||
}
|
||||
|
||||
public void logoutAll() {
|
||||
adminClient.realm(CHILD_IDP).logoutAll();
|
||||
adminClient.realm(PARENT_IDP).logoutAll();
|
||||
}
|
||||
|
||||
private void navigateTo(String uri) {
|
||||
driver.navigate().to(uri);
|
||||
WaitUtils.waitForPageToLoad();
|
||||
}
|
||||
|
||||
private void checkFeature(int statusCode) throws Exception {
|
||||
String accessToken = oauth.doGrantAccessTokenRequest(PARENT_IDP, PARENT2_USERNAME, "password", null, PARENT_CLIENT, "password").getAccessToken();
|
||||
|
||||
if (statusCode != Response.Status.BAD_REQUEST.getStatusCode()) {
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
}
|
||||
|
||||
Client httpClient = AdminClientUtil.createResteasyClient();
|
||||
try {
|
||||
WebTarget exchangeUrl = childTokenExchangeWebTarget(httpClient);
|
||||
{
|
||||
IdentityProviderRepresentation rep = adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).toRepresentation();
|
||||
rep.getConfig().put(OIDCIdentityProviderConfig.VALIDATE_SIGNATURE, String.valueOf(false));
|
||||
adminClient.realm(CHILD_IDP).identityProviders().get(PARENT_IDP).update(rep);
|
||||
// test user info validation.
|
||||
Response response = exchangeUrl.request()
|
||||
.header(HttpHeaders.AUTHORIZATION, BasicAuthHelper.createHeader(ClientApp.DEPLOYMENT_NAME, "password"))
|
||||
.post(Entity.form(
|
||||
new Form()
|
||||
.param(OAuth2Constants.GRANT_TYPE, OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN, accessToken)
|
||||
.param(OAuth2Constants.SUBJECT_TOKEN_TYPE, OAuth2Constants.JWT_TOKEN_TYPE)
|
||||
.param(OAuth2Constants.SUBJECT_ISSUER, PARENT_IDP)
|
||||
.param(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
|
||||
));
|
||||
Assert.assertEquals(statusCode, response.getStatus());
|
||||
|
||||
if (statusCode != Response.Status.BAD_REQUEST.getStatusCode()) {
|
||||
AccessTokenResponse tokenResponse = response.readEntity(AccessTokenResponse.class);
|
||||
String idToken = tokenResponse.getIdToken();
|
||||
Assert.assertNotNull(idToken);
|
||||
response.close();
|
||||
|
||||
Assert.assertEquals(1, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
|
||||
// test logout
|
||||
response = childLogoutWebTarget(httpClient)
|
||||
.queryParam("id_token_hint", idToken)
|
||||
.request()
|
||||
.get();
|
||||
response.close();
|
||||
|
||||
Assert.assertEquals(0, adminClient.realm(CHILD_IDP).getClientSessionStats().size());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
httpClient.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,652 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.container.test.api.OperateOnDeployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.IdentityProviderResource;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.broker.provider.HardcodedAttributeMapper;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.Base64Url;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.IdentityProviderMapperModel;
|
||||
import org.keycloak.models.IdentityProviderMapperSyncMode;
|
||||
import org.keycloak.protocol.oidc.OIDCConfigAttributes;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
|
||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.services.resources.LoginActionsService;
|
||||
import org.keycloak.testsuite.ActionURIUtils;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.arquillian.annotation.EnableFeature;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.broker.BrokerTestTools;
|
||||
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
||||
import org.keycloak.testsuite.pages.ErrorPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.LoginUpdateProfilePage;
|
||||
import org.keycloak.testsuite.util.AdminClientUtil;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
|
||||
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT_LINKS;
|
||||
import static org.keycloak.models.Constants.ACCOUNT_MANAGEMENT_CLIENT_ID;
|
||||
import static org.keycloak.testsuite.admin.ApiUtil.createUserAndResetPasswordWithAdminClient;
|
||||
import static org.keycloak.testsuite.util.ServerURLs.getAuthServerContextRoot;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class ClientInitiatedAccountLinkTest extends AbstractServletsAdapterTest {
|
||||
public static final String CHILD_IDP = "child";
|
||||
public static final String PARENT_IDP = "parent-idp";
|
||||
public static final String PARENT_USERNAME = "parent";
|
||||
private static final String HARDCODED_ATTRIBUTE_MAPPER_NAME = "my_hardcoded_mapper";
|
||||
private static final String USER_ATTRIBUTE = "hardcoded_attribute";
|
||||
private static final String USER_ATTRIBUTE_VALUE = "hardcoded_value";
|
||||
|
||||
@Page
|
||||
protected LoginUpdateProfilePage loginUpdateProfilePage;
|
||||
|
||||
@Page
|
||||
private LoginPage loginPage;
|
||||
|
||||
@Page
|
||||
protected ErrorPage errorPage;
|
||||
|
||||
public static class ClientApp extends AbstractPageWithInjectedUrl {
|
||||
|
||||
public static final String DEPLOYMENT_NAME = "client-linking";
|
||||
|
||||
@ArquillianResource
|
||||
@OperateOnDeployment(DEPLOYMENT_NAME)
|
||||
private URL url;
|
||||
|
||||
@Override
|
||||
public URL getInjectedUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Page
|
||||
private ClientApp appPage;
|
||||
|
||||
@Override
|
||||
public void beforeAuthTest() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation realm = new RealmRepresentation();
|
||||
realm.setRealm(CHILD_IDP);
|
||||
realm.setEnabled(true);
|
||||
ClientRepresentation servlet = new ClientRepresentation();
|
||||
servlet.setClientId("client-linking");
|
||||
servlet.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
String uri = "/client-linking";
|
||||
servlet.setAdminUrl(uri);
|
||||
servlet.setDirectAccessGrantsEnabled(true);
|
||||
servlet.setBaseUrl(uri);
|
||||
servlet.setRedirectUris(new LinkedList<>());
|
||||
servlet.getRedirectUris().add(uri + "/*");
|
||||
servlet.setSecret("password");
|
||||
servlet.setFullScopeAllowed(true);
|
||||
|
||||
Map<String, String> attributes = Optional.ofNullable(servlet.getAttributes()).orElse(new HashMap<>());
|
||||
attributes.put(OIDCConfigAttributes.EXCLUDE_ISSUER_FROM_AUTH_RESPONSE, Boolean.TRUE.toString());
|
||||
servlet.setAttributes(attributes);
|
||||
|
||||
realm.setClients(new LinkedList<>());
|
||||
realm.getClients().add(servlet);
|
||||
testRealms.add(realm);
|
||||
|
||||
|
||||
realm = new RealmRepresentation();
|
||||
realm.setRealm(PARENT_IDP);
|
||||
realm.setEnabled(true);
|
||||
|
||||
testRealms.add(realm);
|
||||
|
||||
}
|
||||
|
||||
@Deployment(name = ClientApp.DEPLOYMENT_NAME)
|
||||
protected static WebArchive accountLink() {
|
||||
return servletDeployment(ClientApp.DEPLOYMENT_NAME, ClientInitiatedAccountLinkServlet.class, ServletTestUtils.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void addIdpUser() {
|
||||
RealmResource realm = adminClient.realms().realm(PARENT_IDP);
|
||||
UserRepresentation user = new UserRepresentation();
|
||||
user.setUsername(PARENT_USERNAME);
|
||||
user.setEnabled(true);
|
||||
String userId = createUserAndResetPasswordWithAdminClient(realm, user, "password");
|
||||
|
||||
}
|
||||
|
||||
private String childUserId = null;
|
||||
|
||||
@Before
|
||||
public void addChildUser() {
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
UserRepresentation user = new UserRepresentation();
|
||||
user.setUsername("child");
|
||||
user.setEnabled(true);
|
||||
childUserId = createUserAndResetPasswordWithAdminClient(realm, user, "password");
|
||||
UserRepresentation user2 = new UserRepresentation();
|
||||
user2.setUsername("child2");
|
||||
user2.setEnabled(true);
|
||||
String user2Id = createUserAndResetPasswordWithAdminClient(realm, user2, "password");
|
||||
|
||||
// have to add a role as undertow default auth manager doesn't like "*". todo we can remove this eventually as undertow fixes this in later versions
|
||||
realm.roles().create(new RoleRepresentation("user", null, false));
|
||||
RoleRepresentation role = realm.roles().get("user").toRepresentation();
|
||||
List<RoleRepresentation> roles = new LinkedList<>();
|
||||
roles.add(role);
|
||||
realm.users().get(childUserId).roles().realmLevel().add(roles);
|
||||
realm.users().get(user2Id).roles().realmLevel().add(roles);
|
||||
ClientRepresentation brokerService = realm.clients().findByClientId(Constants.BROKER_SERVICE_CLIENT_ID).get(0);
|
||||
role = realm.clients().get(brokerService.getId()).roles().get(Constants.READ_TOKEN_ROLE).toRepresentation();
|
||||
roles.clear();
|
||||
roles.add(role);
|
||||
realm.users().get(childUserId).roles().clientLevel(brokerService.getId()).add(roles);
|
||||
realm.users().get(user2Id).roles().clientLevel(brokerService.getId()).add(roles);
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void createBroker() {
|
||||
createParentChild();
|
||||
}
|
||||
|
||||
public void createParentChild() {
|
||||
BrokerTestTools.createKcOidcBroker(adminClient, CHILD_IDP, PARENT_IDP);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testErrorConditions() throws Exception {
|
||||
String helloUrl = appPage.getUriBuilder().clone().path("hello").build().toASCIIString();
|
||||
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
ClientRepresentation client = adminClient.realms().realm(CHILD_IDP).clients().findByClientId("client-linking").get(0);
|
||||
|
||||
UriBuilder redirectUri = UriBuilder.fromUri(appPage.getInjectedUrl().toString())
|
||||
.path("link")
|
||||
.queryParam("response", "true");
|
||||
|
||||
UriBuilder directLinking = UriBuilder.fromUri(getAuthServerContextRoot() + "/auth")
|
||||
.path("realms/child/broker/{provider}/link")
|
||||
.queryParam("client_id", "client-linking")
|
||||
.queryParam("redirect_uri", redirectUri.build())
|
||||
.queryParam("hash", Base64Url.encode("crap".getBytes()))
|
||||
.queryParam("nonce", UUID.randomUUID().toString());
|
||||
|
||||
String linkUrl = directLinking
|
||||
.build(PARENT_IDP).toString();
|
||||
|
||||
// test not logged in
|
||||
|
||||
navigateTo(linkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
|
||||
Assert.assertTrue(driver.getCurrentUrl().contains("link_error=not_logged_in"));
|
||||
|
||||
logoutAll();
|
||||
|
||||
// now log in
|
||||
|
||||
|
||||
navigateTo(helloUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(helloUrl));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Unknown request:"));
|
||||
|
||||
// now test CSRF with bad hash.
|
||||
|
||||
navigateTo(linkUrl);
|
||||
|
||||
Assert.assertTrue(driver.getPageSource().contains("We are sorry..."));
|
||||
|
||||
logoutAll();
|
||||
|
||||
// now log in again with client that does not have scope
|
||||
|
||||
String accountId = adminClient.realms().realm(CHILD_IDP).clients().findByClientId(ACCOUNT_MANAGEMENT_CLIENT_ID).get(0).getId();
|
||||
RoleRepresentation manageAccount = adminClient.realms().realm(CHILD_IDP).clients().get(accountId).roles().get(MANAGE_ACCOUNT).toRepresentation();
|
||||
RoleRepresentation manageLinks = adminClient.realms().realm(CHILD_IDP).clients().get(accountId).roles().get(MANAGE_ACCOUNT_LINKS).toRepresentation();
|
||||
RoleRepresentation userRole = adminClient.realms().realm(CHILD_IDP).roles().get("user").toRepresentation();
|
||||
|
||||
client.setFullScopeAllowed(false);
|
||||
ClientResource clientResource = adminClient.realms().realm(CHILD_IDP).clients().get(client.getId());
|
||||
clientResource.update(client);
|
||||
|
||||
List<RoleRepresentation> roles = new LinkedList<>();
|
||||
roles.add(userRole);
|
||||
clientResource.getScopeMappings().realmLevel().add(roles);
|
||||
|
||||
navigateTo(helloUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(helloUrl));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Unknown request:"));
|
||||
|
||||
|
||||
UriBuilder linkBuilder = UriBuilder.fromUri(appPage.getInjectedUrl().toString())
|
||||
.path("link");
|
||||
String clientLinkUrl = linkBuilder.clone()
|
||||
.queryParam("realm", CHILD_IDP)
|
||||
.queryParam("provider", PARENT_IDP).build().toString();
|
||||
|
||||
|
||||
navigateTo(clientLinkUrl);
|
||||
|
||||
Assert.assertTrue(driver.getCurrentUrl().contains("error=not_allowed"));
|
||||
|
||||
logoutAll();
|
||||
|
||||
// add MANAGE_ACCOUNT_LINKS scope should pass.
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
|
||||
roles = new LinkedList<>();
|
||||
roles.add(manageLinks);
|
||||
clientResource.getScopeMappings().clientLevel(accountId).add(roles);
|
||||
|
||||
navigateTo(clientLinkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue(loginPage.isCurrent(PARENT_IDP));
|
||||
loginPage.login(PARENT_USERNAME, "password");
|
||||
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(linkBuilder.toTemplate()));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Account Linked"));
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertFalse(links.isEmpty());
|
||||
|
||||
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
clientResource.getScopeMappings().clientLevel(accountId).remove(roles);
|
||||
|
||||
logoutAll();
|
||||
|
||||
navigateTo(clientLinkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
|
||||
Assert.assertTrue(driver.getCurrentUrl().contains("link_error=not_allowed"));
|
||||
|
||||
logoutAll();
|
||||
|
||||
// add MANAGE_ACCOUNT scope should pass
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
|
||||
roles = new LinkedList<>();
|
||||
roles.add(manageAccount);
|
||||
clientResource.getScopeMappings().clientLevel(accountId).add(roles);
|
||||
|
||||
navigateTo(clientLinkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue(loginPage.isCurrent(PARENT_IDP));
|
||||
loginPage.login(PARENT_USERNAME, "password");
|
||||
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(linkBuilder.toTemplate()));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Account Linked"));
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertFalse(links.isEmpty());
|
||||
|
||||
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
clientResource.getScopeMappings().clientLevel(accountId).remove(roles);
|
||||
|
||||
logoutAll();
|
||||
|
||||
navigateTo(clientLinkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
|
||||
Assert.assertTrue(driver.getCurrentUrl().contains("link_error=not_allowed"));
|
||||
|
||||
logoutAll();
|
||||
|
||||
|
||||
// undo fullScopeAllowed
|
||||
|
||||
client = adminClient.realms().realm(CHILD_IDP).clients().findByClientId("client-linking").get(0);
|
||||
client.setFullScopeAllowed(true);
|
||||
clientResource.update(client);
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
logoutAll();
|
||||
}
|
||||
|
||||
// TODO remove this once DYNAMIC_SCOPES feature is enabled by default
|
||||
@Test
|
||||
@EnableFeature(value = Profile.Feature.DYNAMIC_SCOPES, skipRestart = true)
|
||||
public void testErrorConditionsWithDynamicScope() throws Exception {
|
||||
// Just use existing test with DYNAMIC_SCOPES feature enabled as it was failing with DYNAMIC_SCOPES
|
||||
testErrorConditions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccountLink() throws Exception {
|
||||
linkAccount();
|
||||
|
||||
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest(CHILD_IDP, "child", "password", null, "client-linking", "password");
|
||||
Assert.assertNotNull(response.getAccessToken());
|
||||
Assert.assertNull(response.getError());
|
||||
Client httpClient = AdminClientUtil.createResteasyClient();
|
||||
String firstToken = getToken(response, httpClient);
|
||||
Assert.assertNotNull(firstToken);
|
||||
|
||||
navigateToAccountLinkPage();
|
||||
Assert.assertTrue(driver.getPageSource().contains("Account Linked"));
|
||||
String nextToken = getToken(response, httpClient);
|
||||
Assert.assertNotNull(nextToken);
|
||||
Assert.assertNotEquals(firstToken, nextToken);
|
||||
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertFalse(links.isEmpty());
|
||||
|
||||
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
logoutAll();
|
||||
}
|
||||
|
||||
// TODO remove this once DYNAMIC_SCOPES feature is enabled by default
|
||||
@Test
|
||||
@EnableFeature(value = Profile.Feature.DYNAMIC_SCOPES, skipRestart = true)
|
||||
public void testAccountLinkWithDynamicScope() throws Exception {
|
||||
// Just use existing test with DYNAMIC_SCOPES feature enabled as it was failing with DYNAMIC_SCOPES
|
||||
testAccountLink();
|
||||
}
|
||||
|
||||
private String getToken(OAuthClient.AccessTokenResponse response, Client httpClient) throws Exception {
|
||||
String idpToken = httpClient.target(OAuthClient.AUTH_SERVER_ROOT)
|
||||
.path("realms")
|
||||
.path("child/broker")
|
||||
.path(PARENT_IDP)
|
||||
.path("token")
|
||||
.request()
|
||||
.header("Authorization", "Bearer " + response.getAccessToken())
|
||||
.get(String.class);
|
||||
AccessTokenResponse res = JsonSerialization.readValue(idpToken, AccessTokenResponse.class);
|
||||
return res.getToken();
|
||||
}
|
||||
|
||||
public void logoutAll() {
|
||||
adminClient.realm(CHILD_IDP).logoutAll();
|
||||
adminClient.realm(PARENT_IDP).logoutAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLinkOnlyProvider() throws Exception {
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
IdentityProviderRepresentation rep = realm.identityProviders().get(PARENT_IDP).toRepresentation();
|
||||
rep.setLinkOnly(true);
|
||||
realm.identityProviders().get(PARENT_IDP).update(rep);
|
||||
try {
|
||||
|
||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
UriBuilder linkBuilder = UriBuilder.fromUri(appPage.getInjectedUrl().toString())
|
||||
.path("link");
|
||||
String linkUrl = linkBuilder.clone()
|
||||
.queryParam("realm", CHILD_IDP)
|
||||
.queryParam("provider", PARENT_IDP).build().toString();
|
||||
navigateTo(linkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
|
||||
// should not be on login page. This is what we are testing
|
||||
Assert.assertFalse(driver.getPageSource().contains(PARENT_IDP));
|
||||
|
||||
// now test that we can still link.
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue(loginPage.isCurrent(PARENT_IDP));
|
||||
loginPage.login(PARENT_USERNAME, "password");
|
||||
System.out.println("After linking: " + driver.getCurrentUrl());
|
||||
System.out.println(driver.getPageSource());
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(linkBuilder.toTemplate()));
|
||||
Assert.assertTrue(driver.getPageSource().contains("Account Linked"));
|
||||
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertFalse(links.isEmpty());
|
||||
|
||||
realm.users().get(childUserId).removeFederatedIdentity(PARENT_IDP);
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
logoutAll();
|
||||
|
||||
System.out.println("testing link-only attack");
|
||||
|
||||
navigateTo(linkUrl);
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
|
||||
System.out.println("login page uri is: " + driver.getCurrentUrl());
|
||||
|
||||
// ok, now scrape the code from page
|
||||
String pageSource = driver.getPageSource();
|
||||
String action = ActionURIUtils.getActionURIFromPageSource(pageSource);
|
||||
System.out.println("action uri: " + action);
|
||||
|
||||
Map<String, String> queryParams = ActionURIUtils.parseQueryParamsFromActionURI(action);
|
||||
System.out.println("query params: " + queryParams);
|
||||
|
||||
// now try and use the code to login to remote link-only idp
|
||||
|
||||
String uri = "/auth/realms/child/broker/parent-idp/login";
|
||||
|
||||
uri = UriBuilder.fromUri(getAuthServerContextRoot())
|
||||
.path(uri)
|
||||
.queryParam(LoginActionsService.SESSION_CODE, queryParams.get(LoginActionsService.SESSION_CODE))
|
||||
.queryParam(Constants.CLIENT_ID, queryParams.get(Constants.CLIENT_ID))
|
||||
.queryParam(Constants.TAB_ID, queryParams.get(Constants.TAB_ID))
|
||||
.build().toString();
|
||||
|
||||
System.out.println("hack uri: " + uri);
|
||||
|
||||
navigateTo(uri);
|
||||
|
||||
Assert.assertTrue(driver.getPageSource().contains("Could not send authentication request to identity provider."));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} finally {
|
||||
|
||||
rep.setLinkOnly(false);
|
||||
realm.identityProviders().get(PARENT_IDP).update(rep);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccountLinkingExpired() {
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
// Login to application first
|
||||
appPage.navigateTo();
|
||||
WaitUtils.waitForPageToLoad();
|
||||
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
loginPage.login("child", "password");
|
||||
|
||||
// Now in another tab, request account linking
|
||||
UriBuilder linkBuilder = UriBuilder.fromUri(appPage.getInjectedUrl().toString())
|
||||
.path("link");
|
||||
String linkUrl = linkBuilder.clone()
|
||||
.queryParam("realm", CHILD_IDP)
|
||||
.queryParam("provider", PARENT_IDP).build().toString();
|
||||
navigateTo(linkUrl);
|
||||
|
||||
Assert.assertTrue(loginPage.isCurrent(PARENT_IDP));
|
||||
|
||||
// Logout "child" userSession in the meantime (for example through admin request)
|
||||
realm.logoutAll();
|
||||
|
||||
// Finish login on parent.
|
||||
loginPage.login(PARENT_USERNAME, "password");
|
||||
|
||||
// Test I was not automatically linked
|
||||
links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
errorPage.assertCurrent();
|
||||
Assert.assertEquals("Requested broker account linking, but current session is no longer valid.", errorPage.getError());
|
||||
|
||||
logoutAll();
|
||||
}
|
||||
|
||||
private void navigateTo(String uri) {
|
||||
driver.navigate().to(uri);
|
||||
WaitUtils.waitForPageToLoad();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccountLinkWithHardcodedMapper() throws Exception {
|
||||
driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.DAYS);
|
||||
addHardcodedAttributeMapper();
|
||||
linkAccount();
|
||||
assertHardcodedAttributeHasBeenAssigned();
|
||||
removeHardcodedAttribute();
|
||||
removeHardcodedAttributeMapper();
|
||||
logoutAll();
|
||||
}
|
||||
|
||||
private void addHardcodedAttributeMapper() {
|
||||
IdentityProviderResource provider = adminClient.realms().realm(CHILD_IDP).identityProviders().get(PARENT_IDP);
|
||||
|
||||
IdentityProviderMapperRepresentation mapper = new IdentityProviderMapperRepresentation();
|
||||
mapper.setIdentityProviderAlias(PARENT_IDP);
|
||||
mapper.setName(HARDCODED_ATTRIBUTE_MAPPER_NAME);
|
||||
mapper.setIdentityProviderMapper("hardcoded-attribute-idp-mapper");
|
||||
mapper.setConfig(Map.of(
|
||||
IdentityProviderMapperModel.SYNC_MODE, IdentityProviderMapperSyncMode.FORCE.toString(),
|
||||
HardcodedAttributeMapper.ATTRIBUTE, USER_ATTRIBUTE,
|
||||
HardcodedAttributeMapper.ATTRIBUTE_VALUE, USER_ATTRIBUTE_VALUE)
|
||||
);
|
||||
|
||||
mapper.setIdentityProviderAlias(PARENT_IDP);
|
||||
provider.addMapper(mapper).close();
|
||||
}
|
||||
|
||||
private void removeHardcodedAttributeMapper() {
|
||||
IdentityProviderResource provider = adminClient.realms().realm(CHILD_IDP).identityProviders().get(PARENT_IDP);
|
||||
Optional<IdentityProviderMapperRepresentation> mapper = provider.getMappers().stream()
|
||||
.filter(m -> m.getName().equals(HARDCODED_ATTRIBUTE_MAPPER_NAME)).findFirst();
|
||||
|
||||
Assert.assertFalse(mapper.isEmpty());
|
||||
|
||||
provider.delete(mapper.get().getId());
|
||||
}
|
||||
|
||||
private void assertHardcodedAttributeHasBeenAssigned() {
|
||||
UserRepresentation user = adminClient.realm(CHILD_IDP).users().get(childUserId).toRepresentation();
|
||||
Assert.assertEquals(USER_ATTRIBUTE_VALUE, user.firstAttribute(USER_ATTRIBUTE));
|
||||
}
|
||||
|
||||
private void removeHardcodedAttribute() {
|
||||
UserRepresentation user = adminClient.realm(CHILD_IDP).users().get(childUserId).toRepresentation();
|
||||
user.getAttributes().remove(USER_ATTRIBUTE);
|
||||
adminClient.realm(CHILD_IDP).users().get(user.getId()).update(user);
|
||||
}
|
||||
|
||||
private void linkAccount() {
|
||||
RealmResource realm = adminClient.realms().realm(CHILD_IDP);
|
||||
List<FederatedIdentityRepresentation> links = realm.users().get(childUserId).getFederatedIdentity();
|
||||
Assert.assertTrue(links.isEmpty());
|
||||
|
||||
navigateToAccountLinkPage();
|
||||
Assert.assertTrue(loginPage.isCurrent(CHILD_IDP));
|
||||
Assert.assertTrue(driver.getPageSource().contains(PARENT_IDP));
|
||||
loginPage.login("child", "password");
|
||||
Assert.assertTrue(loginPage.isCurrent(PARENT_IDP));
|
||||
loginPage.login(PARENT_USERNAME, "password");
|
||||
System.out.println("After linking: " + driver.getCurrentUrl());
|
||||
System.out.println(driver.getPageSource());
|
||||
Assert.assertTrue(driver.getPageSource().contains("Account Linked"));
|
||||
}
|
||||
|
||||
private void navigateToAccountLinkPage() {
|
||||
UriBuilder linkBuilder = UriBuilder.fromUri(appPage.getInjectedUrl().toString())
|
||||
.path("link");
|
||||
String linkUrl = linkBuilder.clone()
|
||||
.queryParam("realm", CHILD_IDP)
|
||||
.queryParam("provider", PARENT_IDP).build().toString();
|
||||
System.out.println("linkUrl: " + linkUrl);
|
||||
navigateTo(linkUrl);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,37 +0,0 @@
|
|||
package org.keycloak.testsuite.adapter.servlet;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.page.SerializationServletPage;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
// The purpose of this class is to test KeycloakPrincipal serialization on different app-server-jdks
|
||||
public class KeycloakPrincipalSerializationTest extends AbstractServletsAdapterTest {
|
||||
@Page
|
||||
protected SerializationServletPage serializationServlet;
|
||||
|
||||
@Deployment(name = SerializationServletPage.DEPLOYMENT_NAME)
|
||||
protected static WebArchive serializationServlet() {
|
||||
return servletDeployment(SerializationServletPage.DEPLOYMENT_NAME, SerializationServlet.class, ErrorServlet.class, ServletTestUtils.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKeycloakPrincipalSerialization() {
|
||||
serializationServlet.navigateTo();
|
||||
testRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
|
||||
assertThat(driver.getPageSource(), containsString("Serialization/Deserialization was successful"));
|
||||
assertThat(driver.getPageSource(), not(containsString("Context was not instance of RefreshableKeycloakSecurityContext")));
|
||||
assertThat(driver.getPageSource(), not(containsString("Deserialization failed")));
|
||||
}
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 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.servlet;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.page.MultiTenant;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.util.URLAssert;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
|
||||
import static org.keycloak.testsuite.utils.io.IOUtil.loadRealm;
|
||||
|
||||
/**
|
||||
* note: migrated from old testsuite
|
||||
*
|
||||
* @author Juraci Paixão Kröhling <juraci at kroehling.de>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class MultiTenancyTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
private MultiTenant tenantPage;
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(loadRealm("/adapter-test/tenant1-realm.json"));
|
||||
testRealms.add(loadRealm("/adapter-test/tenant2-realm.json"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isImportAfterEachMethod() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deployment(name = MultiTenant.DEPLOYMENT_NAME)
|
||||
protected static WebArchive multiTenant() {
|
||||
return servletDeploymentMultiTenant(MultiTenant.DEPLOYMENT_NAME, MultiTenantServlet.class, ErrorServlet.class, MultiTenantResolver.class);
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() {
|
||||
driver.manage().deleteAllCookies();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplest scenario: one user, one realm. The user is not logged in at
|
||||
* any other realm
|
||||
*/
|
||||
@Test
|
||||
public void testTenantsLoggingOut() {
|
||||
doTenantRequests("tenant1", true);
|
||||
doTenantRequests("tenant2", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests the adapter's ability to deal with multiple sessions
|
||||
* from the same user, one for each realm. It should not mixup and return
|
||||
* a session from tenant1 to tenant2
|
||||
*/
|
||||
@Test
|
||||
public void testTenantsWithoutLoggingOut() {
|
||||
doTenantRequests("tenant1", true);
|
||||
doTenantRequests("tenant2", true);
|
||||
|
||||
doTenantRequests("tenant1", false);
|
||||
doTenantRequests("tenant2", true);
|
||||
|
||||
logout("tenant1");
|
||||
}
|
||||
|
||||
/**
|
||||
* This test simulates an user that is not logged in yet, and tries to login
|
||||
* into tenant1 using an account from tenant2.
|
||||
* On this scenario, the user should be shown the login page again.
|
||||
*/
|
||||
@Test
|
||||
public void testUnauthorizedAccessNotLoggedIn() {
|
||||
String keycloakServerBaseUrl = authServerPage.toString();
|
||||
|
||||
driver.navigate().to(tenantPage.getTenantRealmUrl("tenant1"));
|
||||
WaitUtils.waitForPageToLoad();
|
||||
URLAssert.assertCurrentUrlStartsWith(keycloakServerBaseUrl);
|
||||
|
||||
testRealmLoginPage.form().login("user-tenant2", "user-tenant2");
|
||||
URLAssert.assertCurrentUrlStartsWith(keycloakServerBaseUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test simulates an user which is already logged in into tenant1
|
||||
* and tries to access a resource on tenant2.
|
||||
* On this scenario, the user should be shown the login page again.
|
||||
*/
|
||||
@Test
|
||||
public void testUnauthorizedAccessLoggedIn() {
|
||||
doTenantRequests("tenant1", false);
|
||||
|
||||
driver.navigate().to(tenantPage.getTenantRealmUrl("tenant2"));
|
||||
URLAssert.assertCurrentUrlStartsWith(authServerPage.toString());
|
||||
|
||||
logout("tenant1");
|
||||
}
|
||||
|
||||
private void doTenantRequests(String tenant, boolean logout) {
|
||||
String tenantLoginUrl = OIDCLoginProtocolService.authUrl(UriBuilder.fromUri(authServerPage.getAuthRoot())).build(tenant).toString();
|
||||
URL tenantUrl = tenantPage.getTenantRealmUrl(tenant);
|
||||
|
||||
driver.navigate().to(tenantUrl);
|
||||
URLAssert.assertCurrentUrlStartsWith(tenantLoginUrl);
|
||||
testRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
log.debug("Current url: " + driver.getCurrentUrl());
|
||||
|
||||
URLAssert.assertCurrentUrlStartsWith(tenantUrl.toString());
|
||||
String pageSource = driver.getPageSource();
|
||||
log.debug(pageSource);
|
||||
|
||||
Assert.assertTrue(pageSource.contains("Username: bburke@redhat.com"));
|
||||
Assert.assertTrue(pageSource.contains("Realm: " + tenant));
|
||||
|
||||
if (logout) {
|
||||
driver.navigate().to(tenantUrl + "/logout");
|
||||
Assert.assertFalse(driver.getPageSource().contains("Username: bburke@redhat.com"));
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(tenantLoginUrl));
|
||||
}
|
||||
log.debug("---------------------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
private void logout(String tenant) {
|
||||
String tenantLoginUrl = OIDCLoginProtocolService.authUrl(UriBuilder.fromUri(authServerPage.getAuthRoot())).build(tenant).toString();
|
||||
URL tenantUrl = tenantPage.getTenantRealmUrl(tenant);
|
||||
driver.navigate().to(tenantUrl + "/logout");
|
||||
Assert.assertFalse(driver.getPageSource().contains("Username: bburke@redhat.com"));
|
||||
Assert.assertTrue(driver.getCurrentUrl().startsWith(tenantLoginUrl));
|
||||
}
|
||||
}
|
|
@ -1,355 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.common.util.StreamUtil;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
import org.keycloak.crypto.Algorithm;
|
||||
import org.keycloak.crypto.KeyUse;
|
||||
import org.keycloak.keys.KeyProvider;
|
||||
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.action.GlobalRequestResult;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.representations.idm.KeysMetadataRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
|
||||
import org.keycloak.testsuite.adapter.page.CustomerDb;
|
||||
import org.keycloak.testsuite.adapter.page.SecurePortal;
|
||||
import org.keycloak.testsuite.adapter.page.TokenMinTTLPage;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.util.KeyUtils;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.util.URLAssert;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||
|
||||
/**
|
||||
* Tests related to public key rotation for OIDC adapter
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class OIDCPublicKeyRotationAdapterTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
private SecurePortal securePortal;
|
||||
|
||||
@Page
|
||||
private TokenMinTTLPage tokenMinTTLPage;
|
||||
|
||||
@Page
|
||||
private CustomerDb customerDb;
|
||||
|
||||
@Deployment(name = SecurePortal.DEPLOYMENT_NAME)
|
||||
protected static WebArchive securePortal() {
|
||||
return servletDeployment(SecurePortal.DEPLOYMENT_NAME, AdapterActionsFilter.class, CallAuthenticatedServlet.class);
|
||||
}
|
||||
|
||||
@Deployment(name = TokenMinTTLPage.DEPLOYMENT_NAME)
|
||||
protected static WebArchive tokenMinTTLPage() {
|
||||
return servletDeployment(TokenMinTTLPage.DEPLOYMENT_NAME, AdapterActionsFilter.class, AbstractShowTokensServlet.class, TokenMinTTLServlet.class, ErrorServlet.class);
|
||||
}
|
||||
|
||||
@Deployment(name = CustomerDb.DEPLOYMENT_NAME)
|
||||
protected static WebArchive customerDb() {
|
||||
return servletDeployment(CustomerDb.DEPLOYMENT_NAME, AdapterActionsFilter.class, CustomerDatabaseServlet.class);
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void beforeRotationAdapterTest() {
|
||||
// Delete all cookies from token-min-ttl page to be sure we are logged out
|
||||
tokenMinTTLPage.navigateTo();
|
||||
driver.manage().deleteAllCookies();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRealmKeyRotationWithNewKeyDownload() throws Exception {
|
||||
// Login success first
|
||||
loginToTokenMinTtlApp();
|
||||
|
||||
// Logout
|
||||
ApiUtil.findUserByUsernameId(adminClient.realm("demo"), "bburke@redhat.com").logout();
|
||||
|
||||
// Generate new realm keys
|
||||
generateNewRealmKey(KeyUse.SIG);
|
||||
generateNewRealmKey(KeyUse.ENC);
|
||||
|
||||
// Try to login again. It should fail now because not yet allowed to download new keys
|
||||
tokenMinTTLPage.navigateTo();
|
||||
assertTrue(testRealmLoginPage.form().isUsernamePresent());
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
testRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
URLAssert.assertCurrentUrlStartsWith(tokenMinTTLPage.getInjectedUrl().toString());
|
||||
|
||||
ApiUtil.findUserByUsernameId(adminClient.realm("demo"), "bburke@redhat.com").logout();
|
||||
|
||||
setAdapterAndServerTimeOffset(300, tokenMinTTLPage.toString() + "/unsecured/foo");
|
||||
|
||||
// Try to login. Should work now due to realm key change
|
||||
loginToTokenMinTtlApp();
|
||||
ApiUtil.findUserByUsernameId(adminClient.realm("demo"), "bburke@redhat.com").logout();
|
||||
|
||||
// Revert public keys change
|
||||
resetKeycloakDeploymentForAdapter(tokenMinTTLPage.toString() + "/unsecured/foo");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testClientWithJwksUri() throws Exception {
|
||||
// Set client to bad JWKS URI
|
||||
ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "secure-portal");
|
||||
ClientRepresentation client = clientResource.toRepresentation();
|
||||
OIDCAdvancedConfigWrapper wrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client);
|
||||
wrapper.setUseJwksUrl(true);
|
||||
wrapper.setJwksUrl(securePortal + "/bad-jwks-url");
|
||||
clientResource.update(client);
|
||||
|
||||
// Login should fail at the code-to-token
|
||||
securePortal.navigateTo();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
testRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
String pageSource = driver.getPageSource();
|
||||
assertCurrentUrlStartsWith(securePortal);
|
||||
assertFalse(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen"));
|
||||
|
||||
// Set client to correct JWKS URI
|
||||
client = clientResource.toRepresentation();
|
||||
wrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client);
|
||||
wrapper.setUseJwksUrl(true);
|
||||
wrapper.setJwksUrl(securePortal + "/" + AdapterConstants.K_JWKS);
|
||||
clientResource.update(client);
|
||||
|
||||
// Login to secure-portal should be fine now. Client keys downloaded from JWKS URI
|
||||
securePortal.navigateTo();
|
||||
assertCurrentUrlEquals(securePortal);
|
||||
pageSource = driver.getPageSource();
|
||||
assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen"));
|
||||
|
||||
// Logout
|
||||
ApiUtil.findUserByUsernameId(adminClient.realm("demo"), "bburke@redhat.com").logout();
|
||||
}
|
||||
|
||||
|
||||
// KEYCLOAK-3824: Test for public-key-cache-ttl
|
||||
@Test
|
||||
public void testPublicKeyCacheTtl() {
|
||||
String customerDBUnsecuredUrl = customerDb.getUriBuilder().clone().path("unsecured").path("foo").build().toASCIIString();
|
||||
String tokenMinTTLUnsecuredUrl = tokenMinTTLPage.getUriBuilder().clone().path("unsecured").path("foo").build().toASCIIString();
|
||||
|
||||
// increase accessTokenLifespan to 1200
|
||||
RealmRepresentation demoRealm = adminClient.realm(DEMO).toRepresentation();
|
||||
demoRealm.setAccessTokenLifespan(1200);
|
||||
adminClient.realm(DEMO).update(demoRealm);
|
||||
|
||||
// authenticate in tokenMinTTL app
|
||||
loginToTokenMinTtlApp();
|
||||
String accessTokenString = tokenMinTTLPage.getAccessTokenString();
|
||||
|
||||
// Send REST request to customer-db app. I should be successfully authenticated
|
||||
int status = invokeRESTEndpoint(accessTokenString);
|
||||
Assert.assertEquals(200, status);
|
||||
|
||||
// Re-generate realm public key and remove the old key (for both sig and enc)
|
||||
String oldActiveKeyProviderId = getActiveKeyProviderId(KeyUse.SIG);
|
||||
generateNewRealmKey(KeyUse.SIG);
|
||||
adminClient.realm(DEMO).components().component(oldActiveKeyProviderId).remove();
|
||||
oldActiveKeyProviderId = getActiveKeyProviderId(KeyUse.ENC);
|
||||
generateNewRealmKey(KeyUse.ENC);
|
||||
adminClient.realm(DEMO).components().component(oldActiveKeyProviderId).remove();
|
||||
|
||||
// Send REST request to the customer-db app. Should be still succcessfully authenticated as the JWKPublicKeyLocator cache is still valid
|
||||
status = invokeRESTEndpoint(accessTokenString);
|
||||
Assert.assertEquals(200, status);
|
||||
|
||||
// TimeOffset to 900 on the REST app side. Token is still valid (1200) but JWKPublicKeyLocator should try to download new key (public-key-cache-ttl=600)
|
||||
setAdapterAndServerTimeOffset(900, customerDBUnsecuredUrl, tokenMinTTLUnsecuredUrl);
|
||||
|
||||
// Send REST request. New request to the publicKey cache should be sent, and key is no longer returned as token contains the old kid
|
||||
status = invokeRESTEndpoint(accessTokenString);
|
||||
Assert.assertEquals(401, status);
|
||||
|
||||
// Revert public keys change and time offset
|
||||
resetKeycloakDeploymentForAdapter(customerDBUnsecuredUrl);
|
||||
resetKeycloakDeploymentForAdapter(tokenMinTTLUnsecuredUrl);
|
||||
}
|
||||
|
||||
|
||||
// KEYCLOAK-3823: Test that sending notBefore policy invalidates JWKPublicKeyLocator cache
|
||||
@Test
|
||||
public void testPublicKeyCacheInvalidatedWhenPushedNotBefore() {
|
||||
driver.manage().timeouts().pageLoadTimeout(1000, TimeUnit.SECONDS);
|
||||
String customerDBUnsecuredUrl = customerDb.getUriBuilder().clone().path("unsecured").path("foo").build().toASCIIString();
|
||||
String customerDBUrlNoTrailSlash = customerDb.getUriBuilder().build().toASCIIString();
|
||||
customerDBUrlNoTrailSlash = customerDBUrlNoTrailSlash.substring(0, customerDBUrlNoTrailSlash.length() - 1);
|
||||
String tokenMinTTLUnsecuredUrl = tokenMinTTLPage.getUriBuilder().clone().path("unsecured").path("foo").build().toASCIIString();
|
||||
|
||||
// increase accessTokenLifespan to 1200
|
||||
RealmRepresentation demoRealm = adminClient.realm(DEMO).toRepresentation();
|
||||
demoRealm.setAccessTokenLifespan(1200);
|
||||
adminClient.realm(DEMO).update(demoRealm);
|
||||
|
||||
// authenticate in tokenMinTTL app
|
||||
loginToTokenMinTtlApp();
|
||||
String accessTokenString = tokenMinTTLPage.getAccessTokenString();
|
||||
|
||||
// Generate new realm public key
|
||||
String oldActiveSigKeyProviderId = getActiveKeyProviderId(KeyUse.SIG);
|
||||
generateNewRealmKey(KeyUse.SIG);
|
||||
String oldActiveEncKeyProviderId = getActiveKeyProviderId(KeyUse.ENC);
|
||||
generateNewRealmKey(KeyUse.ENC);
|
||||
|
||||
// Send REST request to customer-db app. It should be successfully authenticated even that token is signed by the old key
|
||||
int status = invokeRESTEndpoint(accessTokenString);
|
||||
Assert.assertEquals(200, status);
|
||||
|
||||
// Remove the old realm keys now
|
||||
adminClient.realm(DEMO).components().component(oldActiveSigKeyProviderId).remove();
|
||||
adminClient.realm(DEMO).components().component(oldActiveEncKeyProviderId).remove();
|
||||
|
||||
// Set some offset to ensure pushing notBefore will pass
|
||||
setAdapterAndServerTimeOffset(130, customerDBUnsecuredUrl, tokenMinTTLUnsecuredUrl);
|
||||
|
||||
// Send notBefore policy from the realm
|
||||
demoRealm.setNotBefore(Time.currentTime() - 1);
|
||||
adminClient.realm(DEMO).update(demoRealm);
|
||||
GlobalRequestResult result = adminClient.realm(DEMO).pushRevocation();
|
||||
Assert.assertTrue(result.getSuccessRequests().contains(customerDBUrlNoTrailSlash));
|
||||
|
||||
// Send REST request. New request to the publicKey cache should be sent, and key is no longer returned as token contains the old kid
|
||||
status = invokeRESTEndpoint(accessTokenString);
|
||||
Assert.assertEquals(401, status);
|
||||
|
||||
// Revert public keys change and time offset
|
||||
resetKeycloakDeploymentForAdapter(customerDBUnsecuredUrl);
|
||||
resetKeycloakDeploymentForAdapter(tokenMinTTLUnsecuredUrl);
|
||||
}
|
||||
|
||||
|
||||
// HELPER METHODS
|
||||
|
||||
private void loginToTokenMinTtlApp() {
|
||||
tokenMinTTLPage.navigateTo();
|
||||
assertTrue(testRealmLoginPage.form().isUsernamePresent());
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
testRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
assertCurrentUrlEquals(tokenMinTTLPage);
|
||||
|
||||
AccessToken token = tokenMinTTLPage.getAccessToken();
|
||||
Assert.assertEquals("bburke@redhat.com", token.getPreferredUsername());
|
||||
}
|
||||
|
||||
|
||||
private void generateNewRealmKey(KeyUse keyUse) {
|
||||
String realmId = adminClient.realm(DEMO).toRepresentation().getId();
|
||||
|
||||
ComponentRepresentation keys = new ComponentRepresentation();
|
||||
keys.setName("generated");
|
||||
keys.setProviderType(KeyProvider.class.getName());
|
||||
keys.setProviderId(keyUse == KeyUse.SIG ? "rsa-generated" : "rsa-enc-generated");
|
||||
keys.setParentId(realmId);
|
||||
keys.setConfig(new MultivaluedHashMap<>());
|
||||
keys.getConfig().putSingle("priority", "150");
|
||||
keys.getConfig().putSingle("keyUse", keyUse.getSpecName());
|
||||
Response response = adminClient.realm(DEMO).components().add(keys);
|
||||
assertEquals(201, response.getStatus());
|
||||
response.close();
|
||||
}
|
||||
|
||||
private String getActiveKeyProviderId(KeyUse keyUse) {
|
||||
KeysMetadataRepresentation.KeyMetadataRepresentation key = keyUse == KeyUse.ENC
|
||||
? KeyUtils.findActiveEncryptingKey(adminClient.realm(DEMO), Algorithm.RSA_OAEP)
|
||||
: KeyUtils.findActiveSigningKey(adminClient.realm(DEMO), Algorithm.RS256);
|
||||
|
||||
return key != null ? key.getProviderId() : null;
|
||||
}
|
||||
|
||||
private int invokeRESTEndpoint(String accessTokenString) {
|
||||
|
||||
try (CloseableHttpClient client = HttpClientBuilder.create().build()) {
|
||||
String restUrl = customerDb.toString();
|
||||
HttpGet get = new HttpGet(restUrl);
|
||||
get.addHeader("Authorization", "Bearer " + accessTokenString);
|
||||
try {
|
||||
HttpResponse response = client.execute(get);
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
if (status != 200) {
|
||||
return status;
|
||||
}
|
||||
|
||||
HttpEntity entity = response.getEntity();
|
||||
try (InputStream is = entity.getContent()) {
|
||||
String body = StreamUtil.readString(is, Charset.forName("UTF-8"));
|
||||
Assert.assertTrue(body.contains("Stian Thorgersen") && body.contains("Bill Burke"));
|
||||
return status;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void resetKeycloakDeploymentForAdapter(String adapterActionsUrl) {
|
||||
String timeOffsetUri = UriBuilder.fromUri(adapterActionsUrl)
|
||||
.queryParam(AdapterActionsFilter.RESET_DEPLOYMENT_PARAM, "true")
|
||||
.build().toString();
|
||||
driver.navigate().to(timeOffsetUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,275 +0,0 @@
|
|||
package org.keycloak.testsuite.adapter.servlet;
|
||||
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
|
||||
import org.keycloak.testsuite.adapter.page.OfflineToken;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
|
||||
import org.keycloak.testsuite.util.AccountHelper;
|
||||
import org.keycloak.testsuite.util.InfinispanTestTimeServiceRule;
|
||||
import org.keycloak.testsuite.util.WaitUtils;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.pages.OAuthGrantPage;
|
||||
import org.keycloak.testsuite.utils.io.IOUtil;
|
||||
import org.keycloak.util.TokenUtil;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlDoesntStartWith;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>.
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class OfflineServletsAdapterTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(this);
|
||||
@Page
|
||||
protected OfflineToken offlineTokenPage;
|
||||
@Page
|
||||
protected LoginPage loginPage;
|
||||
@Page
|
||||
protected OAuthGrantPage oauthGrantPage;
|
||||
|
||||
@Rule
|
||||
public InfinispanTestTimeServiceRule ispnTestTimeService = new InfinispanTestTimeServiceRule(this);
|
||||
|
||||
private final String DEFAULT_USERNAME = "test-user@localhost";
|
||||
private final String DEFAULT_PASSWORD = "password";
|
||||
private final String OFFLINE_CLIENT_ID = "offline-client";
|
||||
|
||||
/**
|
||||
* URL in the deployment that doesn't require authentication and which therefore can be used to trigger activities in the actionfilter.
|
||||
*/
|
||||
private static final String UNSECURED_URL = "unsecured/foo";
|
||||
|
||||
@Deployment(name = OfflineToken.DEPLOYMENT_NAME)
|
||||
protected static WebArchive offlineClient() {
|
||||
return servletDeployment(OfflineToken.DEPLOYMENT_NAME, AdapterActionsFilter.class, AbstractShowTokensServlet.class, OfflineTokenServlet.class, ErrorServlet.class, ServletTestUtils.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
super.setDefaultPageUriParameters();
|
||||
testRealmPage.setAuthRealm(TEST);
|
||||
testRealmLoginPage.setAuthRealm(TEST);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addAdapterTestRealms(List<RealmRepresentation> testRealms) {
|
||||
testRealms.add(IOUtil.loadRealm("/adapter-test/offline-client/offlinerealm.json"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isImportAfterEachMethod() {
|
||||
// For proper cleanup of test methods
|
||||
return true;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServlet() {
|
||||
try {
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
oauth.redirectUri(offlineTokenPage.toString());
|
||||
oauth.clientId("offline-client");
|
||||
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
RefreshToken refreshToken = offlineTokenPage.getRefreshToken();
|
||||
assertThat(TokenUtil.TOKEN_TYPE_OFFLINE, is(refreshToken.getType()));
|
||||
assertThat(refreshToken.getExp(), nullValue());
|
||||
|
||||
String accessTokenId = offlineTokenPage.getAccessToken().getId();
|
||||
String refreshTokenId = refreshToken.getId();
|
||||
|
||||
// online user session will be expired and removed
|
||||
setAdapterAndServerTimeOffset(9999);
|
||||
|
||||
// still able to access the page using the offline token
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
// assert successful refresh
|
||||
assertThat(offlineTokenPage.getRefreshToken().getId(), not(refreshTokenId));
|
||||
assertThat(offlineTokenPage.getAccessToken().getId(), not(accessTokenId));
|
||||
|
||||
// logout doesn't make sense because online user session is gone and there is no KEYCLOAK_IDENTITY / KEYCLOAK_SESSION cookie in the browser
|
||||
// navigate to login page which won't be possible if there's valid online session
|
||||
driver.navigate().to(oauth.getLoginFormUrl());
|
||||
WaitUtils.waitForPageToLoad();
|
||||
loginPage.assertCurrent();
|
||||
|
||||
// navigate back to offlineTokenPage to verify the offline session is still valid
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
// logout the offline user session using the offline refresh token
|
||||
oauth.doLogout(offlineTokenPage.getRefreshTokenString(), "secret1");
|
||||
|
||||
// can't access the offlineTokenPage anymore
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
} finally {
|
||||
events.clear();
|
||||
resetTimeOffset();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServletWithRevoke() {
|
||||
try { // Login to servlet first with offline token
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
final RefreshToken refreshToken = offlineTokenPage.getRefreshToken();
|
||||
assertThat(refreshToken.getType(), is(TokenUtil.TOKEN_TYPE_OFFLINE));
|
||||
|
||||
// Assert refresh works with increased time
|
||||
setAdapterAndServerTimeOffset(9999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
setAdapterAndServerTimeOffset(0);
|
||||
|
||||
events.clear();
|
||||
|
||||
// Check that Offline Token is granted
|
||||
List<Map<String, Object>> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME);
|
||||
String actualValue = String.valueOf(((LinkedHashMap) ((ArrayList) userConsents.get(0).get("additionalGrants")).get(0)).get("key"));
|
||||
Assert.assertEquals("Offline Token", actualValue);
|
||||
|
||||
// Revoke consents
|
||||
AccountHelper.revokeConsents(adminClient.realm(TEST), DEFAULT_USERNAME, OFFLINE_CLIENT_ID);
|
||||
pause(500);
|
||||
|
||||
userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME);
|
||||
assertThat(userConsents.size(), is(0));
|
||||
|
||||
// Assert refresh doesn't work now (increase time one more time)
|
||||
setAdapterAndServerTimeOffset(19999);
|
||||
offlineTokenPage.navigateTo();
|
||||
assertCurrentUrlDoesntStartWith(offlineTokenPage);
|
||||
loginPage.assertCurrent();
|
||||
} finally {
|
||||
events.clear();
|
||||
resetTimeOffset();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServletWithConsent() throws IOException {
|
||||
try (Closeable cau = ClientAttributeUpdater.forClient(adminClient, TEST, OFFLINE_CLIENT_ID)
|
||||
.setConsentRequired(true).update()) {
|
||||
|
||||
// Assert grant page doesn't have 'Offline Access' role when offline token is not requested
|
||||
offlineTokenPage.navigateTo();
|
||||
|
||||
loginPage.assertCurrent();
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
|
||||
oauthGrantPage.assertCurrent();
|
||||
waitUntilElement(By.xpath("//body")).text().not().contains("Offline access");
|
||||
oauthGrantPage.cancel();
|
||||
|
||||
// Assert grant page has 'Offline Access' role now
|
||||
String servletUri = UriBuilder.fromUri(offlineTokenPage.toString())
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.OFFLINE_ACCESS)
|
||||
.build().toString();
|
||||
driver.navigate().to(servletUri);
|
||||
waitUntilElement(By.tagName("body")).is().visible();
|
||||
|
||||
loginPage.login(DEFAULT_USERNAME, DEFAULT_PASSWORD);
|
||||
oauthGrantPage.assertCurrent();
|
||||
waitUntilElement(By.xpath("//body")).text().contains(OAuthGrantPage.OFFLINE_ACCESS_CONSENT_TEXT);
|
||||
|
||||
oauthGrantPage.accept();
|
||||
|
||||
assertCurrentUrlStartsWith(offlineTokenPage);
|
||||
|
||||
RefreshToken refreshToken = offlineTokenPage.getRefreshToken();
|
||||
assertThat(refreshToken.getType(), is(TokenUtil.TOKEN_TYPE_OFFLINE));
|
||||
|
||||
// Check that the client scopes have been granted by the user
|
||||
List<Map<String, Object>> userConsents = AccountHelper.getUserConsents(adminClient.realm(TEST), DEFAULT_USERNAME);
|
||||
Assert.assertTrue(((List) userConsents.get(0).get("grantedClientScopes")).stream().anyMatch(p -> p.equals("offline_access")));
|
||||
String actualValue = String.valueOf(((LinkedHashMap) ((ArrayList) userConsents.get(0).get("additionalGrants")).get(0)).get("key"));
|
||||
Assert.assertEquals("Offline Token", actualValue);
|
||||
|
||||
AccountHelper.logout(adminClient.realm(TEST), DEFAULT_USERNAME);
|
||||
} finally {
|
||||
events.clear();
|
||||
resetTimeOffset();
|
||||
}
|
||||
}
|
||||
|
||||
private void setAdapterAndServerTimeOffset(int timeOffset) {
|
||||
super.setAdapterAndServerTimeOffset(timeOffset, offlineTokenPage.toString() + UNSECURED_URL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTimeOffset() {
|
||||
setAdapterServletTimeOffset(0, offlineTokenPage.toString() + UNSECURED_URL);
|
||||
super.resetTimeOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterAbstractKeycloakTestRealmImport() {
|
||||
// after each re-import, ensure that the information stored in JWKPublicKeyLocator is reset
|
||||
String resetDeploymentUri = UriBuilder.fromUri(offlineTokenPage.toString() + UNSECURED_URL)
|
||||
.queryParam(AdapterActionsFilter.RESET_DEPLOYMENT_PARAM, "true")
|
||||
.build().toString();
|
||||
driver.navigate().to(resetDeploymentUri);
|
||||
waitForPageToLoad();
|
||||
|
||||
assertThat(driver.getPageSource(), containsString("Restarted PublicKeyLocator"));
|
||||
super.afterAbstractKeycloakTestRealmImport();
|
||||
}
|
||||
|
||||
}
|
|
@ -25,9 +25,9 @@ import org.jboss.arquillian.container.test.api.Deployment;
|
|||
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.adapters.rotation.PublicKeyLocator;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter;
|
||||
import org.keycloak.testsuite.adapter.page.SalesPostClockSkewServlet;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.util.SamlClientBuilder;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
@ -39,7 +39,6 @@ import static org.hamcrest.Matchers.not;
|
|||
import org.jboss.arquillian.graphene.page.Page;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import org.keycloak.testsuite.adapter.page.SalesPostClockSkewServlet;
|
||||
import static org.keycloak.testsuite.util.SamlClient.Binding.POST;
|
||||
|
||||
|
||||
|
@ -57,16 +56,16 @@ public class SAMLClockSkewAdapterTest extends AbstractSAMLServletAdapterTest {
|
|||
|
||||
@Deployment(name = DEPLOYMENT_NAME_3_SEC, managed = false)
|
||||
protected static WebArchive salesPostClockSkewServlet3Sec() {
|
||||
return samlServletDeployment(SalesPostClockSkewServlet.DEPLOYMENT_NAME, DEPLOYMENT_NAME_3_SEC, SalesPostClockSkewServlet.DEPLOYMENT_NAME + "/WEB-INF/web.xml", 3, AdapterActionsFilter.class, PublicKeyLocator.class, SendUsernameServlet.class);
|
||||
return samlServletDeployment(SalesPostClockSkewServlet.DEPLOYMENT_NAME, DEPLOYMENT_NAME_3_SEC, SalesPostClockSkewServlet.DEPLOYMENT_NAME + "/WEB-INF/web.xml", 3, AdapterActionsFilter.class, SendUsernameServlet.class);
|
||||
}
|
||||
@Deployment(name = DEPLOYMENT_NAME_30_SEC, managed = false)
|
||||
protected static WebArchive salesPostClockSkewServlet30Sec() {
|
||||
return samlServletDeployment(SalesPostClockSkewServlet.DEPLOYMENT_NAME, DEPLOYMENT_NAME_30_SEC, SalesPostClockSkewServlet.DEPLOYMENT_NAME + "/WEB-INF/web.xml", 30, AdapterActionsFilter.class, PublicKeyLocator.class, SendUsernameServlet.class);
|
||||
return samlServletDeployment(SalesPostClockSkewServlet.DEPLOYMENT_NAME, DEPLOYMENT_NAME_30_SEC, SalesPostClockSkewServlet.DEPLOYMENT_NAME + "/WEB-INF/web.xml", 30, AdapterActionsFilter.class, SendUsernameServlet.class);
|
||||
}
|
||||
|
||||
@Deployment(name = SalesPostClockSkewServlet.DEPLOYMENT_NAME, managed = false)
|
||||
protected static WebArchive salesPostClockSkewServlet5Sec() {
|
||||
return samlServletDeployment(SalesPostClockSkewServlet.DEPLOYMENT_NAME, SalesPostClockSkewServlet.DEPLOYMENT_NAME + "/WEB-INF/web.xml", 5, AdapterActionsFilter.class, PublicKeyLocator.class, SendUsernameServlet.class);
|
||||
return samlServletDeployment(SalesPostClockSkewServlet.DEPLOYMENT_NAME, SalesPostClockSkewServlet.DEPLOYMENT_NAME + "/WEB-INF/web.xml", 5, AdapterActionsFilter.class, SendUsernameServlet.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,7 +5,6 @@ import org.jboss.arquillian.graphene.page.Page;
|
|||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.adapters.rotation.PublicKeyLocator;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.admin.client.resource.ProtocolMappersResource;
|
||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||
|
@ -68,7 +67,7 @@ public class SAMLLoginResponseHandlingTest extends AbstractSAMLServletAdapterTes
|
|||
|
||||
@Deployment(name = Employee2Servlet.DEPLOYMENT_NAME)
|
||||
protected static WebArchive employee2() {
|
||||
return samlServletDeployment(Employee2Servlet.DEPLOYMENT_NAME, WEB_XML_WITH_ACTION_FILTER, SendUsernameServlet.class, AdapterActionsFilter.class, PublicKeyLocator.class);
|
||||
return samlServletDeployment(Employee2Servlet.DEPLOYMENT_NAME, WEB_XML_WITH_ACTION_FILTER, SendUsernameServlet.class, AdapterActionsFilter.class);
|
||||
}
|
||||
|
||||
@Deployment(name = EmployeeSigServlet.DEPLOYMENT_NAME)
|
||||
|
|
|
@ -4,7 +4,6 @@ import org.jboss.arquillian.container.test.api.Deployment;
|
|||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.adapters.rotation.PublicKeyLocator;
|
||||
import org.keycloak.dom.saml.v2.SAML2Object;
|
||||
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
|
||||
import org.keycloak.dom.saml.v2.assertion.StatementAbstractType;
|
||||
|
@ -44,7 +43,7 @@ public class SAMLServletSessionTimeoutTest extends AbstractSAMLServletAdapterTes
|
|||
|
||||
@Deployment(name = Employee2Servlet.DEPLOYMENT_NAME)
|
||||
protected static WebArchive employee2() {
|
||||
return samlServletDeployment(Employee2Servlet.DEPLOYMENT_NAME, WEB_XML_WITH_ACTION_FILTER, SendUsernameServlet.class, AdapterActionsFilter.class, PublicKeyLocator.class);
|
||||
return samlServletDeployment(Employee2Servlet.DEPLOYMENT_NAME, WEB_XML_WITH_ACTION_FILTER, SendUsernameServlet.class, AdapterActionsFilter.class);
|
||||
}
|
||||
|
||||
private static final int SESSION_LENGTH_IN_SECONDS = 120;
|
||||
|
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import org.hamcrest.MatcherAssert;
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.testsuite.Assert;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.page.SessionPortal;
|
||||
import org.keycloak.testsuite.auth.page.login.Login;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.pages.InfoPage;
|
||||
import org.keycloak.testsuite.pages.LogoutConfirmPage;
|
||||
import org.keycloak.testsuite.util.AccountHelper;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
import org.keycloak.testsuite.util.SecondBrowser;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author tkyjovsk
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class SessionServletAdapterTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
private SessionPortal sessionPortalPage;
|
||||
|
||||
@Page
|
||||
protected LogoutConfirmPage logoutConfirmPage;
|
||||
|
||||
@Page
|
||||
protected InfoPage infoPage;
|
||||
|
||||
@Override
|
||||
public void setDefaultPageUriParameters() {
|
||||
super.setDefaultPageUriParameters();
|
||||
oauth.realm(DEMO);
|
||||
}
|
||||
|
||||
@Deployment(name = SessionPortal.DEPLOYMENT_NAME)
|
||||
protected static WebArchive sessionPortal() {
|
||||
return servletDeployment(SessionPortal.DEPLOYMENT_NAME, "keycloak.json", SessionServlet.class);
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterSessionServletAdapterTest() {
|
||||
sessionPortalPage.navigateTo();
|
||||
driver.manage().deleteAllCookies();
|
||||
}
|
||||
|
||||
@Drone
|
||||
@SecondBrowser
|
||||
protected WebDriver driver2;
|
||||
|
||||
//KEYCLOAK-732
|
||||
@Test
|
||||
public void testSingleSessionInvalidated() {
|
||||
|
||||
loginAndCheckSession(testRealmLoginPage);
|
||||
|
||||
// cannot pass to loginAndCheckSession because loginPage is not working together with driver2, therefore copypasta
|
||||
driver2.navigate().to(sessionPortalPage.toString());
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage, driver2);
|
||||
driver2.findElement(By.id("username")).sendKeys("bburke@redhat.com");
|
||||
driver2.findElement(By.id("password")).sendKeys("password");
|
||||
driver2.findElement(By.id("password")).submit();
|
||||
assertCurrentUrlEquals(sessionPortalPage, driver2);
|
||||
String pageSource = driver2.getPageSource();
|
||||
MatcherAssert.assertThat(pageSource, containsString("Counter=1"));
|
||||
// Counter increased now
|
||||
driver2.navigate().to(sessionPortalPage.toString());
|
||||
pageSource = driver2.getPageSource();
|
||||
assertTrue(pageSource.contains("Counter=2"));
|
||||
|
||||
// Logout in browser1
|
||||
String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
|
||||
.build("demo").toString();
|
||||
driver.navigate().to(logoutUri);
|
||||
|
||||
logoutConfirmPage.assertCurrent();
|
||||
logoutConfirmPage.confirmLogout();
|
||||
waitForPageToLoad();
|
||||
infoPage.assertCurrent();
|
||||
|
||||
// Assert that I am logged out in browser1
|
||||
sessionPortalPage.navigateTo();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
|
||||
// Assert that I am still logged in browser2 and same session is still preserved
|
||||
driver2.navigate().to(sessionPortalPage.toString());
|
||||
assertCurrentUrlEquals(sessionPortalPage, driver2);
|
||||
pageSource = driver2.getPageSource();
|
||||
MatcherAssert.assertThat(pageSource, containsString("Counter=3"));
|
||||
|
||||
// Logout in driver2
|
||||
driver2.navigate().to(logoutUri);
|
||||
driver2.findElement(By.cssSelector("input[type=\"submit\"]")).click();
|
||||
Assert.assertEquals("You are logged out", driver2.findElement(By.className("instruction")).getText());
|
||||
}
|
||||
|
||||
//KEYCLOAK-741
|
||||
@Test
|
||||
public void testSessionInvalidatedAfterFailedRefresh() {
|
||||
RealmRepresentation testRealmRep = testRealmResource().toRepresentation();
|
||||
ClientResource sessionPortalRes = null;
|
||||
for (ClientRepresentation clientRep : testRealmResource().clients().findAll()) {
|
||||
if ("session-portal".equals(clientRep.getClientId())) {
|
||||
sessionPortalRes = testRealmResource().clients().get(clientRep.getId());
|
||||
}
|
||||
}
|
||||
assertNotNull(sessionPortalRes);
|
||||
sessionPortalRes.toRepresentation().setAdminUrl("");
|
||||
int origTokenLifespan = testRealmRep.getAccessCodeLifespan();
|
||||
testRealmRep.setAccessCodeLifespan(1);
|
||||
testRealmResource().update(testRealmRep);
|
||||
|
||||
// Login
|
||||
loginAndCheckSession(testRealmLoginPage);
|
||||
|
||||
// Logout
|
||||
String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
|
||||
.build("demo").toString();
|
||||
driver.navigate().to(logoutUri);
|
||||
logoutConfirmPage.assertCurrent();
|
||||
logoutConfirmPage.confirmLogout();
|
||||
waitForPageToLoad();
|
||||
infoPage.assertCurrent();
|
||||
|
||||
// Assert that http session was invalidated
|
||||
sessionPortalPage.navigateTo();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
testRealmLoginPage.form().login("bburke@redhat.com", "password");
|
||||
assertCurrentUrlEquals(sessionPortalPage);
|
||||
String pageSource = driver.getPageSource();
|
||||
assertTrue(pageSource.contains("Counter=1"));
|
||||
|
||||
sessionPortalRes.toRepresentation().setAdminUrl(sessionPortalPage.toString());
|
||||
testRealmRep.setAccessCodeLifespan(origTokenLifespan);
|
||||
testRealmResource().update(testRealmRep);
|
||||
}
|
||||
|
||||
//KEYCLOAK-942
|
||||
@Test
|
||||
public void testAdminApplicationLogout() {
|
||||
// login as bburke
|
||||
loginAndCheckSession(testRealmLoginPage);
|
||||
|
||||
// logout mposolda with admin client
|
||||
UserRepresentation mposolda = testRealmResource().users().search("mposolda", null, null, null, null, null).get(0);
|
||||
testRealmResource().users().get(mposolda.getId()).logout();
|
||||
|
||||
// bburke should be still logged with original httpSession in our browser window
|
||||
sessionPortalPage.navigateTo();
|
||||
assertCurrentUrlEquals(sessionPortalPage);
|
||||
String pageSource = driver.getPageSource();
|
||||
assertTrue(pageSource.contains("Counter=3"));
|
||||
String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
|
||||
.build("demo").toString();
|
||||
driver.navigate().to(logoutUri);
|
||||
logoutConfirmPage.assertCurrent();
|
||||
logoutConfirmPage.confirmLogout();
|
||||
waitForPageToLoad();
|
||||
infoPage.assertCurrent();
|
||||
}
|
||||
|
||||
//KEYCLOAK-1216
|
||||
@Test
|
||||
public void testAccountManagementSessionsLogout() {
|
||||
// login as bburke
|
||||
loginAndCheckSession(testRealmLoginPage);
|
||||
AccountHelper.logout(testRealmResource(), "bburke@redhat.com");
|
||||
// Assert I need to login again (logout was propagated to the app)
|
||||
loginAndCheckSession(testRealmLoginPage);
|
||||
}
|
||||
|
||||
private void loginAndCheckSession(Login login) {
|
||||
sessionPortalPage.navigateTo();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
login.form().login("bburke@redhat.com", "password");
|
||||
assertCurrentUrlEquals(sessionPortalPage);
|
||||
String pageSource = driver.getPageSource();
|
||||
assertTrue(pageSource.contains("Counter=1"));
|
||||
|
||||
// Counter increased now
|
||||
sessionPortalPage.navigateTo();
|
||||
pageSource = driver.getPageSource();
|
||||
assertTrue(pageSource.contains("Counter=2"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* 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.servlet;
|
||||
|
||||
import org.jboss.arquillian.container.test.api.Deployment;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolFactory;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.representations.idm.ComponentRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.storage.UserStorageProvider;
|
||||
import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest;
|
||||
import org.keycloak.testsuite.adapter.page.ProductPortal;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
|
||||
import org.keycloak.testsuite.federation.UserMapStorageFactory;
|
||||
import org.keycloak.testsuite.pages.ConsentPage;
|
||||
import org.keycloak.testsuite.pages.InfoPage;
|
||||
import org.keycloak.testsuite.pages.LogoutConfirmPage;
|
||||
import org.keycloak.testsuite.utils.arquillian.ContainerConstants;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.keycloak.storage.UserStorageProviderModel.IMPORT_ENABLED;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals;
|
||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
||||
import static org.keycloak.testsuite.util.WaitUtils.waitForPageToLoad;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@AppServerContainer(ContainerConstants.APP_SERVER_UNDERTOW)
|
||||
public class UserStorageConsentTest extends AbstractServletsAdapterTest {
|
||||
|
||||
@Page
|
||||
private ProductPortal productPortal;
|
||||
|
||||
@Page
|
||||
protected ConsentPage consentPage;
|
||||
|
||||
@Page
|
||||
protected LogoutConfirmPage logoutConfirmPage;
|
||||
|
||||
@Page
|
||||
protected InfoPage infoPage;
|
||||
|
||||
@Deployment(name = ProductPortal.DEPLOYMENT_NAME)
|
||||
protected static WebArchive productPortal() {
|
||||
return servletDeployment(ProductPortal.DEPLOYMENT_NAME, ProductServlet.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void addProvidersBeforeTest() throws URISyntaxException, IOException {
|
||||
ComponentRepresentation memProvider = new ComponentRepresentation();
|
||||
memProvider.setName("memory");
|
||||
memProvider.setProviderId(UserMapStorageFactory.PROVIDER_ID);
|
||||
memProvider.setProviderType(UserStorageProvider.class.getName());
|
||||
memProvider.setConfig(new MultivaluedHashMap<>());
|
||||
memProvider.getConfig().putSingle("priority", Integer.toString(0));
|
||||
memProvider.getConfig().putSingle(IMPORT_ENABLED, Boolean.toString(false));
|
||||
|
||||
addComponent(memProvider);
|
||||
}
|
||||
|
||||
protected String addComponent(ComponentRepresentation component) {
|
||||
Response resp = testRealmResource().components().add(component);
|
||||
resp.close();
|
||||
String id = ApiUtil.getCreatedId(resp);
|
||||
getCleanup().addComponentId(id);
|
||||
return id;
|
||||
}
|
||||
|
||||
public static void setupConsent(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName("demo");
|
||||
ClientModel product = session.clients().getClientByClientId(realm, "product-portal");
|
||||
product.setConsentRequired(true);
|
||||
ClientScopeModel clientScope = realm.addClientScope("clientScope");
|
||||
clientScope.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
System.err.println("client scope protocol mappers size: " + clientScope.getProtocolMappersStream().count());
|
||||
|
||||
for (ProtocolMapperModel mapper : product.getProtocolMappersStream().collect(Collectors.toList())) {
|
||||
if (mapper.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) {
|
||||
if (mapper.getName().equals(OIDCLoginProtocolFactory.USERNAME)
|
||||
|| mapper.getName().equals(OIDCLoginProtocolFactory.EMAIL)
|
||||
|| mapper.getName().equals(OIDCLoginProtocolFactory.GIVEN_NAME)
|
||||
) {
|
||||
ProtocolMapperModel copy = new ProtocolMapperModel();
|
||||
copy.setName(mapper.getName());
|
||||
copy.setProtocol(mapper.getProtocol());
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.putAll(mapper.getConfig());
|
||||
copy.setConfig(config);
|
||||
copy.setProtocolMapper(mapper.getProtocolMapper());
|
||||
clientScope.addProtocolMapper(copy);
|
||||
}
|
||||
}
|
||||
product.removeProtocolMapper(mapper);
|
||||
}
|
||||
product.addClientScope(clientScope, true);
|
||||
}
|
||||
|
||||
public static void setupDisplayClientOnConsentScreen(KeycloakSession session) {
|
||||
RealmModel realm = session.realms().getRealmByName("demo");
|
||||
ClientModel product = session.clients().getClientByClientId(realm, "product-portal");
|
||||
product.setDisplayOnConsentScreen(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* KEYCLOAK-5273
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testLogin() throws Exception {
|
||||
assertLogin();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginDisplayClientOnConsentScreen() throws Exception {
|
||||
testingClient.server().run(UserStorageConsentTest::setupDisplayClientOnConsentScreen);
|
||||
assertLogin();
|
||||
}
|
||||
|
||||
private void assertLogin() throws InterruptedException {
|
||||
testingClient.server().run(UserStorageConsentTest::setupConsent);
|
||||
UserRepresentation memuser = new UserRepresentation();
|
||||
memuser.setUsername("memuser");
|
||||
String uid = ApiUtil.createUserAndResetPasswordWithAdminClient(testRealmResource(), memuser, "password");
|
||||
System.out.println("uid: " + uid);
|
||||
Assert.assertTrue(uid.startsWith("f:")); // make sure its federated
|
||||
RoleRepresentation roleRep = adminClient.realm("demo").roles().get("user").toRepresentation();
|
||||
List<RoleRepresentation> roleList = new ArrayList<>();
|
||||
roleList.add(roleRep);
|
||||
adminClient.realm("demo").users().get(uid).roles().realmLevel().add(roleList);
|
||||
|
||||
productPortal.navigateTo();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
testRealmLoginPage.form().login("memuser", "password");
|
||||
Assert.assertTrue(consentPage.isCurrent());
|
||||
consentPage.confirm();
|
||||
assertCurrentUrlEquals(productPortal.toString());
|
||||
Assert.assertTrue(driver.getPageSource().contains("iPhone"));
|
||||
|
||||
String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder())
|
||||
.build("demo").toString();
|
||||
|
||||
driver.navigate().to(logoutUri);
|
||||
waitForPageToLoad();
|
||||
logoutConfirmPage.assertCurrent();
|
||||
logoutConfirmPage.confirmLogout();
|
||||
waitForPageToLoad();
|
||||
infoPage.assertCurrent();
|
||||
|
||||
driver.navigate().to(productPortal.toString());
|
||||
waitForPageToLoad();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
productPortal.navigateTo();
|
||||
assertCurrentUrlStartsWithLoginUrlOf(testRealmPage);
|
||||
testRealmLoginPage.form().login("memuser", "password");
|
||||
assertCurrentUrlEquals(productPortal.toString());
|
||||
Assert.assertTrue(driver.getPageSource().contains("iPhone"));
|
||||
|
||||
driver.navigate().to(logoutUri);
|
||||
waitForPageToLoad();
|
||||
logoutConfirmPage.assertCurrent();
|
||||
logoutConfirmPage.confirmLogout();
|
||||
adminClient.realm("demo").users().delete(uid).close();
|
||||
}
|
||||
}
|
|
@ -82,7 +82,6 @@ import org.junit.Before;
|
|||
import org.junit.Rule;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.adapters.AdapterUtils;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator;
|
||||
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
|
||||
|
@ -502,7 +501,7 @@ public abstract class AbstractClientPoliciesTest extends AbstractKeycloakTest {
|
|||
|
||||
private JsonWebToken createRequestToken(String clientId, String realmInfoUrl) {
|
||||
JsonWebToken reqToken = new JsonWebToken();
|
||||
reqToken.id(AdapterUtils.generateId());
|
||||
reqToken.id(KeycloakModelUtils.generateId());
|
||||
reqToken.issuer(clientId);
|
||||
reqToken.subject(clientId);
|
||||
reqToken.audience(realmInfoUrl);
|
||||
|
|
|
@ -20,8 +20,10 @@ package org.keycloak.testsuite.federation.kerberos;
|
|||
import static org.keycloak.testsuite.admin.AbstractAdminTest.loadJson;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -33,10 +35,18 @@ import javax.naming.directory.Attributes;
|
|||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
import javax.security.sasl.Sasl;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.auth.AuthSchemeProvider;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.config.AuthSchemes;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.apache.http.config.RegistryBuilder;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.ietf.jgss.GSSCredential;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
|
@ -44,9 +54,10 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
|||
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.HttpClientBuilder;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.authentication.authenticators.browser.SpnegoAuthenticatorFactory;
|
||||
import org.keycloak.common.constants.KerberosConstants;
|
||||
|
@ -74,7 +85,6 @@ import org.keycloak.testsuite.pages.LoginPage;
|
|||
import org.keycloak.testsuite.util.KerberosRule;
|
||||
import org.keycloak.testsuite.util.KerberosUtils;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/**
|
||||
* Contains just helper methods. No test methods.
|
||||
|
@ -255,11 +265,18 @@ public abstract class AbstractKerberosTest extends AbstractAuthTest {
|
|||
cleanupApacheHttpClient();
|
||||
}
|
||||
|
||||
HttpClient httpClient = new HttpClientBuilder()
|
||||
.disableCookieCache(false)
|
||||
.spNegoSchemeFactory(spnegoSchemeFactory)
|
||||
.useSPNego(useSpnego)
|
||||
.build();
|
||||
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
|
||||
if (useSpnego) {
|
||||
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("none", "none"));
|
||||
|
||||
httpClientBuilder.setDefaultAuthSchemeRegistry(RegistryBuilder.<AuthSchemeProvider>create()
|
||||
.register(AuthSchemes.SPNEGO, spnegoSchemeFactory).build())
|
||||
.setDefaultRequestConfig(RequestConfig.copy(RequestConfig.DEFAULT)
|
||||
.setTargetPreferredAuthSchemes(Collections.singletonList(AuthSchemes.SPNEGO)).build())
|
||||
.setDefaultCredentialsProvider(credentialsProvider);
|
||||
}
|
||||
HttpClient httpClient = httpClientBuilder.build();
|
||||
|
||||
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);
|
||||
client = ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder()).httpEngine(engine).build();
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.keycloak.testsuite.i18n;
|
|||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.jboss.arquillian.graphene.page.Page;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
|
@ -26,7 +27,6 @@ import org.junit.Assert;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.HttpClientBuilder;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.cookie.CookieType;
|
||||
|
@ -146,7 +146,7 @@ public class LoginPageTest extends AbstractI18NTest {
|
|||
|
||||
@Test
|
||||
public void acceptLanguageHeader() throws IOException {
|
||||
try(CloseableHttpClient httpClient = (CloseableHttpClient) new HttpClientBuilder().build()) {
|
||||
try(CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
||||
ApacheHttpClient43Engine engine = new ApacheHttpClient43Engine(httpClient);
|
||||
ResteasyClient client = ((ResteasyClientBuilder) ResteasyClientBuilder.newBuilder()).httpEngine(engine).build();
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ import org.junit.Rule;
|
|||
import org.junit.rules.TemporaryFolder;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.adapters.AdapterUtils;
|
||||
import org.keycloak.admin.client.resource.ClientAttributeCertificateResource;
|
||||
import org.keycloak.admin.client.resource.ClientResource;
|
||||
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
|
||||
|
@ -800,7 +799,7 @@ public abstract class AbstractClientAuthSignedJWTTest extends AbstractKeycloakTe
|
|||
@Override
|
||||
protected JsonWebToken createRequestToken(String clientId, String realmInfoUrl) {
|
||||
JsonWebToken reqToken = new JsonWebToken();
|
||||
if (isClaimEnabled("id")) reqToken.id(AdapterUtils.generateId());
|
||||
if (isClaimEnabled("id")) reqToken.id(KeycloakModelUtils.generateId());
|
||||
if (isClaimEnabled("issuer")) reqToken.issuer(clientId);
|
||||
if (isClaimEnabled("subject")) reqToken.subject(clientId);
|
||||
if (isClaimEnabled("audience")) reqToken.audience(realmInfoUrl);
|
||||
|
@ -928,7 +927,7 @@ public abstract class AbstractClientAuthSignedJWTTest extends AbstractKeycloakTe
|
|||
|
||||
protected JsonWebToken createRequestToken(String clientId, String realmInfoUrl) {
|
||||
JsonWebToken reqToken = new JsonWebToken();
|
||||
reqToken.id(AdapterUtils.generateId());
|
||||
reqToken.id(KeycloakModelUtils.generateId());
|
||||
reqToken.issuer(clientId);
|
||||
reqToken.subject(clientId);
|
||||
reqToken.audience(realmInfoUrl);
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "basic-auth-service",
|
||||
"auth-server-url": "/auth",
|
||||
"ssl-required" : "external",
|
||||
"enable-basic-auth" : "true",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "basic-auth-service",
|
||||
"auth-server-url": "/auth",
|
||||
"ssl-required" : "external",
|
||||
"enable-basic-auth" : "true",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>basic-auth</module-name>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<!-- <user-data-constraint>
|
||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||
</user-data-constraint> -->
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "child",
|
||||
"resource" : "client-linking",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"min-time-between-jwks-requests" : 0,
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>client-linking</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ClientInitiatedAccountLinkServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>child</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"id": "child",
|
||||
"realm": "child",
|
||||
"enabled": true,
|
||||
"accessTokenLifespan": 600,
|
||||
"accessCodeLifespan": 10,
|
||||
"accessCodeLifespanUserAction": 6000,
|
||||
"sslRequired": "external",
|
||||
"registrationAllowed": false,
|
||||
"requiredCredentials": [ "password" ],
|
||||
"users" : [
|
||||
{
|
||||
"username" : "bburke@redhat.com",
|
||||
"enabled": true,
|
||||
"email" : "bburke@redhat.com",
|
||||
"firstName": "Bill",
|
||||
"lastName": "Burke",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "client-linking",
|
||||
"enabled": true,
|
||||
"adminUrl": "/client-linking",
|
||||
"baseUrl": "/client-linking",
|
||||
"redirectUris": [
|
||||
"/client-linking/*"
|
||||
],
|
||||
"secret": "password"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "client-secret-jwt-secure-portal-valid-alg",
|
||||
"credentials": {
|
||||
"secret-jwt": {
|
||||
"secret": "234234-234234-234234",
|
||||
"algorithm": "HS512"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2020 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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>client-secret-jwt-secure-portal-valid-alg</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CallAuthenticatedServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Permit all</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>*</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "client-secret-jwt-secure-portal",
|
||||
"credentials": {
|
||||
"secret-jwt": {
|
||||
"secret": "234234-234234-234234"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>client-secret-jwt-secure-portal</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CallAuthenticatedServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Permit all</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>*</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "customer-cookie-portal-root",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"expose-token": true,
|
||||
"token-store": "cookie",
|
||||
"adapter-state-cookie-path": "/",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ * Copyright 2018 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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ErrorServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<filter>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<filter-class>org.keycloak.testsuite.adapter.filter.AdapterActionsFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Errors</web-resource-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Unsecured</web-resource-name>
|
||||
<url-pattern>/unsecured/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "customer-cookie-portal",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"expose-token": true,
|
||||
"token-store": "cookie",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2018 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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>customer-cookie-portal</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ErrorServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<filter>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<filter-class>org.keycloak.testsuite.adapter.filter.AdapterActionsFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Errors</web-resource-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Unsecured</web-resource-name>
|
||||
<url-pattern>/unsecured/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "customer-db-audience-required",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"bearer-only" : true,
|
||||
"enable-cors" : true,
|
||||
"public-key-cache-ttl": 600,
|
||||
"verify-token-audience": true
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>customer-db-audience-required</module-name>
|
||||
|
||||
|
||||
<filter>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<filter-class>org.keycloak.testsuite.adapter.filter.AdapterActionsFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerDatabaseServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Unsecured</web-resource-name>
|
||||
<url-pattern>/unsecured/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
|
||||
</web-app>
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "customer-db",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"bearer-only" : true,
|
||||
"enable-cors" : true
|
||||
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>customer-db-error-page</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerDatabaseServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ErrorServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<error-page>
|
||||
<error-code>400</error-code>
|
||||
<location>/error.html</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>401</error-code>
|
||||
<location>/error.html</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>403</error-code>
|
||||
<location>/error.html</location>
|
||||
</error-page>
|
||||
<error-page>
|
||||
<error-code>500</error-code>
|
||||
<location>/error.html</location>
|
||||
</error-page>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Errors</web-resource-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
<form-login-config>
|
||||
<form-login-page>/error.html</form-login-page>
|
||||
<form-error-page>/error.html</form-error-page>
|
||||
</form-login-config>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "customer-db",
|
||||
"auth-server-url": "/auth",
|
||||
"ssl-required" : "external",
|
||||
"bearer-only" : true,
|
||||
"enable-cors" : true
|
||||
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "customer-db",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"bearer-only" : true,
|
||||
"enable-cors" : true,
|
||||
"public-key-cache-ttl": 600
|
||||
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>customer-db</module-name>
|
||||
|
||||
|
||||
<filter>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<filter-class>org.keycloak.testsuite.adapter.filter.AdapterActionsFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerDatabaseServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Unsecured</web-resource-name>
|
||||
<url-pattern>/unsecured/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
|
||||
</web-app>
|
|
@ -1,76 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>customer-portal-noconf</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerServletNoConf</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ErrorServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Errors</web-resource-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
<form-login-config>
|
||||
<form-login-page>/error.html</form-login-page>
|
||||
<form-error-page>/error.html</form-error-page>
|
||||
</form-login-config>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,76 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>customer-portal-subsystem</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ErrorServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Errors</web-resource-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
<form-login-config>
|
||||
<form-login-page>/error.html</form-login-page>
|
||||
<form-error-page>/error.html</form-error-page>
|
||||
</form-login-config>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "customer-portal",
|
||||
"auth-server-url": "/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "customer-portal",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"expose-token": true,
|
||||
"min-time-between-jwks-requests": 120,
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>customer-portal</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CustomerServlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ErrorServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Errors</web-resource-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
<form-login-config>
|
||||
<form-login-page>/error.html</form-login-page>
|
||||
<form-error-page>/error.html</form-error-page>
|
||||
</form-login-config>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "child",
|
||||
"resource" : "exchange-linking",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"min-time-between-jwks-requests" : 0,
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>exchange-linking</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.LinkAndExchangeServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>child</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"id": "child",
|
||||
"realm": "child",
|
||||
"enabled": true,
|
||||
"accessTokenLifespan": 600,
|
||||
"accessCodeLifespan": 10,
|
||||
"accessCodeLifespanUserAction": 6000,
|
||||
"sslRequired": "external",
|
||||
"registrationAllowed": false,
|
||||
"requiredCredentials": [ "password" ],
|
||||
"users" : [
|
||||
{
|
||||
"username" : "bburke@redhat.com",
|
||||
"enabled": true,
|
||||
"email" : "bburke@redhat.com",
|
||||
"firstName": "Bill",
|
||||
"lastName": "Burke",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "exchange-linking",
|
||||
"enabled": true,
|
||||
"adminUrl": "/exchange-linking",
|
||||
"baseUrl": "/exchange-linking",
|
||||
"redirectUris": [
|
||||
"/exchange-linking/*"
|
||||
],
|
||||
"secret": "password"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "input-portal",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"min-time-between-jwks-requests": 120,
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>input-portal</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.InputServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/secured/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "tenant1",
|
||||
"resource" : "multi-tenant",
|
||||
"realm-public-key" : "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3wAQl0VcOVlT7JIttt0cVpksLDjASjfI9zl0c7U5eMWAt0SCOT1EIMjPjtrjO8eyudi7ckwP3NcEHL3QKoNEzwxHpccW7Y2RwVfsFHXkSRvWaxFtxHGNd1NRF4RNMGsCdtCyaybhknItTnOWjRy4jsgHmxDN8rwOWCF0RfnNwXWGefUcF1fe5vpNj+1u2diIUgaR9GC4zpzaDNT68fhzSt92F6ZaU4/niRdfBOoBxHW25HSqqsDKS/xMhlBB19UFUsKTraPsJjQTEpi0vqdpx88a2NjzKRaShHa/p08SyY5cZtgU99TjW7+uvWD0ka4Wf+BziyJSU0xCyFxek5z95QIDAQAB",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"realm" : "tenant2",
|
||||
"resource" : "multi-tenant",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>multi-tenant</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>MultiTenantServlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.MultiTenantServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<context-param>
|
||||
<param-name>keycloak.config.resolver</param-name>
|
||||
<param-value>org.keycloak.testsuite.adapter.servlet.MultiTenantResolver</param-value>
|
||||
</context-param>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>MultiTenantServlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>not-important</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
|
||||
</web-app>
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "no-access-token",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
},
|
||||
"ignore-oauth-query-parameter": true
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>no-access-token</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.InputServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/secured/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>public</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm": "test",
|
||||
"resource": "offline-client",
|
||||
"auth-server-url": "http://localhost:8081/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials": {
|
||||
"secret": "secret1"
|
||||
},
|
||||
"min-time-between-jwks-requests": 1
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>offline-client</module-name>
|
||||
|
||||
<filter>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<filter-class>org.keycloak.testsuite.adapter.filter.AdapterActionsFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.OfflineTokenServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ErrorServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Error Servlet</servlet-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Unsecured</web-resource-name>
|
||||
<url-pattern>/unsecured/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<!-- No auth-constraint = everybody has access -->
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Errors</web-resource-name>
|
||||
<url-pattern>/error.html</url-pattern>
|
||||
</web-resource-collection>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>test</realm-name>
|
||||
<form-login-config>
|
||||
<form-login-page>/error.html</form-login-page>
|
||||
<form-error-page>/error.html</form-error-page>
|
||||
</form-login-config>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,214 +0,0 @@
|
|||
{
|
||||
"id": "test",
|
||||
"realm": "test",
|
||||
"enabled": true,
|
||||
"accessTokenLifespan": 10,
|
||||
"ssoSessionIdleTimeout": 1800,
|
||||
"ssoSessionMaxLifespan": 36000,
|
||||
"offlineSessionIdleTimeout": 2592000,
|
||||
"offlineSessionMaxLifespan": 5184000,
|
||||
"sslRequired": "external",
|
||||
"registrationAllowed": true,
|
||||
"resetPasswordAllowed": true,
|
||||
"editUsernameAllowed" : true,
|
||||
"requiredCredentials": [ "password" ],
|
||||
"defaultRoles": [ "user" ],
|
||||
"smtpServer": {
|
||||
"from": "auto@keycloak.org",
|
||||
"host": "localhost",
|
||||
"port":"3025"
|
||||
},
|
||||
"users" : [
|
||||
{
|
||||
"username" : "test-user@localhost",
|
||||
"enabled": true,
|
||||
"email" : "test-user@localhost",
|
||||
"firstName": "Tom",
|
||||
"lastName": "Brady",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"realmRoles": ["user", "offline_access"],
|
||||
"clientRoles": {
|
||||
"test-app": [ "customer-user" ],
|
||||
"account": [ "view-profile", "manage-account" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"username" : "john-doh@localhost",
|
||||
"enabled": true,
|
||||
"email" : "john-doh@localhost",
|
||||
"firstName": "John",
|
||||
"lastName": "Doh",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"realmRoles": ["user"],
|
||||
"clientRoles": {
|
||||
"test-app": [ "customer-user" ],
|
||||
"account": [ "view-profile", "manage-account" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"username" : "keycloak-user@localhost",
|
||||
"enabled": true,
|
||||
"email" : "keycloak-user@localhost",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"realmRoles": ["user"],
|
||||
"clientRoles": {
|
||||
"test-app": [ "customer-user" ],
|
||||
"account": [ "view-profile", "manage-account" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"username" : "topGroupUser",
|
||||
"enabled": true,
|
||||
"email" : "top@redhat.com",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"groups": [
|
||||
"/topGroup"
|
||||
]
|
||||
},
|
||||
{
|
||||
"username" : "level2GroupUser",
|
||||
"enabled": true,
|
||||
"email" : "level2@redhat.com",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"groups": [
|
||||
"/topGroup/level2group"
|
||||
]
|
||||
}
|
||||
],
|
||||
"scopeMappings": [
|
||||
{
|
||||
"client": "third-party",
|
||||
"roles": ["user"]
|
||||
},
|
||||
{
|
||||
"client": "test-app",
|
||||
"roles": ["user"]
|
||||
},
|
||||
{
|
||||
"client": "offline-client",
|
||||
"roles": ["user","offline_access"]
|
||||
}
|
||||
],
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "test-app",
|
||||
"enabled": true,
|
||||
"baseUrl": "http://localhost:8180/auth/realms/master/app",
|
||||
"redirectUris": [
|
||||
"http://localhost:8180/auth/realms/master/app/*"
|
||||
],
|
||||
"adminUrl": "http://localhost:8180/auth/realms/master/app/logout",
|
||||
"secret": "password",
|
||||
"attributes" : {
|
||||
"exclude.issuer.from.auth.response": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientId" : "third-party",
|
||||
"enabled": true,
|
||||
"consentRequired": true,
|
||||
|
||||
"redirectUris": [
|
||||
"http://localhost:8180/app/*"
|
||||
],
|
||||
"secret": "password",
|
||||
"attributes" : {
|
||||
"exclude.issuer.from.auth.response": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientId": "offline-client",
|
||||
"enabled": true,
|
||||
"adminUrl": "/offline-client/logout",
|
||||
"baseUrl": "/offline-client",
|
||||
"directAccessGrantsEnabled": true,
|
||||
"redirectUris": [
|
||||
"/offline-client/*"
|
||||
],
|
||||
"secret": "secret1",
|
||||
"attributes" : {
|
||||
"exclude.issuer.from.auth.response": "true"
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
"roles" : {
|
||||
"realm" : [
|
||||
{
|
||||
"name": "user",
|
||||
"description": "Have User privileges"
|
||||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"description": "Have Administrator privileges"
|
||||
}
|
||||
],
|
||||
"client" : {
|
||||
"test-app" : [
|
||||
{
|
||||
"name": "customer-user",
|
||||
"description": "Have Customer User privileges"
|
||||
},
|
||||
{
|
||||
"name": "customer-admin",
|
||||
"description": "Have Customer Admin privileges"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
},
|
||||
"groups" : [
|
||||
{
|
||||
"name": "topGroup",
|
||||
"attributes": {
|
||||
"topAttribute": ["true"]
|
||||
|
||||
},
|
||||
"realmRoles": ["user"],
|
||||
|
||||
"subGroups": [
|
||||
{
|
||||
"name": "level2group",
|
||||
"realmRoles": ["admin"],
|
||||
"clientRoles": {
|
||||
"test-app": ["customer-user"]
|
||||
},
|
||||
"attributes": {
|
||||
"level2Attribute": ["true"]
|
||||
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
"clientScopeMappings": {
|
||||
"test-app": [
|
||||
{
|
||||
"client": "third-party",
|
||||
"roles": ["customer-user"]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"internationalizationEnabled": true,
|
||||
"supportedLocales": ["en", "de"],
|
||||
"defaultLocale": "en",
|
||||
"eventsListeners": ["jboss-logging", "event-queue"]
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "product-portal-autodetect-bearer-only",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
},
|
||||
"autodetect-bearer-only" : true
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>product-portal-autodetect-bearer-only</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ProductServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "product-portal",
|
||||
"auth-server-url" : "/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"realm" : "demo",
|
||||
"resource" : "product-portal",
|
||||
"auth-server-url" : "http://localhost:8180/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials" : {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>product-portal</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.ProductServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Users</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>user</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "secure-portal-with-custom-session-config",
|
||||
"credentials": {
|
||||
"jwt": {
|
||||
"client-key-password": "password",
|
||||
"client-keystore-file": "classpath:keystore.jks",
|
||||
"client-keystore-password": "password",
|
||||
"client-key-alias": "secure-portal",
|
||||
"token-timeout": 10,
|
||||
"client-keystore-type": "jks"
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,64 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>secure-portal-with-custom-session-config</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CallAuthenticatedServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Permit all</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>*</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<session-config>
|
||||
<cookie-config>
|
||||
<http-only>true</http-only>
|
||||
<name>CUSTOM_JSESSION_ID_NAME</name>
|
||||
</cookie-config>
|
||||
</session-config>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "secure-portal-with-rewrite-redirect-uri",
|
||||
"credentials": {
|
||||
"jwt": {
|
||||
"client-key-password": "password",
|
||||
"client-keystore-file": "classpath:keystore.jks",
|
||||
"client-keystore-password": "password",
|
||||
"client-key-alias": "secure-portal",
|
||||
"token-timeout": 10,
|
||||
"client-keystore-type": "jks"
|
||||
}
|
||||
},
|
||||
"redirect-rewrite-rules": {
|
||||
"^/(.*)$" : "/rewritten"
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ * Copyright 2018 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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>secure-portal-with-rewrite-redirect-uri</module-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CallAuthenticatedServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Permit all</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>*</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"auth-server-url": "http://localhost:8180/auth",
|
||||
"ssl-required": "external",
|
||||
"resource": "secure-portal",
|
||||
"credentials": {
|
||||
"jwt": {
|
||||
"client-key-password": "password",
|
||||
"client-keystore-file": "classpath:keystore.jks",
|
||||
"client-keystore-password": "password",
|
||||
"client-key-alias": "secure-portal",
|
||||
"token-timeout": 10,
|
||||
"client-keystore-type": "jks"
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -1,67 +0,0 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<module-name>secure-portal</module-name>
|
||||
|
||||
<filter>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<filter-class>org.keycloak.testsuite.adapter.filter.AdapterActionsFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<servlet-class>org.keycloak.testsuite.adapter.servlet.CallAuthenticatedServlet</servlet-class>
|
||||
</servlet>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>AdapterActionsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Servlet</servlet-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Permit all</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>*</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<login-config>
|
||||
<auth-method>KEYCLOAK</auth-method>
|
||||
<realm-name>demo</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>user</role-name>
|
||||
</security-role>
|
||||
</web-app>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue