Merge pull request #2430 from mstruk/assert-events
KEYCLOAK-2589 KEYCLOAK-2607 KEYCLOAK-2597 Port AssertEvents to integration-arquillian
This commit is contained in:
commit
020d090aee
23 changed files with 1533 additions and 133 deletions
|
@ -105,4 +105,37 @@ public class EventRepresentation {
|
|||
public void setDetails(Map<String, String> details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
EventRepresentation that = (EventRepresentation) o;
|
||||
|
||||
if (time != that.time) return false;
|
||||
if (type != null ? !type.equals(that.type) : that.type != null) return false;
|
||||
if (realmId != null ? !realmId.equals(that.realmId) : that.realmId != null) return false;
|
||||
if (clientId != null ? !clientId.equals(that.clientId) : that.clientId != null) return false;
|
||||
if (userId != null ? !userId.equals(that.userId) : that.userId != null) return false;
|
||||
if (sessionId != null ? !sessionId.equals(that.sessionId) : that.sessionId != null) return false;
|
||||
if (ipAddress != null ? !ipAddress.equals(that.ipAddress) : that.ipAddress != null) return false;
|
||||
if (error != null ? !error.equals(that.error) : that.error != null) return false;
|
||||
return !(details != null ? !details.equals(that.details) : that.details != null);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) (time ^ (time >>> 32));
|
||||
result = 31 * result + (type != null ? type.hashCode() : 0);
|
||||
result = 31 * result + (realmId != null ? realmId.hashCode() : 0);
|
||||
result = 31 * result + (clientId != null ? clientId.hashCode() : 0);
|
||||
result = 31 * result + (userId != null ? userId.hashCode() : 0);
|
||||
result = 31 * result + (sessionId != null ? sessionId.hashCode() : 0);
|
||||
result = 31 * result + (ipAddress != null ? ipAddress.hashCode() : 0);
|
||||
result = 31 * result + (error != null ? error.hashCode() : 0);
|
||||
result = 31 * result + (details != null ? details.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,7 +129,7 @@ public class GroupResource {
|
|||
child = realm.createGroup(rep.getName());
|
||||
updateGroup(rep, child);
|
||||
URI uri = uriInfo.getBaseUriBuilder()
|
||||
.path(uriInfo.getMatchedURIs().get(1))
|
||||
.path(uriInfo.getMatchedURIs().get(2))
|
||||
.path(child.getId()).build();
|
||||
builder.status(201).location(uri);
|
||||
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project name="inject-provider" basedir="." default="inject-provider">
|
||||
|
||||
<scriptdef name="inject-provider" language="javascript" manager="bsf">
|
||||
<attribute name="path"/>
|
||||
<![CDATA[
|
||||
importClass(Packages.java.io.File);
|
||||
importClass(Packages.org.keycloak.util.JsonSerialization);
|
||||
|
||||
path = attributes.get("path");
|
||||
file = new File(path);
|
||||
root = JsonSerialization.mapper.readTree(file);
|
||||
|
||||
// inject provider
|
||||
providers = root.withArray("providers");
|
||||
providers.add("module:org.keycloak.testsuite.integration-arquillian-event-queue");
|
||||
|
||||
// save file
|
||||
JsonSerialization.prettyMapper.writeValue(file, root);
|
||||
]]>
|
||||
</scriptdef>
|
||||
|
||||
<target name="inject-provider">
|
||||
<inject-provider path="${auth.server.home}/standalone/configuration/keycloak-server.json"/>
|
||||
</target>
|
||||
</project>
|
|
@ -100,13 +100,102 @@
|
|||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>copy-event-queue-provider</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-event-queue</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<overWrite>false</overWrite>
|
||||
<outputDirectory>${auth.server.home}/modules/org/keycloak/testsuite/integration-arquillian-event-queue/main</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>install-event-queue-module</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-event-queue</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>jar</type>
|
||||
<outputDirectory>${auth.server.home}/modules</outputDirectory>
|
||||
<includes>**/module.xml</includes>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>inject-into-keycloak-server-json</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<target>
|
||||
<ant antfile="../build.xml" inheritRefs="true">
|
||||
<target name="inject-provider"/>
|
||||
</ant>
|
||||
</target>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ant-contrib</groupId>
|
||||
<artifactId>ant-contrib</artifactId>
|
||||
<version>1.0b3</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>ant</groupId>
|
||||
<artifactId>ant</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.ant</groupId>
|
||||
<artifactId>ant-apache-bsf</artifactId>
|
||||
<version>1.9.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.bsf</groupId>
|
||||
<artifactId>bsf-api</artifactId>
|
||||
<version>3.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>rhino</groupId>
|
||||
<artifactId>js</artifactId>
|
||||
<version>1.7R2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
<name>Auth Server</name>
|
||||
|
||||
<modules>
|
||||
<module>services</module>
|
||||
<module>jboss</module>
|
||||
<module>undertow</module>
|
||||
</modules>
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.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.
|
||||
-->
|
||||
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-servers-auth-server-services</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>integration-arquillian-event-queue</artifactId>
|
||||
<name>Auth Server Services - Event Queue</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Keycloak deps for tests -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-dependencies-server-all</artifactId>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-services</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.events;
|
||||
|
||||
import org.keycloak.events.Event;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class AssertEventsServletFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest req = (HttpServletRequest) servletRequest;
|
||||
|
||||
if ("/event-queue".equals(req.getRequestURI().substring(req.getContextPath().length()))) {
|
||||
BlockingQueue<Event> events = EventsListenerProvider.getInstance();
|
||||
HttpServletResponse resp = (HttpServletResponse) servletResponse;
|
||||
resp.setContentType("application/json");
|
||||
|
||||
Event event = events.poll();
|
||||
if (event != null) {
|
||||
JsonSerialization.writeValueToStream(servletResponse.getOutputStream(), event);
|
||||
} else {
|
||||
resp.setStatus(204);
|
||||
}
|
||||
} else {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.events;
|
||||
|
||||
import org.keycloak.events.Event;
|
||||
import org.keycloak.events.EventListenerProvider;
|
||||
import org.keycloak.events.admin.AdminEvent;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class EventsListenerProvider implements EventListenerProvider {
|
||||
|
||||
private static final BlockingQueue<Event> events = new LinkedBlockingQueue<Event>();
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(AdminEvent event, boolean includeRepresentation) {
|
||||
// TODO: implement if needed
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
}
|
||||
|
||||
public static BlockingQueue<Event> getInstance() {
|
||||
return events;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.events;
|
||||
|
||||
import org.keycloak.Config;
|
||||
import org.keycloak.events.EventListenerProvider;
|
||||
import org.keycloak.events.EventListenerProviderFactory;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class EventsListenerProviderFactory implements EventListenerProviderFactory {
|
||||
|
||||
private static final EventsListenerProvider INSTANCE = new EventsListenerProvider();
|
||||
|
||||
private EventsServer server = new EventsServer();
|
||||
|
||||
@Override
|
||||
public EventListenerProvider create(KeycloakSession session) {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInit(KeycloakSessionFactory factory) {
|
||||
server.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "event-queue";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.events;
|
||||
|
||||
import io.undertow.Undertow;
|
||||
import io.undertow.server.handlers.PathHandler;
|
||||
import io.undertow.servlet.Servlets;
|
||||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.DeploymentManager;
|
||||
import io.undertow.servlet.api.FilterInfo;
|
||||
import io.undertow.servlet.api.ServletContainer;
|
||||
import io.undertow.servlet.api.ServletContainer.Factory;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class EventsServer {
|
||||
|
||||
private static final Logger log = Logger.getLogger(EventsServer.class.getName());
|
||||
|
||||
private String rootPath = "/";
|
||||
private int port;
|
||||
private Undertow server;
|
||||
|
||||
public EventsServer() {
|
||||
int eventsPort = Integer.parseInt(System.getProperty("auth.server.events.http.port", "8089"));
|
||||
int portOffset = Integer.parseInt(System.getProperty("auth.server.port.offset", "0"));
|
||||
int jbossPortOffset = Integer.parseInt(System.getProperty("jboss.socket.binding.port-offset", "-1"));
|
||||
|
||||
log.fine("Configuration:");
|
||||
log.fine(" auth.server.events.http.port: " + eventsPort);
|
||||
log.fine(" auth.server.port.offset: " + portOffset);
|
||||
log.fine(" jboss.socket.binding.port-offset: " + jbossPortOffset);
|
||||
port = eventsPort + (jbossPortOffset != -1 ? jbossPortOffset : portOffset);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
|
||||
PathHandler root = new PathHandler();
|
||||
this.server = Undertow.builder().addHttpListener(port, "localhost").setHandler(root).build();
|
||||
this.server.start();
|
||||
|
||||
ServletContainer container = Factory.newInstance();
|
||||
|
||||
DeploymentInfo di = new DeploymentInfo();
|
||||
di.setClassLoader(getClass().getClassLoader());
|
||||
di.setContextPath(rootPath);
|
||||
di.setDeploymentName("testing-event-queue");
|
||||
|
||||
FilterInfo filter = Servlets.filter("EventsFilter", AssertEventsServletFilter.class);
|
||||
di.addFilter(filter);
|
||||
di.addFilterUrlMapping("EventsFilter", "/event-queue", DispatcherType.REQUEST);
|
||||
|
||||
DeploymentManager manager = container.addDeployment(di);
|
||||
manager.deploy();
|
||||
|
||||
try {
|
||||
root.addPrefixPath(rootPath, manager.start());
|
||||
} catch (ServletException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
log.info("Started EventsServer on port: " + port);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
this.server.stop();
|
||||
}
|
||||
|
||||
public void setRootPath(String rootPath) {
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
org.keycloak.testsuite.events.EventsListenerProviderFactory
|
|
@ -0,0 +1,30 @@
|
|||
<!--
|
||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
~ and other contributors as indicated by the @author tags.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.testsuite.integration-arquillian-event-queue">
|
||||
<resources>
|
||||
<resource-root path="integration-arquillian-event-queue-${project.version}.jar"/>
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="javax.servlet.api"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-server-spi"/>
|
||||
</dependencies>
|
||||
</module>
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.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.
|
||||
-->
|
||||
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<parent>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-servers-auth-server</artifactId>
|
||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>integration-arquillian-servers-auth-server-services</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Auth Server Services</name>
|
||||
|
||||
<modules>
|
||||
<module>event-queue</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
|
@ -57,6 +57,11 @@
|
|||
<artifactId>commons-configuration</artifactId>
|
||||
<version>1.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak.testsuite</groupId>
|
||||
<artifactId>integration-arquillian-event-queue</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.junit.Assert;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.EventRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.representations.idm.UserSessionRepresentation;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.util.TokenUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.PublicKey;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class AssertEvents {
|
||||
|
||||
static final String DEFAULT_CLIENT_ID = "test-app";
|
||||
static final String DEFAULT_IP_ADDRESS = "127.0.0.1";
|
||||
static final String DEFAULT_REALM = "test";
|
||||
static final String DEFAULT_USERNAME = "test-user@localhost";
|
||||
|
||||
String defaultRedirectUri = "http://localhost:8081/app/auth";
|
||||
String defaultEventsQueueUri = "http://localhost:8092";
|
||||
|
||||
private RealmResource realmResource;
|
||||
private RealmRepresentation realmRep;
|
||||
private AbstractKeycloakTest context;
|
||||
private PublicKey realmPublicKey;
|
||||
private UserRepresentation defaultUser;
|
||||
|
||||
public AssertEvents(AbstractKeycloakTest ctx) throws Exception {
|
||||
context = ctx;
|
||||
|
||||
realmResource = context.adminClient.realms().realm(DEFAULT_REALM);
|
||||
realmRep = realmResource.toRepresentation();
|
||||
String pubKeyString = realmRep.getPublicKey();
|
||||
realmPublicKey = PemUtils.decodePublicKey(pubKeyString);
|
||||
|
||||
defaultUser = getUser(DEFAULT_USERNAME);
|
||||
if (defaultUser == null) {
|
||||
throw new RuntimeException("Default user does not exist: " + DEFAULT_USERNAME + ". Make sure to add it to your test realm.");
|
||||
}
|
||||
|
||||
defaultEventsQueueUri = getAuthServerEventsQueueUri();
|
||||
}
|
||||
|
||||
String getAuthServerEventsQueueUri() {
|
||||
int httpPort = Integer.parseInt(System.getProperty("auth.server.event.http.port", "8089"));
|
||||
int portOffset = Integer.parseInt(System.getProperty("auth.server.port.offset", "0"));
|
||||
return "http://localhost:" + (httpPort + portOffset);
|
||||
}
|
||||
|
||||
public EventRepresentation poll() {
|
||||
EventRepresentation event = fetchNextEvent();
|
||||
Assert.assertNotNull("Event expected", event);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
realmResource.clearEvents();
|
||||
}
|
||||
|
||||
public ExpectedEvent expectRequiredAction(EventType event) {
|
||||
return expectLogin().event(event).removeDetail(Details.CONSENT).session(isUUID());
|
||||
}
|
||||
|
||||
public ExpectedEvent expectLogin() {
|
||||
return expect(EventType.LOGIN)
|
||||
.detail(Details.CODE_ID, isCodeId())
|
||||
//.detail(Details.USERNAME, DEFAULT_USERNAME)
|
||||
//.detail(Details.AUTH_METHOD, OIDCLoginProtocol.LOGIN_PROTOCOL)
|
||||
//.detail(Details.AUTH_TYPE, AuthorizationEndpoint.CODE_AUTH_TYPE)
|
||||
.detail(Details.REDIRECT_URI, defaultRedirectUri)
|
||||
.detail(Details.CONSENT, Details.CONSENT_VALUE_NO_CONSENT_REQUIRED)
|
||||
.session(isUUID());
|
||||
}
|
||||
|
||||
public ExpectedEvent expectClientLogin() {
|
||||
return expect(EventType.CLIENT_LOGIN)
|
||||
.detail(Details.CODE_ID, isCodeId())
|
||||
.detail(Details.CLIENT_AUTH_METHOD, ClientIdAndSecretAuthenticator.PROVIDER_ID)
|
||||
.detail(Details.GRANT_TYPE, OAuth2Constants.CLIENT_CREDENTIALS)
|
||||
.removeDetail(Details.CODE_ID)
|
||||
.session(isUUID());
|
||||
}
|
||||
|
||||
public ExpectedEvent expectSocialLogin() {
|
||||
return expect(EventType.LOGIN)
|
||||
.detail(Details.CODE_ID, isCodeId())
|
||||
.detail(Details.USERNAME, DEFAULT_USERNAME)
|
||||
.detail(Details.AUTH_METHOD, "form")
|
||||
.detail(Details.REDIRECT_URI, defaultRedirectUri)
|
||||
.session(isUUID());
|
||||
}
|
||||
|
||||
public ExpectedEvent expectCodeToToken(String codeId, String sessionId) {
|
||||
return expect(EventType.CODE_TO_TOKEN)
|
||||
.detail(Details.CODE_ID, codeId)
|
||||
.detail(Details.TOKEN_ID, isUUID())
|
||||
.detail(Details.REFRESH_TOKEN_ID, isUUID())
|
||||
.detail(Details.REFRESH_TOKEN_TYPE, TokenUtil.TOKEN_TYPE_REFRESH)
|
||||
.detail(Details.CLIENT_AUTH_METHOD, ClientIdAndSecretAuthenticator.PROVIDER_ID)
|
||||
.session(sessionId);
|
||||
}
|
||||
|
||||
public ExpectedEvent expectRefresh(String refreshTokenId, String sessionId) {
|
||||
return expect(EventType.REFRESH_TOKEN)
|
||||
.detail(Details.TOKEN_ID, isUUID())
|
||||
.detail(Details.REFRESH_TOKEN_ID, refreshTokenId)
|
||||
.detail(Details.REFRESH_TOKEN_TYPE, TokenUtil.TOKEN_TYPE_REFRESH)
|
||||
.detail(Details.UPDATED_REFRESH_TOKEN_ID, isUUID())
|
||||
.detail(Details.CLIENT_AUTH_METHOD, ClientIdAndSecretAuthenticator.PROVIDER_ID)
|
||||
.session(sessionId);
|
||||
}
|
||||
|
||||
public ExpectedEvent expectLogout(String sessionId) {
|
||||
return expect(EventType.LOGOUT).client((String) null)
|
||||
.detail(Details.REDIRECT_URI, defaultRedirectUri)
|
||||
.session(sessionId);
|
||||
}
|
||||
|
||||
public ExpectedEvent expectRegister(String username, String email) {
|
||||
UserRepresentation user = username != null ? getUser(username) : null;
|
||||
return expect(EventType.REGISTER)
|
||||
.user(user != null ? user.getId() : null)
|
||||
.detail(Details.USERNAME, username)
|
||||
.detail(Details.EMAIL, email)
|
||||
.detail(Details.REGISTER_METHOD, "form")
|
||||
.detail(Details.REDIRECT_URI, defaultRedirectUri);
|
||||
}
|
||||
|
||||
public ExpectedEvent expectAccount(EventType event) {
|
||||
return expect(event).client("account");
|
||||
}
|
||||
|
||||
public ExpectedEvent expect(EventType event) {
|
||||
return new ExpectedEvent()
|
||||
.realm(realmRep.getId())
|
||||
.client(DEFAULT_CLIENT_ID)
|
||||
.user(defaultUser.getId())
|
||||
.ipAddress(DEFAULT_IP_ADDRESS)
|
||||
.session((String) null)
|
||||
.event(event);
|
||||
}
|
||||
|
||||
UserRepresentation getUser(String username) {
|
||||
List<UserRepresentation> result = realmResource.users().search(username, null, null, null, 0, 1);
|
||||
return result.size() > 0 ? result.get(0) : null;
|
||||
}
|
||||
|
||||
public PublicKey getRealmPublicKey() {
|
||||
return realmPublicKey;
|
||||
}
|
||||
|
||||
public class ExpectedEvent {
|
||||
private EventRepresentation expected = new EventRepresentation();
|
||||
private Matcher<String> userId;
|
||||
private Matcher<String> sessionId;
|
||||
private HashMap<String, Matcher<String>> details;
|
||||
|
||||
public ExpectedEvent realm(RealmRepresentation realm) {
|
||||
expected.setRealmId(realm.getId());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent realm(String realmId) {
|
||||
expected.setRealmId(realmId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent client(ClientRepresentation client) {
|
||||
expected.setClientId(client.getClientId());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent client(String clientId) {
|
||||
expected.setClientId(clientId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent user(UserRepresentation user) {
|
||||
return user(user.getId());
|
||||
}
|
||||
|
||||
public ExpectedEvent user(String userId) {
|
||||
return user(CoreMatchers.equalTo(userId));
|
||||
}
|
||||
|
||||
public ExpectedEvent user(Matcher<String> userId) {
|
||||
this.userId = userId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent session(UserSessionRepresentation session) {
|
||||
return session(session.getId());
|
||||
}
|
||||
|
||||
public ExpectedEvent session(String sessionId) {
|
||||
return session(CoreMatchers.equalTo(sessionId));
|
||||
}
|
||||
|
||||
public ExpectedEvent session(Matcher<String> sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent ipAddress(String ipAddress) {
|
||||
expected.setIpAddress(ipAddress);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent event(EventType e) {
|
||||
expected.setType(e.name());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent detail(String key, String value) {
|
||||
return detail(key, CoreMatchers.equalTo(value));
|
||||
}
|
||||
|
||||
public ExpectedEvent detail(String key, Matcher<String> matcher) {
|
||||
if (details == null) {
|
||||
details = new HashMap<String, Matcher<String>>();
|
||||
}
|
||||
details.put(key, matcher);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent removeDetail(String key) {
|
||||
if (details != null) {
|
||||
details.remove(key);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent clearDetails() {
|
||||
if (details != null) details.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpectedEvent error(String error) {
|
||||
expected.setError(error);
|
||||
return this;
|
||||
}
|
||||
|
||||
public EventRepresentation assertEvent() {
|
||||
return assertEvent(poll());
|
||||
}
|
||||
|
||||
public EventRepresentation assertEvent(EventRepresentation actual) {
|
||||
if (expected.getError() != null && !expected.getType().toString().endsWith("_ERROR")) {
|
||||
expected.setType(expected.getType() + "_ERROR");
|
||||
}
|
||||
Assert.assertEquals(expected.getType(), actual.getType());
|
||||
Assert.assertEquals(expected.getRealmId(), actual.getRealmId());
|
||||
Assert.assertEquals(expected.getClientId(), actual.getClientId());
|
||||
Assert.assertEquals(expected.getError(), actual.getError());
|
||||
Assert.assertEquals(expected.getIpAddress(), actual.getIpAddress());
|
||||
Assert.assertThat(actual.getUserId(), userId);
|
||||
Assert.assertThat(actual.getSessionId(), sessionId);
|
||||
|
||||
if (details == null || details.isEmpty()) {
|
||||
// Assert.assertNull(actual.getDetails());
|
||||
} else {
|
||||
Assert.assertNotNull(actual.getDetails());
|
||||
for (Map.Entry<String, Matcher<String>> d : details.entrySet()) {
|
||||
String actualValue = actual.getDetails().get(d.getKey());
|
||||
if (!actual.getDetails().containsKey(d.getKey())) {
|
||||
Assert.fail(d.getKey() + " missing");
|
||||
}
|
||||
|
||||
Assert.assertThat("Unexpected value for " + d.getKey(), actualValue, d.getValue());
|
||||
}
|
||||
/*
|
||||
for (String k : actual.getDetails().keySet()) {
|
||||
if (!details.containsKey(k)) {
|
||||
Assert.fail(k + " was not expected");
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
}
|
||||
|
||||
public static Matcher<String> isCodeId() {
|
||||
return isUUID();
|
||||
}
|
||||
|
||||
public static Matcher<String> isUUID() {
|
||||
return new TypeSafeMatcher<String>() {
|
||||
@Override
|
||||
protected boolean matchesSafely(String item) {
|
||||
return 36 == item.length() && item.charAt(8) == '-' && item.charAt(13) == '-' && item.charAt(18) == '-' && item.charAt(23) == '-';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("Not an UUID");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private EventRepresentation fetchNextEvent() {
|
||||
CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||
try {
|
||||
HttpPost post = new HttpPost(defaultEventsQueueUri + "/event-queue");
|
||||
CloseableHttpResponse response = httpclient.execute(post);
|
||||
if (response.getStatusLine().getStatusCode() != 200) {
|
||||
throw new RuntimeException("Failed to retrieve event from " + post.getURI() + ": " + response.getStatusLine().toString() + " / " + IOUtils.toString(response.getEntity().getContent()));
|
||||
}
|
||||
|
||||
return JsonSerialization.readValue(response.getEntity().getContent(), EventRepresentation.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
httpclient.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ public abstract class AbstractEventTest extends AbstractAuthTest {
|
|||
configRep.setAdminEventsDetailsEnabled(false);
|
||||
configRep.setAdminEventsEnabled(false);
|
||||
configRep.setEventsEnabled(false);
|
||||
configRep.setEnabledEventTypes(Collections.EMPTY_LIST); // resets to all types
|
||||
configRep.setEnabledEventTypes(Collections.<String>emptyList()); // resets to all types
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.admin.group;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.arquillian.AuthServerTestEnricher;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.keycloak.testsuite.util.IOUtil.loadRealm;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public abstract class AbstractGroupTest extends AbstractKeycloakTest {
|
||||
|
||||
AssertEvents events;
|
||||
|
||||
@Before
|
||||
public void initAssertEvents() throws Exception {
|
||||
events = new AssertEvents(this);
|
||||
}
|
||||
|
||||
AccessToken login(String login, String clientId, String clientSecret, String userId) throws Exception {
|
||||
|
||||
AccessTokenResponse tokenResponse = oauthClient.getToken("test", clientId, clientSecret, login, "password");
|
||||
|
||||
String accessToken = tokenResponse.getToken();
|
||||
String refreshToken = tokenResponse.getRefreshToken();
|
||||
|
||||
AccessToken accessTokenRepresentation = RSATokenVerifier.verifyToken(accessToken, events.getRealmPublicKey(), AuthServerTestEnricher.getAuthServerContextRoot() + "/auth/realms/test");
|
||||
|
||||
JWSInput jws = new JWSInput(refreshToken);
|
||||
if (!RSAProvider.verify(jws, events.getRealmPublicKey())) {
|
||||
throw new RuntimeException("Invalid refresh token");
|
||||
}
|
||||
RefreshToken refreshTokenRepresentation = jws.readJsonContent(RefreshToken.class);
|
||||
|
||||
events.expectLogin()
|
||||
.client(clientId)
|
||||
.user(userId)
|
||||
.session(tokenResponse.getSessionState())
|
||||
.detail(Details.GRANT_TYPE, OAuth2Constants.PASSWORD)
|
||||
.detail(Details.TOKEN_ID, accessTokenRepresentation.getId())
|
||||
.detail(Details.REFRESH_TOKEN_ID, refreshTokenRepresentation.getId())
|
||||
.detail(Details.USERNAME, login)
|
||||
.removeDetail(Details.CODE_ID)
|
||||
.removeDetail(Details.REDIRECT_URI)
|
||||
.removeDetail(Details.CONSENT)
|
||||
.assertEvent();
|
||||
|
||||
return accessTokenRepresentation;
|
||||
}
|
||||
|
||||
RealmRepresentation loadTestRealm(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation result = loadRealm("/testrealm.json");
|
||||
testRealms.add(result);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.admin.group;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.mappers.GroupMembershipMapper;
|
||||
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
|
||||
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class GroupMappersTest extends AbstractGroupTest {
|
||||
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation testRealmRep = loadTestRealm(testRealms);
|
||||
|
||||
testRealmRep.setEventsEnabled(true);
|
||||
|
||||
ClientRepresentation client = getClientByAlias(testRealmRep, "test-app");
|
||||
Assert.assertNotNull("test-app client exists", client);
|
||||
|
||||
client.setDirectAccessGrantsEnabled(true);
|
||||
|
||||
List<ProtocolMapperRepresentation> mappers = new LinkedList<>();
|
||||
ProtocolMapperRepresentation mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName("groups");
|
||||
mapper.setProtocolMapper(GroupMembershipMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
mapper.setConsentRequired(false);
|
||||
Map<String, String> config = new HashMap<>();
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "groups");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName("topAttribute");
|
||||
mapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
mapper.setConsentRequired(false);
|
||||
config = new HashMap<>();
|
||||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, "topAttribute");
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "topAttribute");
|
||||
config.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
mapper = new ProtocolMapperRepresentation();
|
||||
mapper.setName("level2Attribute");
|
||||
mapper.setProtocolMapper(UserAttributeMapper.PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
mapper.setConsentRequired(false);
|
||||
config = new HashMap<>();
|
||||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, "level2Attribute");
|
||||
config.put(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, "level2Attribute");
|
||||
config.put(OIDCAttributeMapperHelper.JSON_TYPE, ProviderConfigProperty.STRING_TYPE);
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
mapper.setConfig(config);
|
||||
mappers.add(mapper);
|
||||
|
||||
client.setProtocolMappers(mappers);
|
||||
}
|
||||
|
||||
private ClientRepresentation getClientByAlias(RealmRepresentation testRealmRep, String alias) {
|
||||
for (ClientRepresentation client: testRealmRep.getClients()) {
|
||||
if (alias.equals(client.getClientId())) {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testGroupMappers() throws Exception {
|
||||
RealmResource realm = adminClient.realms().realm("test");
|
||||
{
|
||||
UserRepresentation user = realm.users().search("topGroupUser", -1, -1).get(0);
|
||||
|
||||
AccessToken token = login(user.getUsername(), "test-app", "password", user.getId());
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
List<String> groups = (List<String>) token.getOtherClaims().get("groups");
|
||||
Assert.assertNotNull(groups);
|
||||
Assert.assertTrue(groups.size() == 1);
|
||||
Assert.assertEquals("topGroup", groups.get(0));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("topAttribute"));
|
||||
}
|
||||
{
|
||||
UserRepresentation user = realm.users().search("level2GroupUser", -1, -1).get(0);
|
||||
|
||||
AccessToken token = login(user.getUsername(), "test-app", "password", user.getId());
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("admin"));
|
||||
Assert.assertTrue(token.getResourceAccess("test-app").getRoles().contains("customer-user"));
|
||||
List<String> groups = (List<String>) token.getOtherClaims().get("groups");
|
||||
Assert.assertNotNull(groups);
|
||||
Assert.assertTrue(groups.size() == 1);
|
||||
Assert.assertEquals("level2group", groups.get(0));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("topAttribute"));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("level2Attribute"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,89 +15,68 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.testsuite.model;
|
||||
package org.keycloak.testsuite.admin.group;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.resource.RealmResource;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.protocol.oidc.mappers.GroupMembershipMapper;
|
||||
import org.keycloak.protocol.oidc.mappers.UserAttributeMapper;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.RefreshToken;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.AssertEvents;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.rule.KeycloakRule;
|
||||
import org.keycloak.testsuite.rule.WebResource;
|
||||
import org.keycloak.testsuite.rule.WebRule;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.keycloak.testsuite.admin.ApiUtil;
|
||||
import org.keycloak.testsuite.util.URLAssert;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class GroupTest {
|
||||
public class GroupTest extends AbstractGroupTest {
|
||||
|
||||
@ClassRule
|
||||
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
|
||||
@Override
|
||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||
ClientModel app = KeycloakModelUtils.createClient(appRealm, "resource-owner");
|
||||
app.setDirectAccessGrantsEnabled(true);
|
||||
app.setSecret("secret");
|
||||
@Override
|
||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||
RealmRepresentation testRealmRep = loadTestRealm(testRealms);
|
||||
|
||||
app = appRealm.getClientByClientId("test-app");
|
||||
app.setDirectAccessGrantsEnabled(true);
|
||||
testRealmRep.setEventsEnabled(true);
|
||||
|
||||
UserModel user = session.users().addUser(appRealm, "direct-login");
|
||||
user.setEmail("direct-login@localhost");
|
||||
user.setEnabled(true);
|
||||
List<UserRepresentation> users = testRealmRep.getUsers();
|
||||
|
||||
UserRepresentation user = new UserRepresentation();
|
||||
user.setUsername("direct-login");
|
||||
user.setEmail("direct-login@localhost");
|
||||
user.setEnabled(true);
|
||||
List<CredentialRepresentation> credentials = new LinkedList<>();
|
||||
CredentialRepresentation credential = new CredentialRepresentation();
|
||||
credential.setType(CredentialRepresentation.PASSWORD);
|
||||
credential.setValue("password");
|
||||
credentials.add(credential);
|
||||
user.setCredentials(credentials);
|
||||
users.add(user);
|
||||
|
||||
|
||||
session.users().updateCredential(appRealm, user, UserCredentialModel.password("password"));
|
||||
keycloak = Keycloak.getInstance("http://localhost:8081/auth", "master", "admin", "admin", Constants.ADMIN_CLI_CLIENT_ID);
|
||||
}
|
||||
});
|
||||
List<ClientRepresentation> clients = testRealmRep.getClients();
|
||||
|
||||
protected static Keycloak keycloak;
|
||||
|
||||
@Rule
|
||||
public AssertEvents events = new AssertEvents(keycloakRule);
|
||||
|
||||
@Rule
|
||||
public WebRule webRule = new WebRule(this);
|
||||
|
||||
@WebResource
|
||||
protected WebDriver driver;
|
||||
|
||||
@WebResource
|
||||
protected OAuthClient oauth;
|
||||
ClientRepresentation client = new ClientRepresentation();
|
||||
client.setClientId("resource-owner");
|
||||
client.setDirectAccessGrantsEnabled(true);
|
||||
client.setSecret("secret");
|
||||
clients.add(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAndTestGroups() throws Exception {
|
||||
RealmResource realm = keycloak.realms().realm("test");
|
||||
RealmResource realm = adminClient.realms().realm("test");
|
||||
{
|
||||
RoleRepresentation groupRole = new RoleRepresentation();
|
||||
groupRole.setName("topRole");
|
||||
|
@ -132,6 +111,21 @@ public class GroupTest {
|
|||
level2Group.setName("level2");
|
||||
response = realm.groups().group(topGroup.getId()).subGroup(level2Group);
|
||||
response.close();
|
||||
|
||||
URI location = response.getLocation();
|
||||
final String level2Id = ApiUtil.getCreatedId(response);
|
||||
final GroupRepresentation level2GroupById = realm.groups().group(level2Id).toRepresentation();
|
||||
Assert.assertEquals(level2Id, level2GroupById.getId());
|
||||
Assert.assertEquals(level2Group.getName(), level2GroupById.getName());
|
||||
|
||||
URLAssert.assertGetURL(location, adminClient.tokenManager().getAccessTokenString(), new URLAssert.AssertJSONResponseHandler() {
|
||||
@Override
|
||||
protected void assertResponseBody(String body) throws IOException {
|
||||
GroupRepresentation level2 = JsonSerialization.readValue(body, GroupRepresentation.class);
|
||||
Assert.assertEquals(level2Id, level2.getId());
|
||||
}
|
||||
});
|
||||
|
||||
level2Group = realm.getGroupByPath("/top/level2");
|
||||
Assert.assertNotNull(level2Group);
|
||||
roles.clear();
|
||||
|
@ -207,73 +201,5 @@ public class GroupTest {
|
|||
realm.removeDefaultGroup(level3Group.getId());
|
||||
defaultGroups = realm.getDefaultGroups();
|
||||
Assert.assertEquals(0, defaultGroups.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupMappers() throws Exception {
|
||||
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
|
||||
@Override
|
||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||
ClientModel app = appRealm.getClientByClientId("test-app");
|
||||
app.addProtocolMapper(GroupMembershipMapper.create("groups", "groups", false, null, true, true));
|
||||
app.addProtocolMapper(UserAttributeMapper.createClaimMapper("topAttribute", "topAttribute", "topAttribute", ProviderConfigProperty.STRING_TYPE, false, null, true, true, false));
|
||||
app.addProtocolMapper(UserAttributeMapper.createClaimMapper("level2Attribute", "level2Attribute", "level2Attribute", ProviderConfigProperty.STRING_TYPE, false, null, true, true, false));
|
||||
}
|
||||
}, "test");
|
||||
RealmResource realm = keycloak.realms().realm("test");
|
||||
{
|
||||
UserRepresentation user = realm.users().search("topGroupUser", -1, -1).get(0);
|
||||
|
||||
AccessToken token = login(user.getUsername(), "test-app", "password", user.getId());
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
List<String> groups = (List<String>) token.getOtherClaims().get("groups");
|
||||
Assert.assertNotNull(groups);
|
||||
Assert.assertTrue(groups.size() == 1);
|
||||
Assert.assertEquals("topGroup", groups.get(0));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("topAttribute"));
|
||||
}
|
||||
{
|
||||
UserRepresentation user = realm.users().search("level2GroupUser", -1, -1).get(0);
|
||||
|
||||
AccessToken token = login(user.getUsername(), "test-app", "password", user.getId());
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("user"));
|
||||
Assert.assertTrue(token.getRealmAccess().getRoles().contains("admin"));
|
||||
Assert.assertTrue(token.getResourceAccess("test-app").getRoles().contains("customer-user"));
|
||||
List<String> groups = (List<String>) token.getOtherClaims().get("groups");
|
||||
Assert.assertNotNull(groups);
|
||||
Assert.assertTrue(groups.size() == 1);
|
||||
Assert.assertEquals("level2group", groups.get(0));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("topAttribute"));
|
||||
Assert.assertEquals("true", token.getOtherClaims().get("level2Attribute"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected AccessToken login(String login, String clientId, String clientSecret, String userId) throws Exception {
|
||||
oauth.clientId(clientId);
|
||||
|
||||
OAuthClient.AccessTokenResponse response = oauth.doGrantAccessTokenRequest(clientSecret, login, "password");
|
||||
|
||||
assertEquals(200, response.getStatusCode());
|
||||
|
||||
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
|
||||
RefreshToken refreshToken = oauth.verifyRefreshToken(response.getRefreshToken());
|
||||
|
||||
events.expectLogin()
|
||||
.client(clientId)
|
||||
.user(userId)
|
||||
.session(accessToken.getSessionState())
|
||||
.detail(Details.GRANT_TYPE, OAuth2Constants.PASSWORD)
|
||||
.detail(Details.TOKEN_ID, accessToken.getId())
|
||||
.detail(Details.REFRESH_TOKEN_ID, refreshToken.getId())
|
||||
.detail(Details.USERNAME, login)
|
||||
.removeDetail(Details.CODE_ID)
|
||||
.removeDetail(Details.REDIRECT_URI)
|
||||
.removeDetail(Details.CONSENT)
|
||||
.assertEvent();
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,14 +18,27 @@
|
|||
package org.keycloak.testsuite.util;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.junit.Assert;
|
||||
import org.keycloak.testsuite.page.AbstractPage;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.keycloak.testsuite.auth.page.login.PageWithLoginUrl;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.support.ui.ExpectedCondition;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -104,9 +117,68 @@ public class URLAssert {
|
|||
public static void assertCurrentUrlStartsWithLoginUrlOf(PageWithLoginUrl page) {
|
||||
assertCurrentUrlStartsWithLoginUrlOf(page.getDriver(), page);
|
||||
}
|
||||
|
||||
|
||||
public static void assertCurrentUrlStartsWithLoginUrlOf(WebDriver driver, PageWithLoginUrl page) {
|
||||
assertCurrentUrlStartsWith(driver, page.getOIDCLoginUrl().toString());
|
||||
}
|
||||
|
||||
public static void assertGetURL(URI url, String accessToken, AssertResponseHandler handler) {
|
||||
CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||
try {
|
||||
HttpGet get = new HttpGet(url);
|
||||
get.setHeader("Authorization", "Bearer " + accessToken);
|
||||
|
||||
CloseableHttpResponse response = httpclient.execute(get);
|
||||
|
||||
if (response.getStatusLine().getStatusCode() != 200) {
|
||||
throw new RuntimeException("Response status error: " + response.getStatusLine().getStatusCode() + ": " + url);
|
||||
}
|
||||
|
||||
handler.assertResponse(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
httpclient.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface AssertResponseHandler {
|
||||
void assertResponse(CloseableHttpResponse response) throws IOException;
|
||||
}
|
||||
|
||||
public static abstract class AssertJSONResponseHandler implements AssertResponseHandler {
|
||||
|
||||
@Override
|
||||
public void assertResponse(CloseableHttpResponse response) throws IOException {
|
||||
HttpEntity entity = response.getEntity();
|
||||
Header contentType = entity.getContentType();
|
||||
Assert.assertEquals("application/json", contentType.getValue());
|
||||
|
||||
char [] buf = new char[8192];
|
||||
StringWriter out = new StringWriter();
|
||||
Reader in = new InputStreamReader(entity.getContent(), Charset.forName("utf-8"));
|
||||
int rc = 0;
|
||||
try {
|
||||
while ((rc = in.read(buf)) != -1) {
|
||||
out.write(buf, 0, rc);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
out.close();
|
||||
}
|
||||
|
||||
assertResponseBody(out.toString());
|
||||
}
|
||||
|
||||
protected abstract void assertResponseBody(String body) throws IOException;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
"jboss-logging" : {
|
||||
"success-level": "debug",
|
||||
"error-level": "warn"
|
||||
}
|
||||
},
|
||||
"event-queue": {}
|
||||
},
|
||||
|
||||
"realm": {
|
||||
|
|
|
@ -0,0 +1,186 @@
|
|||
{
|
||||
"id": "test",
|
||||
"realm": "test",
|
||||
"enabled": true,
|
||||
"sslRequired": "external",
|
||||
"registrationAllowed": true,
|
||||
"resetPasswordAllowed": true,
|
||||
"editUsernameAllowed" : true,
|
||||
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"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"]
|
||||
}
|
||||
],
|
||||
"clients": [
|
||||
{
|
||||
"clientId": "test-app",
|
||||
"enabled": true,
|
||||
"baseUrl": "http://localhost:8081/app",
|
||||
"redirectUris": [
|
||||
"http://localhost:8081/app/*"
|
||||
],
|
||||
"adminUrl": "http://localhost:8081/app/logout",
|
||||
"secret": "password"
|
||||
},
|
||||
{
|
||||
"clientId" : "third-party",
|
||||
"enabled": true,
|
||||
"consentRequired": true,
|
||||
|
||||
"redirectUris": [
|
||||
"http://localhost:8081/app/*"
|
||||
],
|
||||
"secret": "password"
|
||||
}
|
||||
],
|
||||
"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"]
|
||||
}
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
<auth.server.port.offset>100</auth.server.port.offset>
|
||||
<auth.server.http.port>8180</auth.server.http.port>
|
||||
<auth.server.events.http.port>8089</auth.server.events.http.port>
|
||||
<auth.server.https.port>8543</auth.server.https.port>
|
||||
<auth.server.management.port>10090</auth.server.management.port>
|
||||
<auth.server.management.port.jmx>10099</auth.server.management.port.jmx>
|
||||
|
@ -140,6 +141,7 @@
|
|||
|
||||
<auth.server.port.offset>${auth.server.port.offset}</auth.server.port.offset>
|
||||
<auth.server.http.port>${auth.server.http.port}</auth.server.http.port>
|
||||
<auth.server.events.http.port>${auth.server.events.http.port}</auth.server.events.http.port>
|
||||
<auth.server.https.port>${auth.server.https.port}</auth.server.https.port>
|
||||
<auth.server.management.port>${auth.server.management.port}</auth.server.management.port>
|
||||
<auth.server.management.port.jmx>${auth.server.management.port.jmx}</auth.server.management.port.jmx>
|
||||
|
|
Loading…
Reference in a new issue