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:
Ricardo Martin 2024-06-03 09:28:02 +02:00 committed by GitHub
parent f6f3b385c5
commit 0cd0d03c08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
132 changed files with 72 additions and 13301 deletions

View file

@ -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>

View file

@ -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.

View file

@ -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>

View file

@ -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());
}
}

View file

@ -1,9 +0,0 @@
{
"realm": "Test",
"auth-server-url": "/auth",
"ssl-required": "external",
"resource": "app-profile-jee",
"credentials": {
"secret": "4f36f31a-be9d-4f92-b982-425301bac5df"
}
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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;
}

View file

@ -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>

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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");
}
}

View file

@ -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());
}
}

View file

@ -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);
}

View file

@ -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() {

View file

@ -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;
}
}

View file

@ -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");
});
}
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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();
});
}
}

View file

@ -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"));
});
}
}

View file

@ -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();
});
}
}

View file

@ -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));
}
}

View file

@ -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");
});
}
}

View file

@ -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);
}
}

View file

@ -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"));
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}
}

View file

@ -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);
}
}

View file

@ -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")));
}
}

View file

@ -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));
}
}

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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"));
}
}

View file

@ -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();
}
}

View file

@ -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);

View file

@ -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();

View file

@ -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();

View file

@ -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);

View file

@ -1,10 +0,0 @@
{
"realm" : "demo",
"resource" : "basic-auth-service",
"auth-server-url": "/auth",
"ssl-required" : "external",
"enable-basic-auth" : "true",
"credentials": {
"secret": "password"
}
}

View file

@ -1,10 +0,0 @@
{
"realm" : "demo",
"resource" : "basic-auth-service",
"auth-server-url": "/auth",
"ssl-required" : "external",
"enable-basic-auth" : "true",
"credentials": {
"secret": "password"
}
}

View file

@ -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>

View file

@ -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"
}
}

View file

@ -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>

View file

@ -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"
}
]
}

View file

@ -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"
}
}
}

View file

@ -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>

View file

@ -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"
}
}
}

View file

@ -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>

View file

@ -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"
}
}

View file

@ -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>

View file

@ -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"
}
}

View file

@ -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>

View file

@ -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
}

View file

@ -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>

View file

@ -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
}

View file

@ -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>

View file

@ -1,9 +0,0 @@
{
"realm" : "demo",
"resource" : "customer-db",
"auth-server-url": "/auth",
"ssl-required" : "external",
"bearer-only" : true,
"enable-cors" : true
}

View file

@ -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
}

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -1,9 +0,0 @@
{
"realm": "demo",
"resource": "customer-portal",
"auth-server-url": "/auth",
"ssl-required" : "external",
"credentials": {
"secret": "password"
}
}

View file

@ -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"
}
}

View file

@ -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>

View file

@ -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"
}
}

View file

@ -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>

View file

@ -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"
}
]
}

View file

@ -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"
}
}

View file

@ -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>

View file

@ -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"
}
}

View file

@ -1,9 +0,0 @@
{
"realm" : "tenant2",
"resource" : "multi-tenant",
"auth-server-url" : "http://localhost:8180/auth",
"ssl-required" : "external",
"credentials" : {
"secret": "password"
}
}

View file

@ -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>

View file

@ -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
}

View file

@ -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>

View file

@ -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
}

View file

@ -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>

View file

@ -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"]
}

View file

@ -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
}

View file

@ -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>

View file

@ -1,9 +0,0 @@
{
"realm" : "demo",
"resource" : "product-portal",
"auth-server-url" : "/auth",
"ssl-required" : "external",
"credentials" : {
"secret": "password"
}
}

View file

@ -1,9 +0,0 @@
{
"realm" : "demo",
"resource" : "product-portal",
"auth-server-url" : "http://localhost:8180/auth",
"ssl-required" : "external",
"credentials" : {
"secret": "password"
}
}

View file

@ -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>

View file

@ -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"
}
}
}

View file

@ -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>

View file

@ -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"
}
}

View file

@ -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>

View file

@ -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"
}
}
}

View file

@ -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