Merge remote-tracking branch 'keycloak/master'

This commit is contained in:
gautric 2015-10-12 11:45:08 +02:00
commit ab7bfa6d90
298 changed files with 8784 additions and 1201 deletions

31
client-api/pom.xml Executable file
View file

@ -0,0 +1,31 @@
<?xml version="1.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">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-client-api</artifactId>
<name>Keycloak Client API</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,275 @@
package org.keycloak.client.registration;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.util.Base64;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.io.InputStream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistration {
private String clientRegistrationUrl;
private HttpClient httpClient;
private Auth auth;
public static ClientRegistrationBuilder create() {
return new ClientRegistrationBuilder();
}
private ClientRegistration() {
}
public ClientRepresentation create(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = doPost(content);
return deserialize(resultStream, ClientRepresentation.class);
}
public ClientRepresentation get() throws ClientRegistrationException {
if (auth instanceof ClientIdSecretAuth) {
String clientId = ((ClientIdSecretAuth) auth).clientId;
return get(clientId);
} else {
throw new ClientRegistrationException("Requires client authentication");
}
}
public ClientRepresentation get(String clientId) throws ClientRegistrationException {
InputStream resultStream = doGet(clientId);
return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
}
public void update(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
doPut(content, client.getClientId());
}
public void delete() throws ClientRegistrationException {
if (auth instanceof ClientIdSecretAuth) {
String clientId = ((ClientIdSecretAuth) auth).clientId;
delete(clientId);
} else {
throw new ClientRegistrationException("Requires client authentication");
}
}
public void delete(String clientId) throws ClientRegistrationException {
doDelete(clientId);
}
public void close() throws ClientRegistrationException {
if (httpClient instanceof CloseableHttpClient) {
try {
((CloseableHttpClient) httpClient).close();
} catch (IOException e) {
throw new ClientRegistrationException("Failed to close http client", e);
}
}
}
private InputStream doPost(String content) throws ClientRegistrationException {
try {
HttpPost request = new HttpPost(clientRegistrationUrl);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setEntity(new StringEntity(content));
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
InputStream responseStream = null;
if (response.getEntity() != null) {
responseStream = response.getEntity().getContent();
}
if (response.getStatusLine().getStatusCode() == 201) {
return responseStream;
} else {
responseStream.close();
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private InputStream doGet(String endpoint) throws ClientRegistrationException {
try {
HttpGet request = new HttpGet(clientRegistrationUrl + "/" + endpoint);
request.setHeader(HttpHeaders.ACCEPT, "application/json");
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
InputStream responseStream = null;
if (response.getEntity() != null) {
responseStream = response.getEntity().getContent();
}
if (response.getStatusLine().getStatusCode() == 200) {
return responseStream;
} else if (response.getStatusLine().getStatusCode() == 404) {
responseStream.close();
return null;
} else {
responseStream.close();
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private void doPut(String content, String endpoint) throws ClientRegistrationException {
try {
HttpPut request = new HttpPut(clientRegistrationUrl + "/" + endpoint);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setEntity(new StringEntity(content));
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
if (response.getEntity() != null) {
response.getEntity().getContent().close();
}
if (response.getStatusLine().getStatusCode() != 200) {
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private void doDelete(String endpoint) throws ClientRegistrationException {
try {
HttpDelete request = new HttpDelete(clientRegistrationUrl + "/" + endpoint);
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
if (response.getEntity() != null) {
response.getEntity().getContent().close();
}
if (response.getStatusLine().getStatusCode() != 200) {
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private String serialize(ClientRepresentation client) throws ClientRegistrationException {
try {
return JsonSerialization.writeValueAsString(client);
} catch (IOException e) {
throw new ClientRegistrationException("Failed to write json object", e);
}
}
private <T> T deserialize(InputStream inputStream, Class<T> clazz) throws ClientRegistrationException {
try {
return JsonSerialization.readValue(inputStream, clazz);
} catch (IOException e) {
throw new ClientRegistrationException("Failed to read json object", e);
}
}
public static class ClientRegistrationBuilder {
private String realm;
private String authServerUrl;
private Auth auth;
private HttpClient httpClient;
public ClientRegistrationBuilder realm(String realm) {
this.realm = realm;
return this;
}
public ClientRegistrationBuilder authServerUrl(String authServerUrl) {
this.authServerUrl = authServerUrl;
return this;
}
public ClientRegistrationBuilder auth(String token) {
this.auth = new TokenAuth(token);
return this;
}
public ClientRegistrationBuilder auth(String clientId, String clientSecret) {
this.auth = new ClientIdSecretAuth(clientId, clientSecret);
return this;
}
public ClientRegistrationBuilder httpClient(HttpClient httpClient) {
this.httpClient = httpClient;
return this;
}
public ClientRegistration build() {
ClientRegistration clientRegistration = new ClientRegistration();
clientRegistration.clientRegistrationUrl = authServerUrl + "/realms/" + realm + "/client-registration/default";
clientRegistration.httpClient = httpClient != null ? httpClient : HttpClients.createDefault();
clientRegistration.auth = auth;
return clientRegistration;
}
}
public interface Auth {
void addAuth(HttpRequest httpRequest);
}
public static class AuthorizationHeaderAuth implements Auth {
private String credentials;
public AuthorizationHeaderAuth(String credentials) {
this.credentials = credentials;
}
public void addAuth(HttpRequest httpRequest) {
httpRequest.setHeader(HttpHeaders.AUTHORIZATION, credentials);
}
}
public static class TokenAuth extends AuthorizationHeaderAuth {
public TokenAuth(String token) {
super("Bearer " + token);
}
}
public static class ClientIdSecretAuth extends AuthorizationHeaderAuth {
private String clientId;
public ClientIdSecretAuth(String clientId, String clientSecret) {
super("Basic " + Base64.encodeBytes((clientId + ":" + clientSecret).getBytes()));
this.clientId = clientId;
}
}
}

View file

@ -0,0 +1,16 @@
package org.keycloak.client.registration;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistrationException extends Exception {
public ClientRegistrationException(String s, Throwable throwable) {
super(s, throwable);
}
public ClientRegistrationException(String s) {
super(s);
}
}

View file

@ -0,0 +1,22 @@
package org.keycloak.client.registration;
import org.apache.http.StatusLine;
import java.io.IOException;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class HttpErrorException extends IOException {
private StatusLine statusLine;
public HttpErrorException(StatusLine statusLine) {
this.statusLine = statusLine;
}
public StatusLine getStatusLine() {
return statusLine;
}
}

View file

@ -1,14 +1,12 @@
package org.keycloak.representations.idm;
import java.util.ArrayList;
import org.codehaus.jackson.annotate.JsonIgnore;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.keycloak.util.MultivaluedHashMap;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $

View file

@ -31,10 +31,6 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>

View file

@ -14,6 +14,7 @@
<module name="org.apache.httpcomponents"/>
<module name="org.bouncycastle" />
<module name="org.keycloak.keycloak-common"/>
<module name="org.picketbox"/>
</dependencies>
</module>

View file

@ -17,8 +17,12 @@
<outputDirectory>rest-api</outputDirectory>
</fileSet>
<fileSet>
<directory>../../docbook/target/docbook/publish/en-US</directory>
<outputDirectory>userguide</outputDirectory>
<directory>../../docbook/auth-server-docs/target/docbook/publish/en-US</directory>
<outputDirectory>userguide/keycloak-server</outputDirectory>
</fileSet>
<fileSet>
<directory>../../docbook/saml-adapter-docs/target/docbook/publish/en-US</directory>
<outputDirectory>userguide/saml-client-adapter</outputDirectory>
</fileSet>
</fileSets>

View file

@ -1,8 +1,11 @@
<h1>Keyloak Documentation</h1>
<ul>
<li><a href="userguide/html/index.html">Userguide HTML</a></li>
<li><a href="userguide/html_single/index.html">Userguide HTML Single Page</a></li>
<li><a href="userguide/pdf/keycloak-reference-guide-en-US.pdf">Userguide PDF</a></li>
<li><a href="userguide/keycloak-server/html/index.html">Server and Keycloak Adapter Userguide HTML</a></li>
<li><a href="userguide/keycloak-server/html_single/index.html">Server and Keycloak Adapter Userguide HTML Single Page</a></li>
<li><a href="userguide/keycloak-server/pdf/keycloak-reference-guide-en-US.pdf">Server and Keycloak Adapter Userguide PDF</a></li>
<li><a href="userguide/saml-client-adapter/html/index.html">SAML Client Adapter Userguide HTML</a></li>
<li><a href="userguide/saml-client-adapter/html_single/index.html">>SAML Client Adapter Userguide HTML Single Page</a></li>
<li><a href="userguide/saml-client-adapter/pdf/keycloak-reference-guide-en-US.pdf">SAML Client Adapter Userguide PDF</a></li>
<li><a href="rest-api/overview-index.html">Admin REST API</a></li>
<li><a href="javadocs/index.html">Javadocs</a></li>
</ul>

View file

@ -248,7 +248,106 @@
<type>tar.gz</type>
</artifactItem>
</artifactItems>
<outputDirectory>target/${project.version}/adapters</outputDirectory>
<outputDirectory>target/${project.version}/adapters/keycloak-oidc</outputDirectory>
</configuration>
</execution>
<execution>
<id>saml-adapter-downloads</id>
<phase>install</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-eap6-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-eap6-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty81-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty81-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty92-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty92-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat6-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat6-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat7-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat7-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat8-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat8-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-wf9-adapter-dist</artifactId>
<type>zip</type>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-wf9-adapter-dist</artifactId>
<type>tar.gz</type>
</artifactItem>
</artifactItems>
<outputDirectory>target/${project.version}/adapters/saml</outputDirectory>
</configuration>
</execution>
</executions>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-core-jaxrs">
<resources>
<artifact name="${org.keycloak:keycloak-core-jaxrs}"/>
</resources>
<dependencies>
<module name="org.keycloak.keycloak-common"/>
<module name="org.keycloak.keycloak-core"/>
<module name="org.codehaus.jackson.jackson-core-asl"/>
<module name="org.codehaus.jackson.jackson-mapper-asl"/>
<module name="org.codehaus.jackson.jackson-xc"/>
<module name="javax.ws.rs.api"/>
<module name="org.bouncycastle" />
<module name="javax.api"/>
</dependencies>
</module>

View file

@ -11,7 +11,6 @@
<module name="org.keycloak.keycloak-connections-file" services="import"/>
<module name="org.keycloak.keycloak-common" services="import"/>
<module name="org.keycloak.keycloak-core" services="import"/>
<module name="org.keycloak.keycloak-core-jaxrs" services="import"/>
<module name="org.keycloak.keycloak-email-api" services="import"/>
<module name="org.keycloak.keycloak-email-freemarker" services="import"/>
<module name="org.keycloak.keycloak-events-api" services="import"/>

View file

@ -21,7 +21,6 @@
<module name="org.keycloak.keycloak-connections-file" services="import"/>
<module name="org.keycloak.keycloak-common" services="import"/>
<module name="org.keycloak.keycloak-core" services="import"/>
<module name="org.keycloak.keycloak-core-jaxrs" services="import"/>
<module name="org.keycloak.keycloak-email-api" services="import"/>
<module name="org.keycloak.keycloak-email-freemarker" services="import"/>
<module name="org.keycloak.keycloak-events-api" services="import"/>

View file

@ -0,0 +1,36 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/unpacked</directory>
<includes>
<include>org/keycloak/keycloak-common/**</include>
<include>org/keycloak/keycloak-saml-core/**</include>
<include>org/keycloak/keycloak-saml-adapter-core/**</include>
<include>org/keycloak/keycloak-adapter-spi/**</include>
<include>org/keycloak/keycloak-jboss-adapter-core/**</include>
<include>org/bouncycastle/**</include>
<include>org/keycloak/keycloak-saml-as7-adapter/**</include>
<include>org/keycloak/keycloak-saml-as7-subsystem/**</include>
<include>org/keycloak/keycloak-saml-adapter-subsystem/**</include>
</includes>
<excludes>
<exclude>**/*.war</exclude>
</excludes>
<outputDirectory>modules</outputDirectory>
</fileSet>
</fileSets>
<files>
<file>
<source>../../shared-cli/adapter-install.cli</source>
<outputDirectory>bin</outputDirectory>
</file>
</files>
</assembly>

View file

@ -0,0 +1,79 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-as7-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML AS7 Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-modules</artifactId>
<type>zip</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-modules</artifactId>
<type>zip</type>
<outputDirectory>${project.build.directory}/unpacked</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,22 @@
<assembly>
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>../../</directory>
<includes>
<include>License.html</include>
</includes>
<outputDirectory></outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}/modules</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
</assembly>

View file

@ -0,0 +1,88 @@
<!--
~ JBoss, Home of Professional Open Source.
~ Copyright 2012, Red Hat, Inc., and individual contributors
~ as indicated by the @author tags. See the copyright.txt file in the
~ distribution for a full listing of individual contributors.
~
~ This is free software; you can redistribute it and/or modify it
~ under the terms of the GNU Lesser General Public License as
~ published by the Free Software Foundation; either version 2.1 of
~ the License, or (at your option) any later version.
~
~ This software is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
~ Lesser General Public License for more details.
~
~ You should have received a copy of the GNU Lesser General Public
~ License along with this software; if not, write to the Free
~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->
<project name="module-repository" basedir="." default="all">
<import file="lib.xml"/>
<property name="output.dir" value="target"/>
<target name="all">
<antcall target="modules">
<param name="mavenized.modules" value="false"/>
<param name="output.dir" value="target"/>
</antcall>
</target>
<target name="modules">
<!-- server min dependencies -->
<module-def name="org.keycloak.keycloak-common">
<maven-resource group="org.keycloak" artifact="keycloak-common"/>
</module-def>
<module-def name="org.bouncycastle">
<maven-resource group="org.bouncycastle" artifact="bcprov-jdk15on"/>
<maven-resource group="org.bouncycastle" artifact="bcpkix-jdk15on"/>
</module-def>
<!-- subsystems -->
<module-def name="org.keycloak.keycloak-adapter-spi">
<maven-resource group="org.keycloak" artifact="keycloak-adapter-spi"/>
<maven-resource group="org.keycloak" artifact="keycloak-tomcat-adapter-spi"/>
<maven-resource group="org.keycloak" artifact="keycloak-as7-adapter-spi"/>
</module-def>
<module-def name="org.keycloak.keycloak-saml-core">
<maven-resource group="org.keycloak" artifact="keycloak-saml-core"/>
</module-def>
<module-def name="org.keycloak.keycloak-saml-adapter-core">
<maven-resource group="org.keycloak" artifact="keycloak-saml-adapter-core"/>
</module-def>
<module-def name="org.keycloak.keycloak-jboss-adapter-core">
<maven-resource group="org.keycloak" artifact="keycloak-jboss-adapter-core"/>
</module-def>
<module-def name="org.keycloak.keycloak-saml-as7-adapter">
<maven-resource group="org.keycloak" artifact="keycloak-saml-as7-adapter"/>
<maven-resource group="org.keycloak" artifact="keycloak-saml-tomcat-adapter-core"/>
</module-def>
<module-def name="org.keycloak.keycloak-saml-as7-subsystem">
<maven-resource group="org.keycloak" artifact="keycloak-saml-as7-subsystem"/>
</module-def>
</target>
<target name="clean-target">
<delete dir="${output.dir}"/>
</target>
<target name="clean" depends="clean-target">
<delete file="maven-ant-tasks.jar"/>
</target>
</project>

View file

@ -0,0 +1,282 @@
<!--
~ JBoss, Home of Professional Open Source.
~ Copyright 2010, Red Hat, Inc., and individual contributors
~ as indicated by the @author tags. See the copyright.txt file in the
~ distribution for a full listing of individual contributors.
~
~ This is free software; you can redistribute it and/or modify it
~ under the terms of the GNU Lesser General Public License as
~ published by the Free Software Foundation; either version 2.1 of
~ the License, or (at your option) any later version.
~
~ This software is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
~ Lesser General Public License for more details.
~
~ You should have received a copy of the GNU Lesser General Public
~ License along with this software; if not, write to the Free
~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->
<project name="module-repository-lib">
<property name="src.dir" value="src"/>
<property name="module.repo.src.dir" value="${src.dir}/main/resources/modules"/>
<property name="module.xml" value="module.xml"/>
<taskdef resource="net/sf/antcontrib/antlib.xml"/>
<taskdef name="jandex" classname="org.jboss.jandex.JandexAntTask" />
<macrodef name="module-def">
<attribute name="name"/>
<attribute name="slot" default="main"/>
<element name="resources" implicit="yes" optional="yes"/>
<sequential>
<echo message="Initializing module -> @{name}"/>
<property name="module.repo.output.dir" value="${output.dir}/modules"/>
<!-- Figure out the correct module path -->
<define-module-dir name="@{name}" slot="@{slot}"/>
<!-- Make the module output director -->
<mkdir dir="${module.repo.output.dir}/${current.module.path}"/>
<!-- Copy the module.xml and other stuff to the output director -->
<copy todir="${module.repo.output.dir}/${current.module.path}" overwrite="true">
<fileset dir="${module.repo.src.dir}/${current.module.path}">
<include name="**"/>
</fileset>
</copy>
<!-- Process the resource -->
<resources/>
<!-- Add keycloak version property to module xml -->
<replace file="${module.repo.output.dir}/${current.module.path}/${module.xml}"
token="$${project.version}"
value="${project.version}"/>
<!-- Some final cleanup -->
<replace file="${module.repo.output.dir}/${current.module.path}/${module.xml}">
<replacetoken>
<![CDATA[
<!-- Insert resources here -->]]></replacetoken>
<replacevalue>
</replacevalue>
</replace>
</sequential>
</macrodef>
<macrodef name="bundle-def">
<attribute name="name"/>
<attribute name="slot" default="main"/>
<element name="resources" implicit="yes" optional="yes"/>
<sequential>
<echo message="Initializing bundle -> @{name}"/>
<property name="bundle.repo.output.dir" value="${output.dir}/bundles/system/layers/base"/>
<!-- Figure out the correct bundle path -->
<define-bundle-dir name="@{name}" slot="@{slot}" />
<!-- Make the bundle output director -->
<mkdir dir="${bundle.repo.output.dir}/${current.bundle.path}"/>
<!-- Process the resource -->
<resources/>
</sequential>
</macrodef>
<macrodef name="maven-bundle" >
<attribute name="group"/>
<attribute name="artifact"/>
<sequential>
<!-- Copy the jar to the bundle dir -->
<property name="bundle.repo.output.dir" value="${output.dir}/bundles/system/layers/base"/>
<copy todir="${bundle.repo.output.dir}/${current.bundle.path}" failonerror="true">
<fileset file="${@{group}:@{artifact}:jar}"/>
<mapper type="flatten" />
</copy>
</sequential>
</macrodef>
<scriptdef name="define-module-dir" language="javascript" manager="bsf">
<attribute name="name"/>
<attribute name="slot"/>
<![CDATA[
name = attributes.get("name");
name = name.replace(".", "/");
project.setProperty("current.module.path", name + "/" + attributes.get("slot"));
]]>
</scriptdef>
<scriptdef name="define-bundle-dir" language="javascript" manager="bsf">
<attribute name="name"/>
<attribute name="slot"/>
<![CDATA[
name = attributes.get("name");
name = name.replace(".", "/");
project.setProperty("current.bundle.path", name + "/" + attributes.get("slot"));
]]>
</scriptdef>
<!--
Get the version from the parent directory of the jar. If the parent directory is 'target' this
means that the jar is contained in AS build so extract the version from the file name
-->
<scriptdef name="define-maven-artifact" language="javascript" manager="bsf">
<attribute name="group"/>
<attribute name="artifact"/>
<attribute name="classifier"/>
<attribute name="element"/>
<attribute name="path"/>
<![CDATA[
importClass(Packages.java.io.File);
group = attributes.get("group");
artifact = attributes.get("artifact");
classifier = attributes.get("classifier");
element = attributes.get("element");
path = attributes.get("path");
if(path.indexOf('${') != -1) {
throw "Module resource root not found, make sure it is listed in build/pom.xml" + path;
}
fp = new File(path);
version = fp.getParentFile().getName();
if (version.equals("target")) {
version = fp.getName();
version = version.substring(artifact.length() + 1);
suffix = ".jar";
if (classifier) {
suffix = "-" + classifier + suffix;
}
version = version.replace(suffix, "");
}
root = "<" + element + " name=\"" + group + ":" + artifact + ":" + version;
if (classifier) {
root = root + ":" + classifier;
}
root = root + "\"/>";
project.setProperty("current.maven.root", root);
]]>
</scriptdef>
<macrodef name="maven-resource" >
<attribute name="group"/>
<attribute name="artifact"/>
<attribute name="jandex" default="false" />
<sequential>
<if>
<equals arg1="${mavenized.modules}" arg2="true"/>
<then>
<define-maven-artifact group="@{group}" artifact="@{artifact}" element="artifact" path="${@{group}:@{artifact}:jar}"/>
<replace file="${module.repo.output.dir}/${current.module.path}/${module.xml}">
<replacefilter token="&lt;!-- Insert resources here --&gt;" value="${current.maven.root}&#10; &lt;!-- Insert resources here --&gt;"/>
</replace>
</then>
<else>
<!-- Copy the jar to the module dir -->
<copy todir="${module.repo.output.dir}/${current.module.path}" failonerror="true">
<fileset file="${@{group}:@{artifact}:jar}"/>
<mapper type="flatten" />
</copy>
<basename file="${@{group}:@{artifact}:jar}" property="resourcename.@{group}.@{artifact}"/>
<!-- Generate the Jandex Index -->
<jandex run="@{jandex}" newJar="true" >
<fileset dir="${module.repo.output.dir}/${current.module.path}" />
</jandex>
<!-- Update the resource entry in module.xml -->
<define-resource-root path="${resourcename.@{group}.@{artifact}}" jandex="@{jandex}"/>
<replace file="${module.repo.output.dir}/${current.module.path}/${module.xml}">
<replacefilter token="&lt;!-- Insert resources here --&gt;" value="${current.resource.root}&#10; &lt;!-- Insert resources here --&gt;"/>
</replace>
</else>
</if>
</sequential>
</macrodef>
<macrodef name="maven-resource-with-classifier" >
<attribute name="group"/>
<attribute name="artifact"/>
<attribute name="classifier"/>
<attribute name="jandex" default="false" />
<sequential>
<if>
<equals arg1="${mavenized.modules}" arg2="true"/>
<then>
<define-maven-artifact group="@{group}" artifact="@{artifact}" element="artifact" classifier="@{classifier}" path="${@{group}:@{artifact}:jar:@{classifier}}"/>
<replace file="${module.repo.output.dir}/${current.module.path}/${module.xml}">
<replacefilter token="&lt;!-- Insert resources here --&gt;" value="${current.maven.root}&#10; &lt;!-- Insert resources here --&gt;"/>
</replace>
</then>
<else>
<!-- Copy the jar to the module dir -->
<copy todir="${module.repo.output.dir}/${current.module.path}" failonerror="true">
<fileset file="${@{group}:@{artifact}:jar:@{classifier}}"/>
<!-- http://jira.codehaus.org/browse/MANTRUN-159 -->
<mapper type="flatten" />
</copy>
<basename file="${@{group}:@{artifact}:jar:@{classifier}}" property="resourcename.@{group}.@{artifact}.@{classifier}"/>
<!-- Update the resource entry in module.xml -->
<define-resource-root path="${resourcename.@{group}.@{artifact}.@{classifier}}"/>
<replace file="${module.repo.output.dir}/${current.module.path}/${module.xml}">
<replacefilter token="&lt;!-- Insert resources here --&gt;" value="${current.resource.root}&#10; &lt;!-- Insert resources here --&gt;"/>
</replace>
</else>
</if>
</sequential>
</macrodef>
<macrodef name="extract-native-jar" >
<attribute name="group"/>
<attribute name="artifact"/>
<sequential>
<if>
<equals arg1="${mavenized.modules}" arg2="true"/>
<then>
<define-maven-artifact group="@{group}" artifact="@{artifact}" element="native-artifact" path="${@{group}:@{artifact}:jar}"/>
<replace file="${module.repo.output.dir}/${current.module.path}/${module.xml}">
<replacefilter token="&lt;!-- Insert resources here --&gt;" value="${current.maven.root}&#10; &lt;!-- Insert resources here --&gt;"/>
</replace>
</then>
<else>
<unzip src="${@{group}:@{artifact}:jar}" dest="${module.repo.output.dir}/${current.module.path}">
<patternset>
<include name="lib/**"/>
</patternset>
</unzip>
</else>
</if>
</sequential>
</macrodef>
<scriptdef name="define-resource-root" language="javascript" manager="bsf">
<attribute name="path"/>
<attribute name="jandex"/>
<![CDATA[
path = attributes.get("path");
root = "<resource-root path=\"" + path + "\"/>";
if(path.indexOf('${') != -1) {
throw "Module resource root not found, make sure it is listed in build/pom.xml" + path;
}
if(attributes.get("jandex") == "true" ) {
root = root + "\n\t<resource-root path=\"" + path.replace(".jar","-jandex.jar") + "\"/>";
}
project.setProperty("current.resource.root", root);
]]>
</scriptdef>
</project>

View file

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-as7-modules</artifactId>
<name>Keycloak SAML AS7 / JBoss EAP 6 Modules</name>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-common</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-spi</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-adapter-spi</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jboss-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-subsystem</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jboss-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<inherited>false</inherited>
<executions>
<execution>
<id>build-dist</id>
<goals>
<goal>run</goal>
</goals>
<phase>compile</phase>
<configuration>
<target>
<ant antfile="build.xml" inheritRefs="true">
<target name="all"/>
</ant>
</target>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jandex</artifactId>
<version>1.0.3.Final</version>
</dependency>
<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>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/modules/org/keycloak/keycloak-saml-adapter-subsystem</outputDirectory>
<resources>
<resource>
<directory>src/main/resources/modules/org/keycloak/keycloak-saml-adapter-subsystem</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.bouncycastle">
<resources>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>

View file

@ -2,19 +2,19 @@
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-core-jaxrs">
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-adapter-spi">
<resources>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="org.keycloak.keycloak-common"/>
<module name="org.keycloak.keycloak-core"/>
<module name="org.codehaus.jackson.jackson-core-asl"/>
<module name="org.codehaus.jackson.jackson-mapper-asl"/>
<module name="org.codehaus.jackson.jackson-xc"/>
<module name="javax.ws.rs.api"/>
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.as.web"/>
<module name="javax.servlet.api"/>
<module name="org.apache.httpcomponents"/>
<module name="org.bouncycastle" />
<module name="org.keycloak.keycloak-common"/>
<module name="org.picketbox"/>
</dependencies>
</module>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-common">
<resources>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="org.bouncycastle" />
<module name="javax.api"/>
<module name="javax.activation.api"/>
<module name="sun.jdk" optional="true" />
<module name="sun.jdk.jgss" optional="true" />
</dependencies>
</module>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-jboss-adapter-core">
<resources>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="javax.api"/>
<module name="org.jboss.logging"/>
<module name="org.picketbox"/>
<module name="org.keycloak.keycloak-adapter-spi"/>
<module name="org.keycloak.keycloak-common"/>
</dependencies>
</module>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-saml-adapter-core">
<resources>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="javax.api"/>
<module name="org.jboss.logging"/>
<module name="org.keycloak.keycloak-adapter-spi"/>
<module name="org.keycloak.keycloak-saml-core"/>
<module name="org.keycloak.keycloak-common"/>
</dependencies>
</module>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ JBoss, Home of Professional Open Source.
~ Copyright 2014, Red Hat, Inc., and individual contributors
~ as indicated by the @author tags. See the copyright.txt file in the
~ distribution for a full listing of individual contributors.
~
~ This is free software; you can redistribute it and/or modify it
~ under the terms of the GNU Lesser General Public License as
~ published by the Free Software Foundation; either version 2.1 of
~ the License, or (at your option) any later version.
~
~ This software is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
~ Lesser General Public License for more details.
~
~ You should have received a copy of the GNU Lesser General Public
~ License along with this software; if not, write to the Free
~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-saml-adapter-subsystem">
<resources>
<resource-root path="."/>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="org.keycloak.keycloak-saml-as7-subsystem" export="true" services="export"/>
</dependencies>
</module>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-saml-as7-adapter">
<resources>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="javax.api"/>
<module name="org.bouncycastle" />
<module name="javax.servlet.api"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.as.security"/>
<module name="org.jboss.as.web"/>
<module name="org.picketbox"/>
<module name="org.keycloak.keycloak-saml-as7-adapter"/>
<module name="org.keycloak.keycloak-adapter-spi"/>
<module name="org.keycloak.keycloak-saml-core"/>
<module name="org.keycloak.keycloak-saml-adapter-core"/>
<module name="org.keycloak.keycloak-common"/>
</dependencies>
</module>

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ JBoss, Home of Professional Open Source.
~ Copyright 2014, Red Hat, Inc., and individual contributors
~ as indicated by the @author tags. See the copyright.txt file in the
~ distribution for a full listing of individual contributors.
~
~ This is free software; you can redistribute it and/or modify it
~ under the terms of the GNU Lesser General Public License as
~ published by the Free Software Foundation; either version 2.1 of
~ the License, or (at your option) any later version.
~
~ This software is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
~ Lesser General Public License for more details.
~
~ You should have received a copy of the GNU Lesser General Public
~ License along with this software; if not, write to the Free
~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-saml-as7-subsystem">
<resources>
<resource-root path="."/>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="javax.api"/>
<module name="org.keycloak.keycloak-saml-as7-adapter"/>
<module name="org.jboss.staxmapper"/>
<module name="org.jboss.as.controller"/>
<module name="org.jboss.as.server"/>
<module name="org.jboss.as.web"/>
<module name="org.jboss.modules"/>
<module name="org.jboss.msc"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.vfs"/>
<module name="org.jboss.metadata"/>
</dependencies>
</module>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-saml-core">
<resources>
<!-- Insert resources here -->
</resources>
<dependencies>
<module name="org.jboss.logging"/>
<module name="org.keycloak.keycloak-common"/>
<module name="org.apache.santuario.xmlsec">
<imports>
<exclude path="javax/*"/>
</imports>
</module>
<module name="javax.api"/>
</dependencies>
</module>

View file

@ -0,0 +1,36 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/unpacked</directory>
<includes>
<include>org/keycloak/keycloak-common/**</include>
<include>org/keycloak/keycloak-saml-core/**</include>
<include>org/keycloak/keycloak-saml-adapter-core/**</include>
<include>org/keycloak/keycloak-adapter-spi/**</include>
<include>org/keycloak/keycloak-jboss-adapter-core/**</include>
<include>org/bouncycastle/**</include>
<include>org/keycloak/keycloak-saml-as7-adapter/**</include>
<include>org/keycloak/keycloak-saml-as7-subsystem/**</include>
<include>org/keycloak/keycloak-saml-adapter-subsystem/**</include>
</includes>
<excludes>
<exclude>**/*.war</exclude>
</excludes>
<outputDirectory>modules/system/layers/base</outputDirectory>
</fileSet>
</fileSets>
<files>
<file>
<source>../../shared-cli/adapter-install.cli</source>
<outputDirectory>bin</outputDirectory>
</file>
</files>
</assembly>

View file

@ -0,0 +1,79 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-eap6-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML JBoss EAP 6 Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-adapter</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-modules</artifactId>
<type>zip</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-as7-modules</artifactId>
<type>zip</type>
<outputDirectory>${project.build.directory}/unpacked</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,21 @@
<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">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML AS7 / JBoss EAP 6 Adapter Distros</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-saml-as7-eap6-adapter-dist-pom</artifactId>
<packaging>pom</packaging>
<modules>
<module>as7-modules</module>
<module>as7-adapter-zip</module>
<module>eap6-adapter-zip</module>
</modules>
</project>

View file

@ -0,0 +1,26 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>org.keycloak:keycloak-saml-jetty81-adapter</include>
</includes>
<excludes>
<exclude>org.eclipse.jetty:jetty-server</exclude>
<exclude>org.eclipse.jetty:jetty-util</exclude>
<exclude>org.eclipse.jetty:jetty-security</exclude>
</excludes>
<outputDirectory>lib/keycloak</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View file

@ -0,0 +1,51 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-jetty81-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML Jetty 8.1.x Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty81-adapter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,39 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory></directory>
<includes>
<include>keycloak.mod</include>
</includes>
<outputDirectory>modules</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}/modules</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>org.keycloak:keycloak-saml-jetty91-adapter</include>
</includes>
<excludes>
<exclude>org.eclipse.jetty:jetty-server</exclude>
<exclude>org.eclipse.jetty:jetty-util</exclude>
<exclude>org.eclipse.jetty:jetty-security</exclude>
</excludes>
<outputDirectory>lib/keycloak</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View file

@ -0,0 +1,11 @@
#
# Keycloak Jetty Adapter
#
[depend]
server
security
[lib]
lib/keycloak/*.jar

View file

@ -0,0 +1,51 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-jetty91-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML Jetty 9.1.x Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty91-adapter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,39 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory></directory>
<includes>
<include>keycloak.mod</include>
</includes>
<outputDirectory>modules</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}/modules</directory>
<outputDirectory></outputDirectory>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>org.keycloak:keycloak-saml-jetty92-adapter</include>
</includes>
<excludes>
<exclude>org.eclipse.jetty:jetty-server</exclude>
<exclude>org.eclipse.jetty:jetty-util</exclude>
<exclude>org.eclipse.jetty:jetty-security</exclude>
</excludes>
<outputDirectory>lib/keycloak</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View file

@ -0,0 +1,11 @@
#
# Keycloak Jetty Adapter
#
[depend]
server
security
[lib]
lib/keycloak/*.jar

View file

@ -0,0 +1,51 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-jetty92-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML Jetty 9.2.x Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty92-adapter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -16,5 +16,13 @@
<modules>
<module>wf9-adapter</module>
<module>tomcat6-adapter-zip</module>
<module>tomcat7-adapter-zip</module>
<module>tomcat8-adapter-zip</module>
<module>jetty81-adapter-zip</module>
<!-- jetty 9.1 doesn't work right now
<module>jetty91-adapter-zip</module> -->
<module>jetty92-adapter-zip</module>
<module>as7-eap6-adapter</module>
</modules>
</project>

View file

@ -0,0 +1,24 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>org.keycloak:keycloak-saml-tomcat6-adapter</include>
</includes>
<excludes>
<exclude>org.apache.tomcat:catalina</exclude>
</excludes>
<outputDirectory></outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View file

@ -0,0 +1,51 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-tomcat6-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML Tomcat 6 Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat6-adapter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,25 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>org.keycloak:keycloak-saml-tomcat7-adapter</include>
</includes>
<excludes>
<exclude>org.apache.tomcat:tomcat-servlet-api</exclude>
<exclude>org.apache.tomcat:tomcat-catalina</exclude>
</excludes>
<outputDirectory></outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View file

@ -0,0 +1,51 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-tomcat7-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML Tomcat 7 Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat7-adapter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,25 @@
<assembly>
<id>war-dist</id>
<formats>
<format>zip</format>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>true</useTransitiveDependencies>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>org.keycloak:keycloak-saml-tomcat8-adapter</include>
</includes>
<excludes>
<exclude>org.apache.tomcat:tomcat-servlet-api</exclude>
<exclude>org.apache.tomcat:tomcat-catalina</exclude>
</excludes>
<outputDirectory></outputDirectory>
</dependencySet>
</dependencySets>
</assembly>

View file

@ -0,0 +1,51 @@
<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>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>keycloak-saml-tomcat8-adapter-dist</artifactId>
<packaging>pom</packaging>
<name>Keycloak SAML Tomcat 8 Adapter Distro</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-tomcat8-adapter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<outputDirectory>
target
</outputDirectory>
<workDirectory>
target/assembly/work
</workDirectory>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -63,10 +63,6 @@
<maven-resource group="org.keycloak" artifact="keycloak-broker-saml"/>
</module-def>
<module-def name="org.keycloak.keycloak-core-jaxrs">
<maven-resource group="org.keycloak" artifact="keycloak-core-jaxrs"/>
</module-def>
<module-def name="org.keycloak.keycloak-services">
<maven-resource group="org.keycloak" artifact="keycloak-services"/>
</module-def>

View file

@ -30,10 +30,6 @@
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-server-subsystem</artifactId>

View file

@ -11,7 +11,6 @@
<module name="org.keycloak.keycloak-connections-file" services="import"/>
<module name="org.keycloak.keycloak-common" services="import"/>
<module name="org.keycloak.keycloak-core" services="import"/>
<module name="org.keycloak.keycloak-core-jaxrs" services="import"/>
<module name="org.keycloak.keycloak-email-api" services="import"/>
<module name="org.keycloak.keycloak-email-freemarker" services="import"/>
<module name="org.keycloak.keycloak-events-api" services="import"/>

View file

@ -21,7 +21,6 @@
<module name="org.keycloak.keycloak-connections-file" services="import"/>
<module name="org.keycloak.keycloak-common" services="import"/>
<module name="org.keycloak.keycloak-core" services="import"/>
<module name="org.keycloak.keycloak-core-jaxrs" services="import"/>
<module name="org.keycloak.keycloak-email-api" services="import"/>
<module name="org.keycloak.keycloak-email-freemarker" services="import"/>
<module name="org.keycloak.keycloak-events-api" services="import"/>

View file

@ -47,6 +47,7 @@
<!ENTITY ProtocolMappers SYSTEM "modules/protocol-mappers.xml">
<!ENTITY Recaptcha SYSTEM "modules/recaptcha.xml">
<!ENTITY AuthSPI SYSTEM "modules/auth-spi.xml">
<!ENTITY FilterAdapter SYSTEM "modules/servlet-filter-adapter.xml">
]>
<book>
@ -94,11 +95,18 @@ This one is short
types are supported and how to configure and install them so that you can use Keycloak to secure
your applications.
</para>
<para>
These client adapters use an extension of the OpenID Connect protocol (a derivate of OAuth 2.0).
This extension provides support for clustering, backchannel logout, and other non-standard adminstrative functions.
The Keycloak project also provides a separate, standalone, generic, SAML client adapter. But that is describe in a separate
document and has a different download.
</para>
&AdapterConfig;
&JBossAdapter;
&TomcatAdapter;
&Jetty9Adapter;
&Jetty8Adapter;
&FilterAdapter;
&FuseAdapter;
&JavascriptAdapter;
&SpringBootAdapter;

View file

@ -209,6 +209,7 @@ new Keycloak({ url: 'http://localhost/auth', realm: 'myrealm', clientId: 'myApp'
<listitem>redirectUri - specifies the uri to redirect to after login</listitem>
<listitem>prompt - can be set to 'none' to check if the user is logged in already (if not logged in, a login form is not displayed)</listitem>
<listitem>loginHint - used to pre-fill the username/email field on the login form</listitem>
<listitem>action - if value is 'register' then user is redirected to registration page, otherwise to login page</listitem>
</itemizedlist>
</para>
</simplesect>
@ -246,6 +247,20 @@ new Keycloak({ url: 'http://localhost/auth', realm: 'myrealm', clientId: 'myApp'
</para>
</simplesect>
<simplesect>
<title>register(options)</title>
<para>Redirects to registration form. It's a shortcut for doing login with option action = 'register'</para>
<para>Options are same as login method but 'action' is overwritten to 'register'</para>
</simplesect>
<simplesect>
<title>createRegisterUrl(options)</title>
<para>Returns the url to registration page. It's a shortcut for doing createRegisterUrl with option action = 'register'</para>
<para>Options are same as createLoginUrl method but 'action' is overwritten to 'register'</para>
</simplesect>
<simplesect>
<title>accountManagement()</title>

View file

@ -0,0 +1,51 @@
<section>
<title>Java Servlet Filter Adapter</title>
<para>
If you want to use Keycloak with a Java servlet application that doesn't have an adapter for that servlet
platform, you can opt to use the servlet filter adapter that Keycloak has. This adapter works a little
differently than the other adapters. You do not define security constraints in web.xml. Instead you define
a filter mapping using the Keycloak servlet filter adapter to secure the url patterns you want to secure.
</para>
<warning>
<para>
Backchannel logout works a bit differently than the standard adapters. Instead of invalidating the http session
it instead marks the session id as logged out. There's just no way of arbitrarily invalidating an http session
based on a session id.
</para>
</warning>
<programlisting>
<![CDATA[
<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>
<filter>
<filter-name>Keycloak Filter</filter-name>
<filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Keycloak Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
]]>
</programlisting>
<para>
The Keycloak filter has the same configuration parameters available as the other adapters except you must define
them as filter init params instead of context params.
</para>
<para>
To use this filter, include this maven artifact in your WAR poms
</para>
<programlisting><![CDATA[
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>
<version>&project.version;</version>
</dependency>
]]></programlisting>
</section>

View file

@ -10,7 +10,7 @@
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-saml-pom</artifactId>
<artifactId>keycloak-docbook-parent</artifactId>
<packaging>pom</packaging>
<modules>

View file

@ -1,13 +1,21 @@
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.docbook.org/xml/4.4/docbookx.dtd"
[
<!ENTITY Overview SYSTEM "modules/overview.xml">
<!ENTITY AdapterConfig SYSTEM "modules/adapter-config.xml">
<!ENTITY JBossAdapter SYSTEM "modules/jboss-adapter.xml">
<!ENTITY TomcatAdapter SYSTEM "modules/tomcat-adapter.xml">
<!ENTITY Jetty9Adapter SYSTEM "modules/jetty9-adapter.xml">
<!ENTITY Jetty8Adapter SYSTEM "modules/jetty8-adapter.xml">
<!ENTITY FilterAdapter SYSTEM "modules/servlet-filter-adapter.xml">
<!ENTITY Logout SYSTEM "modules/logout.xml">
]>
<book>
<bookinfo>
<title>Keycloak SAML Client Adapter Reference Guide</title>
<subtitle>SAML 2.0 Client Adapters for Java Applications</subtitle>
<subtitle>SAML 2.0 Client Adapters</subtitle>
<releaseinfo>&project.version;</releaseinfo>
</bookinfo>
@ -33,6 +41,15 @@ This one is short
</programlisting>
</para>
</preface>
&Overview;
&AdapterConfig;
&JBossAdapter;
&TomcatAdapter;
&Jetty9Adapter;
&Jetty8Adapter;
&FilterAdapter;
&Logout;
</book>

View file

@ -0,0 +1,475 @@
<chapter id="adapter-config">
<title>General Adapter Config</title>
<para>
Each SAML adapter supported by Keycloak can be configured by a simple XML text file. This is what one might
look like:
</para>
<para>
<programlisting><![CDATA[
<keycloak-saml-adapter>
<SP entityID="http://localhost:8081/sales-post-sig/"
sslPolicy="EXTERNAL"
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
logoutPage="/logout.jsp"
forceAuthentication="false">
<Keys>
<Key signing="true" >
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
<PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
<Certificate alias="http://localhost:8080/sales-post-sig/"/>
</KeyStore>
</Key>
</Keys>
<PrincipalNameMapping policy="FROM_NAME_ID"/>
<RoleMapping>
<Attribute name="Role"/>
</RoleMapping>
<IDP entityID="idp"
signaturesRequired="true">
<SingleSignOnService requestBinding="POST"
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
/>
<SingleLogoutService
requestBinding="POST"
responseBinding="POST"
postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
/>
<Keys>
<Key signing="true">
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
<Certificate alias="demo"/>
</KeyStore>
</Key>
</Keys>
</IDP>
</SP>
</keycloak-saml-adapter>]]>
</programlisting>
</para>
<para>
Some of these configuration switches may be adapter specific and some are common across all adapters.
For Java adapters you can use <literal>${...}</literal> enclosure as System property replacement.
For example <literal>${jboss.server.config.dir}</literal>.
</para>
<section>
<title>SP Element</title>
<para>
Here is the explanation of the SP element attributes
</para>
<programlisting><![CDATA[
<SP entityID="sp"
sslPolicy="ssl"
nameIDPolicyFormat="format"
forceAuthentication="true">
...
</SP>]]></programlisting>
<para>
<variablelist>
<varlistentry>
<term>entityID</term>
<listitem>
<para>
This is the identifier for this client. The IDP needs this value to determine
who the client is that is communicating with it.
<emphasis>REQUIRED.</emphasis>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>sslPolicy</term>
<listitem>
<para>
This is the SSL policy the adapter will enforce. Valid values are:
ALL, EXTERNAL, and NONE. For ALL, all requests must come in via HTTPS. For
EXTERNAL, only non-private IP addresses must come over the wire via HTTPS. For
NONE, no requests are required to come over via HTTPS. This is
<emphasis>OPTIONAL.</emphasis> and defaults to EXTERNAL.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>nameIDPolicyFormat</term>
<listitem>
<para>
SAML clients can request a specific NameID Subject format. Fill in this value
if you want a specific format. It must be a standard SAML format identifier, i.e.
<literal>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</literal>
<emphasis>OPTIONAL.</emphasis>. By default, no special format is requested.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>forceAuthentication</term>
<listitem>
<para>
SAML clients can request that a user is re-authenticated even if
they are already logged in at the IDP. Set this to true if you
want this.
<emphasis>OPTIONAL.</emphasis>. Set to <literal>false</literal> by default.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section id="sp_keys">
<title>SP Keys and Key elements</title>
<para>
If the IDP requires that the SP sign all of its requests and/or if the IDP will
encrypt assertions, you must define the keys used to do this. For client signed
documents you must define both the private and public key or certificate that will
be used to sign documents. For encryption, you only have to define the private key
that will be used to decrypt.
</para>
<para>
There are two ways to describe your keys. Either they are stored within a Java KeyStore
or you can cut and paste the keys directly within <literal>keycloak-saml.xml</literal>
in the PEM format.
</para>
<programlisting><![CDATA[
<Keys>
<Key signing="true" >
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
<PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
<Certificate alias="http://localhost:8080/sales-post-sig/"/>
</KeyStore>
</Key>
</Keys>
]]>
</programlisting>
<para>
The <literal>Key</literal> element has two optional attributes <literal>signing</literal>
and <literal>encryption</literal>. When set to true these tell the adapter what the
key will be used for. If both attributes are set to true, then the key will be used for both
signing documents and decrypting encrypted assertions. You must set at least one of these
attributes to true.
</para>
<section id="keystore">
<title>KeyStore element</title>
<para>
<variablelist>
<varlistentry>
<term>file</term>
<listitem>
<para>
File path to the key store.
<emphasis>OPTIONAL.</emphasis> The file or resource attribute
must be set.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>resource</term>
<listitem>
<para>
WAR resource path to the KeyStore. This is a path used in method call to ServletContext.getResourceAsStream().
<emphasis>OPTIONAL.</emphasis> The file or resource attribute
must be set.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>password</term>
<listitem>
<para>
The password of the KeyStore
<emphasis>REQUIRED.</emphasis>
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
You can and must also specify references to your private keys and certificates within
the Java KeyStore. The <literal>PrivateKey</literal> and <literal>Certificate</literal>
elements do this. The <literal>alias</literal> attribute defines the alias within the
KeyStore for the key. For <literal>PrivateKey</literal>, a password is required to access this key
specify that value in the <literal>password</literal> attribute.
</para>
</section>
<section id="key_pems">
<title>Key PEMS</title>
<para>
Within the <literal>Key</literal> element you alternatively declare your keys and certificates
directly using the sub elements <literal>PrivateKeyPem</literal>, <literal>PublicKeyPem</literal>, and
<literal>CertificatePem</literal>. The values contained in these elements must conform to the
PEM key format. You usually use this option if you are generating keys using <literal>openssl</literal>
</para>
</section>
</section>
<section>
<title>SP PrincipalNameMapping element</title>
<para>
This element is optional. When creating a Java Principal object that you obtain from
methods like HttpServletRequest.getUserPrincipal(), you can define what name that is returned
by the Principal.getName() method. The <literal>policy</literal> attribute defines the
policy used to populate this value. The values are <literal>FROM_NAME_ID</literal>. This policy
just grabs whatever the SAML subject value is. The other is <literal>FROM_ATTRIBUTE</literal>. This will
pull the value of Principal.getName() from one of the attributes in the SAML assertion received from the server.
The default value is <literal>FROM_NAME_ID</literal>.
</para>
</section>
<section>
<title>RoleIdentifiers element</title>
<programlisting><![CDATA[
<RoleIdentifiers>
<Attribute name="Role"/>
<Attribute name="member"/>
<Attribute name="memberOf"/>
</RoleIdentifiers>
]]></programlisting>
<para>
This element is optional. It defines which SAML attribute values in the assertion should be
mapped to a Java EE role. By default <literal>Role</literal> attribute values are converted
to Java EE roles. Some IDPs send roles via a <literal>member</literal> or <literal>memberOf</literal>
attribute assertion. You define one or more <literal>Attribute</literal> elements to specify
which SAML attributes must be converted into roles.
</para>
</section>
<section>
<title>IDP Element</title>
<para>
Everything in the IDP element describes the settings for the IDP the SP is communicating
with.
</para>
<programlisting>
<![CDATA[
<IDP entityID="idp"
signaturesRequired="true"
signatureAlgorithm="RSA_SHA1"
signatureCanonicalizationMethod="http://www.w3.org/2001/10/xml-exc-c14n#">
...
</IDP>]]>
</programlisting>
<para>
<variablelist>
<varlistentry>
<term>entityID</term>
<listitem>
<para>
This is the issuer ID of the IDP.
<emphasis>REQUIRED.</emphasis>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>signaturesRequired</term>
<listitem>
<para>
If set to true, the client adapter will sign every document
it sends to the IDP. Also, the client will expect that the IDP
will be signing an documents sent to it. This switch sets
the default for all request and response types, but you will see
later that you have some fine grain control over this.
<emphasis>OPTIONAL.</emphasis>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>signatureAlgorithm</term>
<listitem>
<para>
This is the signature algorithm that the IDP expects signed documents
to use
<emphasis>OPTIONAL.</emphasis>. The default value is RSA_SHA256, but
you can also use RSA_SHA1, RSA_256, RSA_512, and DSA_SHA1.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>signatureCanonicalizationMethod</term>
<listitem>
<para>
This is the signature canonicalization method that the IDP expects signed documents
to use
<emphasis>OPTIONAL.</emphasis>. The default value is <literal>http://www.w3.org/2001/10/xml-exc-c14n#</literal>
and should be good for most IDPs.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section>
<title>IDP SingleSignOnService sub element</title>
<para>
The <literal>SignleSignOnService</literal> sub element defines the
login SAML endpoint of the IDP.
</para>
<programlisting><![CDATA[
<SingleSignOnService signRequest="true"
validateResponseSignature="true"
requestBinding="post"
bindingUrl="url"/>
]]></programlisting>
<para>
<variablelist>
<varlistentry>
<term>signRequest</term>
<listitem>
<para>
Should the client sign authn requests?
<emphasis>OPTIONAL.</emphasis>. Defaults to whatever the
IDP <literal>signaturesRequired</literal> element value is.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>validateResponseSignature</term>
<listitem>
<para>
Should the client expect the IDP to sign the assertion response document
sent back from an auhtn request?
<emphasis>OPTIONAL.</emphasis> Defaults to whatever the
IDP <literal>signaturesRequired</literal> element value is.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>requestBinding</term>
<listitem>
<para>
This is the SAML binding type used for communicating with the IDP
<emphasis>OPTIONAL.</emphasis>. The default value is POST, but
you can set it to REDIRECT as well.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>responseBinding</term>
<listitem>
<para>
SAML allows the client to request what binding type it wants authn responses
to use. The values of this can be POST or REDIRECT
<emphasis>OPTIONAL.</emphasis>. The default is that the client will not request
a specific binding type for responses.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>bindingUrl</term>
<listitem>
<para>
This is the URL for the ID login service that the client will send requests to.
<emphasis>REQUIRED.</emphasis>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section> <section>
<title>IDP SingleSignOnService sub element</title>
<para>
The <literal>SignleSignOnService</literal> sub element defines the
login SAML endpoint of the IDP.
</para>
<programlisting><![CDATA[
<SingleLogoutService validateRequestSignature="true"
validateResponseSignature="true"
signRequest="true"
signResponse="true"
requestBinding="redirect"
responseBinding="post"
postBindingUrl="posturl"
redirectBindingUrl="redirecturl">
]]></programlisting>
<para>
<variablelist>
<varlistentry>
<term>signRequest</term>
<listitem>
<para>
Should the client sign logout requests it makes to the IDP?
<emphasis>OPTIONAL.</emphasis>. Defaults to whatever the
IDP <literal>signaturesRequired</literal> element value is.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>signResponse</term>
<listitem>
<para>
Should the client sign logout responses it sends to the IDP requests?
<emphasis>OPTIONAL.</emphasis>. Defaults to whatever the
IDP <literal>signaturesRequired</literal> element value is.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>validateRequestSignature</term>
<listitem>
<para>
Should the client expect signed logout request documents from the IDP?
<emphasis>OPTIONAL.</emphasis> Defaults to whatever the
IDP <literal>signaturesRequired</literal> element value is.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>validateResponseSignature</term>
<listitem>
<para>
Should the client expect signed logout response documents from the IDP?
<emphasis>OPTIONAL.</emphasis> Defaults to whatever the
IDP <literal>signaturesRequired</literal> element value is.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>requestBinding</term>
<listitem>
<para>
This is the SAML binding type used for communicating SAML requests to the IDP
<emphasis>OPTIONAL.</emphasis>. The default value is POST, but
you can set it to REDIRECT as well.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>responseBinding</term>
<listitem>
<para>
This is the SAML binding type used for communicating SAML responses to the IDP
The values of this can be POST or REDIRECT
<emphasis>OPTIONAL.</emphasis>. The default value is POST, but
you can set it to REDIRECT as well.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>postBindingUrl</term>
<listitem>
<para>
This is the URL for the IDP's logout service when using the POST binding.
<emphasis>REQUIRED</emphasis> if using the POST binding at all.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>redirectBindingUrl</term>
<listitem>
<para>
This is the URL for the IDP's logout service when using the REDIRECT binding.
<emphasis>REQUIRED</emphasis> if using the REDIRECT binding at all.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</section>
<section>
<title>IDP Keys subelement</title>
<para>
The Keys sub element of IDP is only used to define the certificate or
public key to use to verify documents signed by the IDP. It is defined
in the same way as the <link linkend="sp_keys">SP's Key's element</link>. But
again, you only have to define one certificate or public key reference.
</para>
</section>
</chapter>

View file

@ -0,0 +1,188 @@
<chapter id="jboss-adapter">
<title>JBoss/Wildfly Adapter</title>
<para>
To be able to secure WAR apps deployed on JBoss EAP 6.x or Wildfly, you must install and
configure the Keycloak SAML Adapter Subsystem. You then provide a keycloak
config, <literal>/WEB-INF/keycloak-saml</literal> file in your WAR and change the auth-method to KEYCLOAK-SAML within web.xml.
Both methods are described in this section.
</para>
<section id="jboss-adapter-installation">
<title>Adapter Installation</title>
<para>
SAML Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
the Keycloak download site. They are also available as a maven artifact.
</para>
<para>
Install on Wildfly 9:
<programlisting>
$ cd $WILDFLY_HOME
$ unzip keycloak-saml-wf9-adapter-dist.zip
</programlisting>
</para>
<para>
Install on JBoss EAP 6.x:
<programlisting>
$ cd $JBOSS_HOME
$ unzip keycloak-saml-eap6-adapter-dist.zip
</programlisting>
</para>
<para>
This zip file creates new JBoss Modules specific to the Wildfly Keycloak SAML Adapter within your Wildfly distro.
</para>
<para>
After adding the Keycloak modules, you must then enable the Keycloak SAML Subsystem within your app server's server configuration:
<literal>domain.xml</literal> or <literal>standalone.xml</literal>.
</para>
<para>
There is a CLI script that will help you modify your server configuration. Start the server and run the script
from the server's bin directory:
<programlisting>
$ cd $JBOSS_HOME/bin
$ jboss-cli.sh -c --file=adapter-install.cli
</programlisting>
The script will add the extension, subsystem, and optional security-domain as described below.
</para>
<para>
<programlisting><![CDATA[
<server xmlns="urn:jboss:domain:1.4">
<extensions>
<extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
...
</extensions>
<profile>
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.6"/>
...
</profile>
]]>
</programlisting>
</para>
<para>
The keycloak security domain should be used with EJBs and other components when you need the security context created
in the secured web tier to be propagated to the EJBs (other EE component) you are invoking. Otherwise
this configuration is optional.
</para>
<programlisting><![CDATA[
<server xmlns="urn:jboss:domain:1.4">
<subsystem xmlns="urn:jboss:domain:security:1.2">
<security-domains>
...
<security-domain name="keycloak">
<authentication>
<login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule"
flag="required"/>
</authentication>
</security-domain>
</security-domains>
]]>
</programlisting>
<para>
For example, if you have a JAX-RS service that is an EJB within your WEB-INF/classes directory, you'll want
to annotate it with the @SecurityDomain annotation as follows:
</para>
<programlisting><![CDATA[
import org.jboss.ejb3.annotation.SecurityDomain;
import org.jboss.resteasy.annotations.cache.NoCache;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.ArrayList;
import java.util.List;
@Path("customers")
@Stateless
@SecurityDomain("keycloak")
public class CustomerService {
@EJB
CustomerDB db;
@GET
@Produces("application/json")
@NoCache
@RolesAllowed("db_user")
public List<String> getCustomers() {
return db.getCustomers();
}
}
]]>
</programlisting>
<para>
We hope to improve our integration in the future so that you don't have to specify the @SecurityDomain
annotation when you want to propagate a keycloak security context to the EJB tier.
</para>
</section>
<section>
<title>Required Per WAR Configuration</title>
<para>
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
</para>
<para>
The first thing you must do is create
a <literal>keycloak-saml.xml</literal> adapter config file within the <literal>WEB-INF</literal> directory
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
section.
</para>
<para>
Next you must set the <literal>auth-method</literal> to <literal>KEYCLOAK-SAML</literal> in <literal>web.xml</literal>. You also
have to use standard servlet security to specify role-base constraints on your URLs. Here's an example
pulled from one of the examples that comes distributed with Keycloak.
</para>
<para>
<programlisting>
<![CDATA[
<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>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admins</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Customers</web-resource-name>
<url-pattern>/customers/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>KEYCLOAK-SAML</auth-method>
<realm-name>this is ignored currently</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>
]]>
</programlisting>
</para>
</section>
</chapter>

View file

@ -0,0 +1,49 @@
<chapter id="jetty8-adapter">
<title>Jetty 8.1.x SAML Adapter</title>
<para>
Keycloak has a separate SAML adapter for Jetty 8.1.x that you will have to install into your Jetty
installation. You then have to provide some extra configuration in each WAR you deploy to
Jetty. Let's go over these steps.
</para>
<section id="jetty8-adapter-installation">
<title>Adapter Installation</title>
<para>
Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
the Keycloak download site. They are also available as a maven artifact.
</para>
<para>
You must unzip the Jetty 8.1.x distro into Jetty 8.1.x's root directory. Including
adapter's jars within your WEB-INF/lib directory will not work!
</para>
<para>
<programlisting>
$ cd $JETTY_HOME
$ unzip keycloak-saml-jetty81-adapter-dist.zip
</programlisting>
</para>
<para>
Next, you will have to enable the keycloak option. Edit start.ini and add keycloak to the options
</para>
<para>
<programlisting>
<![CDATA[
#===========================================================
# Start classpath OPTIONS.
# These control what classes are on the classpath
# for a full listing do
# java -jar start.jar --list-options
#-----------------------------------------------------------
OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations,keycloak
]]>
</programlisting>
</para>
</section>
<section>
<title>Required Per WAR Configuration</title>
<para>
Enabling Keycloak for your WARs is the same as the Jetty 9.x adapter. See <link linkend="jetty9_per_war">Required Per WAR Configuration</link>
</para>
</section>
</chapter>

View file

@ -0,0 +1,106 @@
<chapter id="jetty9-adapter">
<title>Jetty 9.x SAML Adapters</title>
<para>
Keycloak has a separate SAML adapter for Jetty 9.x. You then have to provide some extra configuration in each WAR you deploy to
Jetty. Let's go over these steps.
</para>
<section id="jetty9-adapter-installation">
<title>Adapter Installation</title>
<para>
Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on
the Keycloak download site. They are also available as a maven artifact.
</para>
<para>
You must unzip the Jetty 9.x distro into Jetty 9.x's root directory. Including
adapter's jars within your WEB-INF/lib directory will not work!
</para>
<para>
<programlisting>
$ cd $JETTY_HOME
$ unzip keycloak-saml-jetty92-adapter-dist.zip
</programlisting>
</para>
<para>
Next, you will have to enable the keycloak module for your jetty.base.
</para>
<para>
<programlisting>
$ cd your-base
$ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak
</programlisting>
</para>
</section>
<section id="jetty9_per_war">
<title>Required Per WAR Configuration</title>
<para>
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
</para>
<para>
The first thing you must do is create a <literal>WEB-INF/jetty-web.xml</literal> file in your WAR package. This is
a Jetty specific config file and you must define a Keycloak specific authenticator within it.
</para>
<programlisting>
<![CDATA[
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Get name="securityHandler">
<Set name="authenticator">
<New class="org.keycloak.adapters.saml.jetty.KeycloakSamlAuthenticator">
</New>
</Set>
</Get>
</Configure>]]>
</programlisting>
<para>
Next you must create
a <literal>keycloak-saml.xml</literal> adapter config file within the <literal>WEB-INF</literal> directory
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
section.
</para>
<para>
Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
role-base constraints on your URLs. Here's an example:
</para>
<para>
<programlisting>
<![CDATA[
<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>
<security-constraint>
<web-resource-collection>
<web-resource-name>Customers</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>user</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>this is ignored currently</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>
]]>
</programlisting>
</para>
</section>
</chapter>

View file

@ -0,0 +1,10 @@
<chapter>
<title>Logout</title>
<para>
There are multiple ways you can logout from a web application. For Java EE servlet containers, you can call
HttpServletRequest.logout().
For any other browser application, you can point the browser at any url of your web application that has
a security constraing and pass in a query parameter GLO, i.e. <literal>http://myapp?GLO=true</literal>.
This will log you out if you have an SSO session with your browser.
</para>
</chapter>

View file

@ -0,0 +1,56 @@
<chapter id="multi_tenancy">
<title>Multi Tenancy</title>
<para>
Multi Tenancy, in our context, means that one single target application (WAR) can be secured by a single (or clustered) Keycloak server, authenticating
its users against different realms. In practice, this means that one application needs to use different <literal>keycloak.json</literal> files.
For this case, there are two possible solutions:
<itemizedlist>
<listitem>
The same WAR file deployed under two different names, each with its own Keycloak configuration (probably via the Keycloak Subsystem).
This scenario is suitable when the number of realms is known in advance or when there's a dynamic provision of application instances.
One example would be a service provider that dynamically creates servers/deployments for their clients, like a PaaS.
</listitem>
<listitem>
A WAR file deployed once (possibly in a cluster), that decides which realm to authenticate against based on the request parameters.
This scenario is suitable when there are an undefined number of realms. One example would be a SaaS provider that have only one deployment
(perhaps in a cluster) serving several companies, differentiating between clients based on the hostname
(<literal>client1.acme.com</literal>, <literal>client2.acme.com</literal>) or path (<literal>/app/client1/</literal>,
<literal>/app/client2/</literal>) or even via a special HTTP Header.
</listitem>
</itemizedlist>
This chapter of the reference guide focus on this second scenario.
</para>
<para>
Keycloak provides an extension point for applications that need to evaluate the realm on a request basis. During the authentication
and authorization phase of the incoming request, Keycloak queries the application via this extension point and expects the application
to return a complete representation of the realm. With this, Keycloak then proceeds the authentication and authorization process,
accepting or refusing the request based on the incoming credentials and on the returned realm.
For this scenario, an application needs to:
<itemizedlist>
<listitem>
Add a context parameter to the <literal>web.xml</literal>, named <literal>keycloak.config.resolver</literal>.
The value of this property should be the fully qualified name of the class extending
<literal>org.keycloak.adapters.KeycloakConfigResolver</literal>.
</listitem>
<listitem>
A concrete implementation of <literal>org.keycloak.adapters.KeycloakConfigResolver</literal>. Keycloak will call the
<literal>resolve(org.keycloak.adapters.HttpFacade.Request)</literal> method and expects a complete
<literal>org.keycloak.adapters.KeycloakDeployment</literal> in response. Note that Keycloak will call this for every request,
so, take the usual performance precautions.
</listitem>
</itemizedlist>
</para>
<para>
An implementation of this feature can be found in the examples.
</para>
</chapter>

View file

@ -0,0 +1,9 @@
<chapter>
<title>Overview</title>
<para>
This document describes the Keycloak SAML client adapter and how it can be configured for a variety of platforms.
The Keycloak SAML client adapter is a standalone component that provides generic SAML 2.0 support for your web applications.
There are no Keycloak server extensions built into it. As long as the IDP you are talking to supports standard SAML, the
Keycloak SAML client adapter should be able to integrate with it.
</para>
</chapter>

View file

@ -0,0 +1,55 @@
<chapter>
<title>Java Servlet Filter Adapter</title>
<para>
If you want to use SAML with a Java servlet application that doesn't have an adapter for that servlet
platform, you can opt to use the servlet filter adapter that Keycloak has. This adapter works a little
differently than the other adapters. You do not define security constraints in web.xml. Instead you define
a filter mapping using the Keycloak servlet filter adapter to secure the url patterns you want to secure.
</para>
<warning>
<para>
Backchannel logout works a bit differently than the standard adapters. Instead of invalidating the http session
it instead marks the session id as logged out. There's just no way of arbitrarily invalidating an http session
based on a session id.
</para>
</warning>
<warning>
<para>
Backchannel logout does not currently work when you have a clustered application that uses the SAML filter.
</para>
</warning>
<programlisting>
<![CDATA[
<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>
<filter>
<filter-name>Keycloak Filter</filter-name>
<filter-class>org.keycloak.adapters.saml.servlet.SamlFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Keycloak Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
]]>
</programlisting>
<para>
The Keycloak filter has the same configuration parameters available as the other adapters except you must define
them as filter init params instead of context params.
</para>
<para>
To use this filter, include this maven artifact in your WAR poms
</para>
<programlisting><![CDATA[
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-servlet-filter-adapter</artifactId>
<version>&project.version;</version>
</dependency>
]]></programlisting>
</chapter>

View file

@ -0,0 +1,92 @@
<chapter id="tomcat-adapter">
<title>Tomcat 6, 7 and 8 SAML dapters</title>
<para>
To be able to secure WAR apps deployed on Tomcat 6, 7 and 8 you must install the Keycloak Tomcat 6, 7 or 8 SAML adapter
into your Tomcat installation. You then have to provide some extra configuration in each WAR you deploy to
Tomcat. Let's go over these steps.
</para>
<section id="tomcat-adapter-installation">
<title>Adapter Installation</title>
<para>
Adapters are no longer included with the appliance or war distribution. Each adapter is a separate download on
the Keycloak download site. They are also available as a maven artifact.
</para>
<para>
You must unzip the adapter distro into Tomcat's <literal>lib/</literal> directory. Including
adapter's jars within your WEB-INF/lib directory will not work! The Keycloak SAML adapter is implemented as a Valve
and valve code must reside in Tomcat's main lib/ directory.
</para>
<para>
<programlisting>
$ cd $TOMCAT_HOME/lib
$ unzip keycloak-saml-tomcat6-adapter-dist.zip
or
$ unzip keycloak-saml-tomcat7-adapter-dist.zip
or
$ unzip keycloak-saml-tomcat8-adapter-dist.zip
</programlisting>
</para>
</section>
<section>
<title>Required Per WAR Configuration</title>
<para>
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
</para>
<para>
The first thing you must do is create a <literal>META-INF/context.xml</literal> file in your WAR package. This is
a Tomcat specific config file and you must define a Keycloak specific Valve.
</para>
<programlisting>
<![CDATA[
<Context path="/your-context-path">
<Valve className="org.keycloak.adapters.saml.tomcat.SamlAuthenticatorValve"/>
</Context>]]>
</programlisting>
<para>
Next you must create
a <literal>keycloak-saml.xml</literal> adapter config file within the <literal>WEB-INF</literal> directory
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
section.
</para>
<para>
Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
role-base constraints on your URLs. Here's an example:
</para>
<para>
<programlisting>
<![CDATA[
<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>
<security-constraint>
<web-resource-collection>
<web-resource-name>Customers</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>BASIC</auth-method>
<realm-name>this is ignored currently</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
</security-role>
<security-role>
<role-name>user</role-name>
</security-role>
</web-app>
]]>
</programlisting>
</para>
</section>
</chapter>

View file

@ -69,7 +69,16 @@ public enum EventType {
IMPERSONATE(true),
CUSTOM_REQUIRED_ACTION(true),
CUSTOM_REQUIRED_ACTION_ERROR(true),
EXECUTE_ACTIONS(true);
EXECUTE_ACTIONS(true),
CLIENT_INFO(false),
CLIENT_INFO_ERROR(false),
CLIENT_REGISTER(true),
CLIENT_REGISTER_ERROR(true),
CLIENT_UPDATE(true),
CLIENT_UPDATE_ERROR(true),
CLIENT_DELETE(true),
CLIENT_DELETE_ERROR(true);
private boolean saveByDefault;

View file

@ -12,6 +12,6 @@ Open the Keycloak admin console, click on Add Realm, click on 'Choose a JSON fil
Deploy the JS Console to Keycloak by running:
mvn install jboss-as:deploy
mvn install wildfly:deploy
Open the console at http://localhost:8080/js-console and login with username: 'user', and password: 'password'.

View file

@ -7,6 +7,7 @@
<div>
<button onclick="keycloak.login()">Login</button>
<button onclick="keycloak.logout()">Logout</button>
<button onclick="keycloak.register()">Register</button>
<button onclick="refreshToken(9999)">Refresh Token</button>
<button onclick="refreshToken(30)">Refresh Token (if <30s validity)</button>
<button onclick="loadProfile()">Get Profile</button>
@ -18,6 +19,7 @@
<button onclick="output(keycloak)">Show Details</button>
<button onclick="output(keycloak.createLoginUrl())">Show Login URL</button>
<button onclick="output(keycloak.createLogoutUrl())">Show Logout URL</button>
<button onclick="output(keycloak.createRegisterUrl())">Show Register URL</button>
</div>
<h2>Result</h2>

View file

@ -13,9 +13,9 @@
</Key>
</Keys>
<PrincipalNameMapping policy="FROM_NAME_ID"/>
<RoleMapping>
<RoleIdentifiers>
<Attribute name="Role"/>
</RoleMapping>
</RoleIdentifiers>
<IDP entityID="idp">
<SingleSignOnService signRequest="true"
validateResponseSignature="true"

View file

@ -13,9 +13,9 @@
</Key>
</Keys>
<PrincipalNameMapping policy="FROM_NAME_ID"/>
<RoleMapping>
<RoleIdentifiers>
<Attribute name="Role"/>
</RoleMapping>
</RoleIdentifiers>
<IDP entityID="idp">
<SingleSignOnService signRequest="true"
validateResponseSignature="true"

View file

@ -13,9 +13,9 @@
</Key>
</Keys>
<PrincipalNameMapping policy="FROM_NAME_ID"/>
<RoleMapping>
<RoleIdentifiers>
<Attribute name="Role"/>
</RoleMapping>
</RoleIdentifiers>
<IDP entityID="idp">
<SingleSignOnService signRequest="true"
validateResponseSignature="true"

View file

@ -47,6 +47,8 @@ public class LDAPQuery {
private final List<UserFederationMapperModel> mappers = new ArrayList<UserFederationMapperModel>();
private int searchScope = SearchControls.SUBTREE_SCOPE;
private String ldapFilter = null;
public LDAPQuery(LDAPFederationProvider ldapProvider) {
this.ldapFedProvider = ldapProvider;
@ -189,4 +191,12 @@ public class LDAPQuery {
return this.conditions;
}
public String getLdapFilter() {
return ldapFilter;
}
public void setLdapFilter(String ldapFilter) {
this.ldapFilter = ldapFilter;
}
}

View file

@ -255,7 +255,9 @@ public class LDAPIdentityStore implements IdentityStore {
for (Condition condition : identityQuery.getConditions()) {
applyCondition(filter, condition);
}
if (!(identityQuery.getLdapFilter() == null || identityQuery.getLdapFilter().isEmpty())) {
filter.append(identityQuery.getLdapFilter());
}
filter.insert(0, "(&");
filter.append(getObjectClassesFilter(identityQuery.getObjectClasses()));

View file

@ -54,6 +54,9 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
// See docs for Mode enum
public static final String MODE = "mode";
// Customized LDAP filter which is added to the whole LDAP query
public static final String ROLES_LDAP_FILTER = "roles.ldap.filter";
// List of IDs of UserFederationMapperModels where syncRolesFromLDAP was already called in this KeycloakSession. This is to improve performance
@ -128,6 +131,7 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
ldapQuery.addObjectClasses(roleObjectClasses);
String rolesRdnAttr = getRoleNameLdapAttribute(mapperModel);
ldapQuery.setLdapFilter(mapperModel.getConfig().get(RoleLDAPFederationMapper.ROLES_LDAP_FILTER));
String membershipAttr = getMembershipLdapAttribute(mapperModel);
ldapQuery.addReturningLdapAttribute(rolesRdnAttr);
ldapQuery.addReturningLdapAttribute(membershipAttr);

View file

@ -51,6 +51,12 @@ public class RoleLDAPFederationMapperFactory extends AbstractLDAPFederationMappe
"Object class (or classes) of the role object. It's divided by comma if more classes needed. In typical LDAP deployment it could be 'groupOfNames' . In Active Directory it's usually 'group' ",
ProviderConfigProperty.STRING_TYPE, null);
configProperties.add(roleObjectClasses);
ProviderConfigProperty ldapFilter = createConfigProperty(RoleLDAPFederationMapper.ROLES_LDAP_FILTER,
"LDAP Filter",
"LDAP Filter adds additional custom filter to the whole query.",
ProviderConfigProperty.STRING_TYPE, null);
configProperties.add(ldapFilter);
List<String> modes = new LinkedList<String>();
for (RoleLDAPFederationMapper.Mode mode : RoleLDAPFederationMapper.Mode.values()) {

View file

@ -6,7 +6,13 @@ cancel=de Cancel
onText=AN
offText=AUS
client=de Client
clients=de Clients
clear=de Clear
selectOne=de Select One...
true=de True
false=de False
# Realm settings
realm-detail.enabled.tooltip=de Users and clients can only access a realm if it's enabled
@ -111,6 +117,346 @@ active-sessions=de Active Sessions
sessions=de Sessions
not-before=de Not Before
not-before.tooltip=de Revoke any tokens issued before this date.
set-to-now=de Set To Now
set-to-now=de Set to now
push=de Push
push.tooltip=de For every client that has an admin URL, notify them of the new revocation policy.
#Protocol Mapper
usermodel.prop.label=de Property
usermodel.prop.tooltip=de Name of the property method in the UserModel interface. For example, a value of 'email' would reference the UserModel.getEmail() method.
usermodel.attr.label=de User Attribute
usermodel.attr.tooltip=de Name of stored user attribute which is the name of an attribute within the UserModel.attribute map.
userSession.modelNote.label=de User Session Note
userSession.modelNote.tooltip=de Name of stored user session note within the UserSessionModel.note map.
multivalued.label=de Multivalued
multivalued.tooltip=de Indicates if attribute supports multiple values. If true, then the list of all values of this attribute will be set as claim. If false, then just first value will be set as claim
selectRole.label=de Select Role
selectRole.tooltip=de Enter role in the textbox to the left, or click this button to browse and select the role you want
tokenClaimName.label=de Token Claim Name
tokenClaimName.tooltip=de Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.
jsonType.label=de Claim JSON Type
jsonType.tooltip=de JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.
includeInIdToken.label=de Add to ID token
includeInIdTokenTooltip.Should the claim be added to the ID token?
includeInAccessToken.label=de Add to access token
includeInAccessToken.tooltip=de Should the claim be added to the access token?
# client details
clients.tooltip=de Clients are trusted browser apps and web services in a realm. These clients can request a login. You can also define client specific roles.
search.placeholder=de Search...
create=de Create
import=de Import
client-id=de Client ID
base-url=de Base URL
actions=de Actions
not-defined=de Not defined
edit=de Edit
delete=de Delete
no-results=de No results
no-clients-available=de No clients available
add-client=de Add Client
select-file=de Select file
view-details=de View details
clear-import=de Clear import
client-id.tooltip=de Specifies ID referenced in URI and tokens. For example 'my-client'
client.name.tooltip=de Specifies display name of the client. For example 'My Client'. Supports keys for localized values as well. For example: ${my_client}
client.enabled.tooltip=de Disabled clients cannot initiate a login or have obtain access tokens.
consent-required=de Consent Required
consent-required.tooltip=de If enabled users have to consent to client access.
direct-grants-only=de Direct Grants Only
direct-grants-only.tooltip=de When enabled, client can only obtain grants from grant REST API.
client-protocol=de Client Protocol
client-protocol.tooltip=de 'OpenID connect' allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server.'SAML' enables web-based authentication and authorization scenarios including cross-domain single sign-on (SSO) and uses security tokens containing assertions to pass information.
access-type=de Access Type
access-type.tooltip=de 'Confidential' clients require a secret to initiate login protocol. 'Public' clients do not require a secret. 'Bearer-only' clients are web services that never initiate a login.
service-accounts-enabled=de Service Accounts Enabled
service-accounts-enabled.tooltip=de Allows you to authenticate this client to Keycloak and retrieve access token dedicated to this client.
include-authnstatement=de Include AuthnStatement
include-authnstatement.tooltip=de Should a statement specifying the method and timestamp be included in login responses?
sign-documents=de Sign Documents
sign-documents.tooltip=de Should SAML documents be signed by the realm?
sign-assertions=de Sign Assertions
sign-assertions.tooltip=de Should assertions inside SAML documents be signed? This setting isn't needed if document is already being signed.
signature-algorithm=de Signature Algorithm
signature-algorithm.tooltip=de The signature algorithm to use to sign documents.
canonicalization-method=de Canonicalization Method
canonicalization-method.tooltip=de Canonicalization Method for XML signatures.
encrypt-assertions=de Encrypt Assertions
encrypt-assertions.tooltip=de Should SAML assertions be encrypted with client's public key using AES?
client-signature-required=de Client Signature Required
client-signature-required.tooltip=de Will the client sign their saml requests and responses? And should they be validated?
force-post-binding=de Force POST Binding
force-post-binding.tooltip=de Always use POST binding for responses.
front-channel-logout=de Front Channel Logout
front-channel-logout.tooltip=de When true, logout requires a browser redirect to client. When false, server performs a background invocation for logout.
force-name-id-format=de Force Name ID Format
force-name-id-format.tooltip=de Ignore requested NameID subject format and use admin console configured one.
name-id-format=de Name ID Format
name-id-format.tooltip=de The name ID format to use for the subject.
root-url=de Root URL
root-url.tooltip=de Root URL appended to relative URLs
valid-redirect-uris=de Valid Redirect URIs
valid-redirect-uris.tooltip=de Valid URI pattern a browser can redirect to after a successful login or logout. Simple wildcards are allowed i.e. 'http://example.com/*'. Relative path can be specified too i.e. /my/relative/path/*. Relative paths will generate a redirect URI using the request's host and port. For SAML, you must set valid URI patterns if you are relying on the consumer service URL embedded with the login request.
base-url.tooltip=de Default URL to use when the auth server needs to redirect or link back to the client.
admin-url=de Admin URL
admin-url.tooltip=de URL to the admin interface of the client. Set this if the client supports the adapter REST API. This REST API allows the auth server to push revocation policies and other adminstrative tasks. Usually this is set to the base URL of the client.
master-saml-processing-url=de Master SAML Processing URL
master-saml-processing-url.tooltip=de If configured, this URL will be used for every binding to both the SP's Assertion Consumer and Single Logout Services. This can be individually overiden for each binding and service in the Fine Grain SAML Endpoint Configuration.
idp-sso-url-ref=de IDP Initiated SSO URL Name
idp-sso-url-ref.tooltip=de URL fragment name to reference client when you want to do IDP Initiated SSO. Leaving this empty will disable IDP Initiated SSO. The URL you will reference from your browser will be: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}
idp-sso-relay-state=de IDP Initiated SSO Relay State
idp-sso-relay-state.tooltip=de Relay state you want to send with SAML request when you want to do IDP Initiated SSO.
web-origins=de Web Origins
web-origins.tooltip=de Allowed CORS origins. To permit all origins of Valid Redirect URIs add '+'. To permit all origins add '*'.
fine-saml-endpoint-conf=de Fine Grain SAML Endpoint Configuration
fine-saml-endpoint-conf.tooltip=de Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service.
assertion-consumer-post-binding-url=de Assertion Consumer Service POST Binding URL
assertion-consumer-post-binding-url.tooltip=de SAML POST Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.
assertion-consumer-redirect-binding-url=de Assertion Consumer Service Redirect Binding URL
assertion-consumer-redirect-binding-url.tooltip=de SAML Redirect Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.
logout-service-binding-post-url=de Logout Service POST Binding URL
logout-service-binding-post-url.tooltip=de SAML POST Binding URL for the client's single logout service. You can leave this blank if you are using a different binding
logout-service-redir-binding-url=de Logout Service Redirect Binding URL
logout-service-redir-binding-url.tooltip=de SAML Redirect Binding URL for the client's single logout service. You can leave this blank if you are using a different binding.
# client import
import-client=de Import Client
format-option=de Format Option
select-format=de Select a Format
import-file=de Import File
# client tabs
settings=de Settings
credentials=de Credentials
saml-keys=de SAML Keys
roles=de Roles
mappers=de Mappers
mappers.tootip=de Protocol mappers perform transformation on tokens and documents. They an do things like map user data into protocol claims, or just transform any requests going between the client and auth server.
scope=de Scope
scope.tooltip=de Scope mappings allow you to restrict which user role mappings are included within the access token requested by the client.
sessions.tooltip=de View active sessions for this client. Allows you to see which users are active and when they logged in.
offline-access=de Offline Access
offline-access.tooltip=de View offline sessions for this client. Allows you to see which users retrieve offline token and when they retrieve it. To revoke all tokens for the client, go to Revocation tab and set not before value to now.
clustering=de Clustering
installation=de Installation
installation.tooltip=de Helper utility for generating various client adapter configuration formats which you can download or cut and paste to configure your clients.
service-account-roles=de Service Account Roles
service-account-roles.tooltip=de Allows you to authenticate role mappings for the service account dedicated to this client.
# client credentials
client-authenticator=de Client Authenticator
client-authenticator.tooltip=de Client Authenticator used for authentication this client against Keycloak server
certificate.tooltip=de Client Certificate for validate JWT issued by client and signed by Client private key from your keystore.
no-client-certificate-configured=de No client certificate configured
gen-new-keys-and-cert=de Generate new keys and certificate
import-certificate=de Import Certificate
gen-client-private-key=de Generate Client Private Key
generate-private-key=de Generate Private Key
archive-format=de Archive Format
archive-format.tooltip=de Java keystore or PKCS12 archive format.
key-alias=de Key Alias
key-alias.tooltip=de Archive alias for your private key and certificate.
key-password=de Key Password
key-password.tooltip=de Password to access the private key in the archive
store-password=de Store Password
store-password.tooltip=de Password to access the archive itself
generate-and-download=de Generate and Download
client-certificate-import=de Client Certificate Import
import-client-certificate=de Import Client Certificate
jwt-import.key-alias.tooltip=de Archive alias for your certificate.
secret=de Secret
regenerate-secret=de Regenerate Secret
add-role=de Add Role
role-name=de Role Name
composite=de Composite
description=de Description
no-client-roles-available=de No client roles available
scope-param-required=de Scope Param Required
scope-param-required.tooltip=de This role will only be granted if scope parameter with role name is used during authorization/token request.
composite-roles=de Composite Roles
composite-roles.tooltip=de When this role is (un)assigned to a user any role associated with it will be (un)assigned implicitly.
realm-roles=de Realm Roles
available-roles=de Available Roles
add-selected=de Add selected
associated-roles=de Associated Roles
composite.associated-realm-roles.tooltip=de Realm level roles associated with this composite role.
composite.available-realm-roles.tooltip=de Realm level roles associated with this composite role.
remove-selected=de Remove selected
client-roles=de Client Roles
select-client-to-view-roles=de Select client to view roles for client
available-roles.tooltip=de Roles from this client that you can associate to this composite role.
client.associated-roles.tooltip=de Client roles associated with this composite role.
add-builtin=de Add Builtin
category=de Category
type=de Type
no-mappers-available=de No mappers available
add-builtin-protocol-mappers=de Add Builtin Protocol Mappers
add-builtin-protocol-mapper=de Add Builtin Protocol Mapper
scope-mappings=de Scope Mappings
full-scope-allowed=de Full Scope Allowed
full-scope-allowed.tooltip=de Allows you to disable all restrictions.
scope.available-roles.tooltip=de Realm level roles that can be assigned to scope.
assigned-roles=de Assigned Roles
assigned-roles.tooltip=de Realm level roles assigned to scope.
effective-roles=de Effective Roles
realm.effective-roles.tooltip=de Assigned realm level roles that may have been inherited from a composite role.
select-client-roles.tooltip=de Select client to view roles for client
assign.available-roles.tooltip=de Client roles available to be assigned.
client.assigned-roles.tooltip=de Assigned client roles.
client.effective-roles.tooltip=de Assigned client roles that may have been inherited from a composite role.
basic-configuration=de Basic configuration
node-reregistration-timeout=de Node Re-registration Timeout
node-reregistration-timeout.tooltip=de Interval to specify max time for registered clients cluster nodes to re-register. If cluster node won't send re-registration request to Keycloak within this time, it will be unregistered from Keycloak
registered-cluster-nodes=de Registered cluster nodes
register-node-manually=de Register node manually
test-cluster-availability=de Test cluster availability
last-registration=de Last registration
node-host=de Node host
no-registered-cluster-nodes=de No registered cluster nodes available
cluster-nodes=de Cluster Nodes
add-node=de Add Node
active-sessions.tooltip=de Total number of active user sessions for this client.
show-sessions=de Show Sessions
show-sessions.tooltip=de Warning, this is a potentially expensive operation depending on number of active sessions.
user=de User
from-ip=de From IP
session-start=de Session Start
first-page=de First Page
previous-page=de Previous Page
next-page=de Next Page
client-revoke.not-before.tooltip=de Revoke any tokens issued before this date for this client.
client-revoke.push.tooltip=de If admin URL is configured for this client, push this policy to that client.
select-a-format=de Select a Format
download=de Download
offline-tokens=de Offline Tokens
offline-tokens.tooltip=de Total number of offline tokens for this client.
show-offline-tokens=de Show Offline Tokens
show-offline-tokens.tooltip=de Warning, this is a potentially expensive operation depending on number of offline tokens.
token-issued=de Token Issued
key-export=de Key Export
key-import=de Key Import
export-saml-key=de Export SAML Key
import-saml-key=de Import SAML Key
realm-certificate-alias=de Realm Certificate Alias
realm-certificate-alias.tooltip=de Realm certificate is stored in archive too. This is the alias to it.
signing-key=de Signing Key
saml-signing-key=de SAML Signing Key.
private-key=de Private Key
generate-new-keys=de Generate new keys
export=de Export
encryption-key=de Encryption Key
saml-encryption-key.tooltip=de SAML Encryption Key.
service-accounts=de Service Accounts
service-account.available-roles.tooltip=de Realm level roles that can be assigned to service account.
service-account.assigned-roles.tooltip=de Realm level roles assigned to service account.
service-account-is-not-enabled-for=de Service account is not enabled for {{client}}
create-protocol-mappers=de Create Protocol Mappers
create-protocol-mapper=de Create Protocol Mapper
protocol=de Protocol
protocol.tooltip=de Protocol.
id=de ID
mapper.name.tooltip=de Name of the mapper.
mapper.consent-required.tooltip=de When granting temporary access, must the user consent to providing this data to the client?
consent-text=de Consent Text
consent-text.tooltip=de Text to display on consent page.
mapper-type=de Mapper Type
select-role=de Select role
select-role.tooltip=de Enter role in the textbox to the left, or click this button to browse and select the role you want.
# realm identity providers
identity-providers=de Identity Providers
table-of-identity-providers=de Table of identity providers
add-provider.placeholder=de Add provider...
provider=de Provider
gui-order=de GUI order
redirect-uri=de Redirect URI
redirect-uri.tooltip=de The redirect uri to use when configuring the identity provider.
alias=de Alias
identity-provider.alias.tooltip=de The alias uniquely identifies an identity provider and it is also used to build the redirect uri.
identity-provider.enabled.tooltip=de Enable/disable this identity provider.
authenticate-by-default=de Authenticate by Default
identity-provider.authenticate-by-default.tooltip=de Indicates if this provider should be tried by default for authentication even before displaying login screen.
store-tokens=de Store Tokens
identity-provider.store-tokens.tooltip=de Enable/disable if tokens must be stored after authenticating users.
stored-tokens-readable=de Stored Tokens Readable
identity-provider.stored-tokens-readable.tooltip=de Enable/disable if new users can read any stored tokens. This assigns the broker.read-token role.
update-profile-on-first-login=de Update Profile on First Login
on=de On
on-missing-info=de On missing info
off=de Off
update-profile-on-first-login.tooltip=de Define conditions under which a user has to update their profile during first-time login.
trust-email=de Trust Email
trust-email.tooltip=de If enabled then email provided by this provider is not verified even if verification is enabled for the realm.
gui-order.tooltip=de Number defining order of the provider in GUI (eg. on Login page).
openid-connect-config=de OpenID Connect Config
openid-connect-config.tooltip=de OIDC SP and external IDP configuration.
authorization-url=de Authorization URL
authorization-url.tooltip=de The Authorization Url.
token-url=de Token URL
token-url.tooltip=de The Token URL.
logout-url=de Logout URL
identity-provider.logout-url.tooltip=de End session endpoint to use to logout user from external IDP.
backchannel-logout=de Backchannel Logout
backchannel-logout.tooltip=de Does the external IDP support backchannel logout?
user-info-url=de User Info URL
user-info-url.tooltip=de The User Info Url. This is optional.
identity-provider.client-id.tooltip=de The client or client identifier registered within the identity provider.
client-secret=de Client Secret
show-secret=de Show secret
hide-secret=de Hide secret
client-secret.tooltip=de The client or client secret registered within the identity provider.
issuer=de Issuer
issuer.tooltip=de The issuer identifier for the issuer of the response. If not provided, no validation will be performed.
default-scopes=de Default Scopes
identity-provider.default-scopes.tooltip=de The scopes to be sent when asking for authorization. It can be a space-separated list of scopes. Defaults to 'openid'.
prompt=de Prompt
unspecified.option=de unspecified
none.option=de none
consent.option=de consent
login.option=de login
select-account.option=de select_account
prompt.tooltip=de Specifies whether the Authorization Server prompts the End-User for reauthentication and consent.
validate-signatures=de Validate Signatures
identity-provider.validate-signatures.tooltip=de Enable/disable signature validation of external IDP signatures.
validating-public-key=de Validating Public Key
identity-provider.validating-public-key.tooltip=de The public key in PEM format that must be used to verify external IDP signatures.
import-external-idp-config=de Import External IDP Config
import-external-idp-config.tooltip=de Allows you to load external IDP metadata from a config file or to download it from a URL.
import-from-url=de Import from URL
identity-provider.import-from-url.tooltip=de Import metadata from a remote IDP discovery descriptor.
import-from-file=de Import from file
identity-provider.import-from-file.tooltip=de Import metadata from a downloaded IDP discovery descriptor.
saml-config=de SAML Config
identity-provider.saml-config.tooltip=de SAML SP and external IDP configuration.
single-signon-service-url=de Single Sign-On Service URL
saml.single-signon-service-url.tooltip=de The Url that must be used to send authentication requests (SAML AuthnRequest).
single-logout-service-url=de Single Logout Service URL
saml.single-logout-service-url.tooltip=de The Url that must be used to send logout requests.
nameid-policy-format=de NameID Policy Format
nameid-policy-format.tooltip=de Specifies the URI reference corresponding to a name identifier format. Defaults to urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
http-post-binding-response=de HTTP-POST Binding Response
http-post-binding-response.tooltip=de Indicates whether to respond to requests using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.
http-post-binding-for-authn-request=de HTTP-POST Binding for AuthnRequest
http-post-binding-for-authn-request.tooltip=de Indicates whether the AuthnRequest must be sent using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.
want-authn-requests-signed=de Want AuthnRequests Signed
want-authn-requests-signed.tooltip=de Indicates whether the identity provider expects signed a AuthnRequest.
force-authentication=de Force Authentication
identity-provider.force-authentication.tooltip=de Indicates whether the identity provider must authenticate the presenter directly rather than rely on a previous security context.
validate-signature=de Validate Signature
saml.validate-signature.tooltip=de Enable/disable signature validation of SAML responses.
validating-x509-certificate=de Validating X509 Certificate
validating-x509-certificate.tooltip=de The certificate in PEM format that must be used to check for signatures.
saml.import-from-url.tooltip=de Import metadata from a remote IDP SAML entity descriptor.
social.client-id.tooltip=de The client identifier registered with the identity provider.
social.client-secret.tooltip=de The client secret registered with the identity provider.
social.default-scopes.tooltip=de The scopes to be sent when asking for authorization. See documentation for possible values, separator and default value'.
key=de Key
stackoverflow.key.tooltip=de The Key obtained from Stack Overflow client registration.
realms=de Realms
realm=de Realm
identity-provider-mappers=de Identity Provider Mappers
create-identity-provider-mapper=de Create Identity Provider Mapper
add-identity-provider-mapper=de Add Identity Provider Mapper

View file

@ -6,7 +6,13 @@ cancel=Cancel
onText=ON
offText=OFF
client=Client
clients=Clients
clear=Clear
selectOne=Select One...
true=True
false=False
# Realm settings
realm-detail.enabled.tooltip=Users and clients can only access a realm if it's enabled
@ -111,6 +117,344 @@ active-sessions=Active Sessions
sessions=Sessions
not-before=Not Before
not-before.tooltip=Revoke any tokens issued before this date.
set-to-now=Set To Now
set-to-now=Set to now
push=Push
push.tooltip=For every client that has an admin URL, notify them of the new revocation policy.
#Protocol Mapper
usermodel.prop.label=Property
usermodel.prop.tooltip=Name of the property method in the UserModel interface. For example, a value of 'email' would reference the UserModel.getEmail() method.
usermodel.attr.label=User Attribute
usermodel.attr.tooltip=Name of stored user attribute which is the name of an attribute within the UserModel.attribute map.
userSession.modelNote.label=User Session Note
userSession.modelNote.tooltip=Name of stored user session note within the UserSessionModel.note map.
multivalued.label=Multivalued
multivalued.tooltip=Indicates if attribute supports multiple values. If true, then the list of all values of this attribute will be set as claim. If false, then just first value will be set as claim
selectRole.label=Select Role
selectRole.tooltip=Enter role in the textbox to the left, or click this button to browse and select the role you want.
tokenClaimName.label=Token Claim Name
tokenClaimName.tooltip=Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.
jsonType.label=Claim JSON Type
jsonType.tooltip=JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.
includeInIdToken.label=Add to ID token
includeInIdTokenTooltip.Should the claim be added to the ID token?
includeInAccessToken.label=Add to access token
includeInAccessToken.tooltip=Should the claim be added to the access token?
# client details
clients.tooltip=Clients are trusted browser apps and web services in a realm. These clients can request a login. You can also define client specific roles.
search.placeholder=Search...
create=Create
import=Import
client-id=Client ID
base-url=Base URL
actions=Actions
not-defined=Not defined
edit=Edit
delete=Delete
no-results=No results
no-clients-available=No clients available
add-client=Add Client
select-file=Select file
view-details=View details
clear-import=Clear import
client-id.tooltip=Specifies ID referenced in URI and tokens. For example 'my-client'
client.name.tooltip=Specifies display name of the client. For example 'My Client'. Supports keys for localized values as well. For example: ${my_client}
client.enabled.tooltip=Disabled clients cannot initiate a login or have obtain access tokens.
consent-required=Consent Required
consent-required.tooltip=If enabled users have to consent to client access.
direct-grants-only=Direct Grants Only
direct-grants-only.tooltip=When enabled, client can only obtain grants from grant REST API.
client-protocol=Client Protocol
client-protocol.tooltip='OpenID connect' allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server.'SAML' enables web-based authentication and authorization scenarios including cross-domain single sign-on (SSO) and uses security tokens containing assertions to pass information.
access-type=Access Type
access-type.tooltip='Confidential' clients require a secret to initiate login protocol. 'Public' clients do not require a secret. 'Bearer-only' clients are web services that never initiate a login.
service-accounts-enabled=Service Accounts Enabled
service-accounts-enabled.tooltip=Allows you to authenticate this client to Keycloak and retrieve access token dedicated to this client.
include-authnstatement=Include AuthnStatement
include-authnstatement.tooltip=Should a statement specifying the method and timestamp be included in login responses?
sign-documents=Sign Documents
sign-documents.tooltip=Should SAML documents be signed by the realm?
sign-assertions=Sign Assertions
sign-assertions.tooltip=Should assertions inside SAML documents be signed? This setting isn't needed if document is already being signed.
signature-algorithm=Signature Algorithm
signature-algorithm.tooltip=The signature algorithm to use to sign documents.
canonicalization-method=Canonicalization Method
canonicalization-method.tooltip=Canonicalization Method for XML signatures.
encrypt-assertions=Encrypt Assertions
encrypt-assertions.tooltip=Should SAML assertions be encrypted with client's public key using AES?
client-signature-required=Client Signature Required
client-signature-required.tooltip=Will the client sign their saml requests and responses? And should they be validated?
force-post-binding=Force POST Binding
force-post-binding.tooltip=Always use POST binding for responses.
front-channel-logout=Front Channel Logout
front-channel-logout.tooltip=When true, logout requires a browser redirect to client. When false, server performs a background invocation for logout.
force-name-id-format=Force Name ID Format
force-name-id-format.tooltip=Ignore requested NameID subject format and use admin console configured one.
name-id-format=Name ID Format
name-id-format.tooltip=The name ID format to use for the subject.
root-url=Root URL
root-url.tooltip=Root URL appended to relative URLs
valid-redirect-uris=Valid Redirect URIs
valid-redirect-uris.tooltip=Valid URI pattern a browser can redirect to after a successful login or logout. Simple wildcards are allowed i.e. 'http://example.com/*'. Relative path can be specified too i.e. /my/relative/path/*. Relative paths will generate a redirect URI using the request's host and port. For SAML, you must set valid URI patterns if you are relying on the consumer service URL embedded with the login request.
base-url.tooltip=Default URL to use when the auth server needs to redirect or link back to the client.
admin-url=Admin URL
admin-url.tooltip=URL to the admin interface of the client. Set this if the client supports the adapter REST API. This REST API allows the auth server to push revocation policies and other adminstrative tasks. Usually this is set to the base URL of the client.
master-saml-processing-url=Master SAML Processing URL
master-saml-processing-url.tooltip=If configured, this URL will be used for every binding to both the SP's Assertion Consumer and Single Logout Services. This can be individually overiden for each binding and service in the Fine Grain SAML Endpoint Configuration.
idp-sso-url-ref=IDP Initiated SSO URL Name
idp-sso-url-ref.tooltip=URL fragment name to reference client when you want to do IDP Initiated SSO. Leaving this empty will disable IDP Initiated SSO. The URL you will reference from your browser will be: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}
idp-sso-relay-state=IDP Initiated SSO Relay State
idp-sso-relay-state.tooltip=Relay state you want to send with SAML request when you want to do IDP Initiated SSO.
web-origins=Web Origins
web-origins.tooltip=Allowed CORS origins. To permit all origins of Valid Redirect URIs add '+'. To permit all origins add '*'.
fine-saml-endpoint-conf=Fine Grain SAML Endpoint Configuration
fine-saml-endpoint-conf.tooltip=Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service.
assertion-consumer-post-binding-url=Assertion Consumer Service POST Binding URL
assertion-consumer-post-binding-url.tooltip=SAML POST Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.
assertion-consumer-redirect-binding-url=Assertion Consumer Service Redirect Binding URL
assertion-consumer-redirect-binding-url.tooltip=SAML Redirect Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.
logout-service-binding-post-url=Logout Service POST Binding URL
logout-service-binding-post-url.tooltip=SAML POST Binding URL for the client's single logout service. You can leave this blank if you are using a different binding
logout-service-redir-binding-url=Logout Service Redirect Binding URL
logout-service-redir-binding-url.tooltip=SAML Redirect Binding URL for the client's single logout service. You can leave this blank if you are using a different binding.
# client import
import-client=Import Client
format-option=Format Option
select-format=Select a Format
import-file=Import File
# client tabs
settings=Settings
credentials=Credentials
saml-keys=SAML Keys
roles=Roles
mappers=Mappers
mappers.tootip=Protocol mappers perform transformation on tokens and documents. They an do things like map user data into protocol claims, or just transform any requests going between the client and auth server.
scope=Scope
scope.tooltip=Scope mappings allow you to restrict which user role mappings are included within the access token requested by the client.
sessions.tooltip=View active sessions for this client. Allows you to see which users are active and when they logged in.
offline-access=Offline Access
offline-access.tooltip=View offline sessions for this client. Allows you to see which users retrieve offline token and when they retrieve it. To revoke all tokens for the client, go to Revocation tab and set not before value to now.
clustering=Clustering
installation=Installation
installation.tooltip=Helper utility for generating various client adapter configuration formats which you can download or cut and paste to configure your clients.
service-account-roles=Service Account Roles
service-account-roles.tooltip=Allows you to authenticate role mappings for the service account dedicated to this client.
# client credentials
client-authenticator=Client Authenticator
client-authenticator.tooltip=Client Authenticator used for authentication this client against Keycloak server
certificate.tooltip=Client Certificate for validate JWT issued by client and signed by Client private key from your keystore.
no-client-certificate-configured=No client certificate configured
gen-new-keys-and-cert=Generate new keys and certificate
import-certificate=Import Certificate
gen-client-private-key=Generate Client Private Key
generate-private-key=Generate Private Key
archive-format=Archive Format
archive-format.tooltip=Java keystore or PKCS12 archive format.
key-alias=Key Alias
key-alias.tooltip=Archive alias for your private key and certificate.
key-password=Key Password
key-password.tooltip=Password to access the private key in the archive
store-password=Store Password
store-password.tooltip=Password to access the archive itself
generate-and-download=Generate and Download
client-certificate-import=Client Certificate Import
import-client-certificate=Import Client Certificate
jwt-import.key-alias.tooltip=Archive alias for your certificate.
secret=Secret
regenerate-secret=Regenerate Secret
add-role=Add Role
role-name=Role Name
composite=Composite
description=Description
no-client-roles-available=No client roles available
scope-param-required=Scope Param Required
scope-param-required.tooltip=This role will only be granted if scope parameter with role name is used during authorization/token request.
composite-roles=Composite Roles
composite-roles.tooltip=When this role is (un)assigned to a user any role associated with it will be (un)assigned implicitly.
realm-roles=Realm Roles
available-roles=Available Roles
add-selected=Add selected
associated-roles=Associated Roles
composite.associated-realm-roles.tooltip=Realm level roles associated with this composite role.
composite.available-realm-roles.tooltip=Realm level roles associated with this composite role.
remove-selected=Remove selected
client-roles=Client Roles
select-client-to-view-roles=Select client to view roles for client
available-roles.tooltip=Roles from this client that you can associate to this composite role.
client.associated-roles.tooltip=Client roles associated with this composite role.
add-builtin=Add Builtin
category=Category
type=Type
no-mappers-available=No mappers available
add-builtin-protocol-mappers=Add Builtin Protocol Mappers
add-builtin-protocol-mapper=Add Builtin Protocol Mapper
scope-mappings=Scope Mappings
full-scope-allowed=Full Scope Allowed
full-scope-allowed.tooltip=Allows you to disable all restrictions.
scope.available-roles.tooltip=Realm level roles that can be assigned to scope.
assigned-roles=Assigned Roles
assigned-roles.tooltip=Realm level roles assigned to scope.
effective-roles=Effective Roles
realm.effective-roles.tooltip=Assigned realm level roles that may have been inherited from a composite role.
select-client-roles.tooltip=Select client to view roles for client
assign.available-roles.tooltip=Client roles available to be assigned.
client.assigned-roles.tooltip=Assigned client roles.
client.effective-roles.tooltip=Assigned client roles that may have been inherited from a composite role.
basic-configuration=Basic configuration
node-reregistration-timeout=Node Re-registration Timeout
node-reregistration-timeout.tooltip=Interval to specify max time for registered clients cluster nodes to re-register. If cluster node won't send re-registration request to Keycloak within this time, it will be unregistered from Keycloak
registered-cluster-nodes=Registered cluster nodes
register-node-manually=Register node manually
test-cluster-availability=Test cluster availability
last-registration=Last registration
node-host=Node host
no-registered-cluster-nodes=No registered cluster nodes available
cluster-nodes=Cluster Nodes
add-node=Add Node
active-sessions.tooltip=Total number of active user sessions for this client.
show-sessions=Show Sessions
show-sessions.tooltip=Warning, this is a potentially expensive operation depending on number of active sessions.
user=User
from-ip=From IP
session-start=Session Start
first-page=First Page
previous-page=Previous Page
next-page=Next Page
client-revoke.not-before.tooltip=Revoke any tokens issued before this date for this client.
client-revoke.push.tooltip=If admin URL is configured for this client, push this policy to that client.
select-a-format=Select a Format
download=Download
offline-tokens=Offline Tokens
offline-tokens.tooltip=Total number of offline tokens for this client.
show-offline-tokens=Show Offline Tokens
show-offline-tokens.tooltip=Warning, this is a potentially expensive operation depending on number of offline tokens.
token-issued=Token Issued
key-export=Key Export
key-import=Key Import
export-saml-key=Export SAML Key
import-saml-key=Import SAML Key
realm-certificate-alias=Realm Certificate Alias
realm-certificate-alias.tooltip=Realm certificate is stored in archive too. This is the alias to it.
signing-key=Signing Key
saml-signing-key=SAML Signing Key.
private-key=Private Key
generate-new-keys=Generate new keys
export=Export
encryption-key=Encryption Key
saml-encryption-key.tooltip=SAML Encryption Key.
service-accounts=Service Accounts
service-account.available-roles.tooltip=Realm level roles that can be assigned to service account.
service-account.assigned-roles.tooltip=Realm level roles assigned to service account.
service-account-is-not-enabled-for=Service account is not enabled for {{client}}
create-protocol-mappers=Create Protocol Mappers
create-protocol-mapper=Create Protocol Mapper
protocol=Protocol
protocol.tooltip=Protocol.
id=ID
mapper.name.tooltip=Name of the mapper.
mapper.consent-required.tooltip=When granting temporary access, must the user consent to providing this data to the client?
consent-text=Consent Text
consent-text.tooltip=Text to display on consent page.
mapper-type=Mapper Type
# realm identity providers
identity-providers=Identity Providers
table-of-identity-providers=Table of identity providers
add-provider.placeholder=Add provider...
provider=Provider
gui-order=GUI order
redirect-uri=Redirect URI
redirect-uri.tooltip=The redirect uri to use when configuring the identity provider.
alias=Alias
identity-provider.alias.tooltip=The alias uniquely identifies an identity provider and it is also used to build the redirect uri.
identity-provider.enabled.tooltip=Enable/disable this identity provider.
authenticate-by-default=Authenticate by Default
identity-provider.authenticate-by-default.tooltip=Indicates if this provider should be tried by default for authentication even before displaying login screen.
store-tokens=Store Tokens
identity-provider.store-tokens.tooltip=Enable/disable if tokens must be stored after authenticating users.
stored-tokens-readable=Stored Tokens Readable
identity-provider.stored-tokens-readable.tooltip=Enable/disable if new users can read any stored tokens. This assigns the broker.read-token role.
update-profile-on-first-login=Update Profile on First Login
on=On
on-missing-info=On missing info
off=Off
update-profile-on-first-login.tooltip=Define conditions under which a user has to update their profile during first-time login.
trust-email=Trust Email
trust-email.tooltip=If enabled then email provided by this provider is not verified even if verification is enabled for the realm.
gui-order.tooltip=Number defining order of the provider in GUI (eg. on Login page).
openid-connect-config=OpenID Connect Config
openid-connect-config.tooltip=OIDC SP and external IDP configuration.
authorization-url=Authorization URL
authorization-url.tooltip=The Authorization Url.
token-url=Token URL
token-url.tooltip=The Token URL.
logout-url=Logout URL
identity-provider.logout-url.tooltip=End session endpoint to use to logout user from external IDP.
backchannel-logout=Backchannel Logout
backchannel-logout.tooltip=Does the external IDP support backchannel logout?
user-info-url=User Info URL
user-info-url.tooltip=The User Info Url. This is optional.
identity-provider.client-id.tooltip=The client or client identifier registered within the identity provider.
client-secret=Client Secret
show-secret=Show secret
hide-secret=Hide secret
client-secret.tooltip=The client or client secret registered within the identity provider.
issuer=Issuer
issuer.tooltip=The issuer identifier for the issuer of the response. If not provided, no validation will be performed.
default-scopes=Default Scopes
identity-provider.default-scopes.tooltip=The scopes to be sent when asking for authorization. It can be a space-separated list of scopes. Defaults to 'openid'.
prompt=Prompt
unspecified.option=unspecified
none.option=none
consent.option=consent
login.option=login
select-account.option=select_account
prompt.tooltip=Specifies whether the Authorization Server prompts the End-User for reauthentication and consent.
validate-signatures=Validate Signatures
identity-provider.validate-signatures.tooltip=Enable/disable signature validation of external IDP signatures.
validating-public-key=Validating Public Key
identity-provider.validating-public-key.tooltip=The public key in PEM format that must be used to verify external IDP signatures.
import-external-idp-config=Import External IDP Config
import-external-idp-config.tooltip=Allows you to load external IDP metadata from a config file or to download it from a URL.
import-from-url=Import from URL
identity-provider.import-from-url.tooltip=Import metadata from a remote IDP discovery descriptor.
import-from-file=Import from file
identity-provider.import-from-file.tooltip=Import metadata from a downloaded IDP discovery descriptor.
saml-config=SAML Config
identity-provider.saml-config.tooltip=SAML SP and external IDP configuration.
single-signon-service-url=Single Sign-On Service URL
saml.single-signon-service-url.tooltip=The Url that must be used to send authentication requests (SAML AuthnRequest).
single-logout-service-url=Single Logout Service URL
saml.single-logout-service-url.tooltip=The Url that must be used to send logout requests.
nameid-policy-format=NameID Policy Format
nameid-policy-format.tooltip=Specifies the URI reference corresponding to a name identifier format. Defaults to urn:oasis:names:tc:SAML:2.0:nameid-format:persistent.
http-post-binding-response=HTTP-POST Binding Response
http-post-binding-response.tooltip=Indicates whether to respond to requests using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.
http-post-binding-for-authn-request=HTTP-POST Binding for AuthnRequest
http-post-binding-for-authn-request.tooltip=Indicates whether the AuthnRequest must be sent using HTTP-POST binding. If false, HTTP-REDIRECT binding will be used.
want-authn-requests-signed=Want AuthnRequests Signed
want-authn-requests-signed.tooltip=Indicates whether the identity provider expects signed a AuthnRequest.
force-authentication=Force Authentication
identity-provider.force-authentication.tooltip=Indicates whether the identity provider must authenticate the presenter directly rather than rely on a previous security context.
validate-signature=Validate Signature
saml.validate-signature.tooltip=Enable/disable signature validation of SAML responses.
validating-x509-certificate=Validating X509 Certificate
validating-x509-certificate.tooltip=The certificate in PEM format that must be used to check for signatures.
saml.import-from-url.tooltip=Import metadata from a remote IDP SAML entity descriptor.
social.client-id.tooltip=The client identifier registered with the identity provider.
social.client-secret.tooltip=The client secret registered with the identity provider.
social.default-scopes.tooltip=The scopes to be sent when asking for authorization. See documentation for possible values, separator and default value'.
key=Key
stackoverflow.key.tooltip=The Key obtained from Stack Overflow client registration.
realms=Realms
realm=Realm
identity-provider-mappers=Identity Provider Mappers
create-identity-provider-mapper=Create Identity Provider Mapper
add-identity-provider-mapper=Add Identity Provider Mapper

View file

@ -14,16 +14,57 @@ var loadingTimer = -1;
angular.element(document).ready(function () {
var keycloakAuth = new Keycloak(configUrl);
function whoAmI(success, error) {
var req = new XMLHttpRequest();
req.open('GET', consoleBaseUrl + "/whoami", true);
req.setRequestHeader('Accept', 'application/json');
req.setRequestHeader('Authorization', 'bearer ' + keycloakAuth.token);
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status == 200) {
var data = JSON.parse(req.responseText);
success(data);
} else {
error();
}
}
}
req.send();
}
function hasAnyAccess(user) {
return user && user['realm_access'];
}
keycloakAuth.onAuthLogout = function() {
location.reload();
}
keycloakAuth.init({ onLoad: 'login-required' }).success(function () {
auth.authz = keycloakAuth;
module.factory('Auth', function() {
return auth;
auth.refreshPermissions = function(success, error) {
whoAmI(function(data) {
auth.user = data;
auth.loggedIn = true;
auth.hasAnyAccess = hasAnyAccess(data);
success();
}, function() {
error();
});
};
auth.refreshPermissions(function() {
module.factory('Auth', function() {
return auth;
});
angular.bootstrap(document, ["keycloak"]);
}, function() {
window.location.reload();
});
angular.bootstrap(document, ["keycloak"]);
}).error(function () {
window.location.reload();
});

View file

@ -1,31 +1,9 @@
module.controller('GlobalCtrl', function($scope, $http, Auth, WhoAmI, Current, $location, Notifications, ServerInfo) {
$scope.addMessage = function() {
Notifications.success("test");
};
module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location, Notifications, ServerInfo) {
$scope.authUrl = authUrl;
$scope.resourceUrl = resourceUrl;
$scope.auth = Auth;
$scope.serverInfo = ServerInfo.get();
function hasAnyAccess() {
var realmAccess = Auth.user && Auth.user['realm_access'];
if (realmAccess) {
for (var p in realmAccess){
return true;
}
return false;
} else {
return false;
}
}
WhoAmI.get(function (data) {
Auth.user = data;
Auth.loggedIn = true;
Auth.hasAnyAccess = hasAnyAccess();
});
function getAccess(role) {
if (!Current.realm) {
return false;
@ -155,7 +133,7 @@ module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $l
}
});
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, $route, Dialog, Notifications, Auth, $modal) {
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, $location, $route, Dialog, Notifications, Auth, $modal) {
console.log('RealmCreateCtrl');
Current.realm = null;
@ -193,22 +171,17 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
}, true);
$scope.$watch('realm.realm', function() {
if (create) {
$scope.realm.id = $scope.realm.realm;
}
}, true);
$scope.save = function() {
var realmCopy = angular.copy($scope.realm);
Realm.create(realmCopy, function() {
Realm.query(function(data) {
Current.realms = data;
WhoAmI.get(function(user) {
Auth.user = user;
Notifications.success("The realm has been created.");
Auth.refreshPermissions(function() {
$scope.$apply(function() {
$location.url("/realms/" + realmCopy.realm);
Notifications.success("The realm has been created.");
});
});
});
@ -227,7 +200,7 @@ module.controller('ObjectModalCtrl', function($scope, object) {
$scope.object = object;
});
module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, WhoAmI, Auth) {
module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, Auth) {
$scope.createRealm = !realm.realm;
$scope.serverInfo = serverInfo;
@ -272,11 +245,13 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, ser
});
if (nameChanged) {
WhoAmI.get(function(user) {
Auth.user = user;
$location.url("/realms/" + realmCopy.realm);
Notifications.success("Your changes have been saved to the realm.");
Auth.refreshPermissions(function() {
Auth.refreshPermissions(function() {
Notifications.success("Your changes have been saved to the realm.");
$scope.$apply(function() {
$location.url("/realms/" + realmCopy.realm);
});
});
});
} else {
$location.url("/realms/" + realmCopy.realm);

View file

@ -184,10 +184,6 @@ module.factory('Notifications', function($rootScope, $timeout) {
return notifications;
});
module.factory('WhoAmI', function($resource) {
return $resource(consoleBaseUrl + '/whoami');
});
module.factory('Realm', function($resource) {
return $resource(authUrl + '/admin/realms/:id', {
id : '@realm'

View file

@ -1,13 +1,13 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering">Cluster Nodes</a></li>
<li data-ng-show="create">Add Node</li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering">{{:: 'cluster-nodes' | translate}}</a></li>
<li data-ng-show="create">{{:: 'add-node' | translate}}</li>
<li data-ng-hide="create">{{node.host|capitalize}}</li>
</ol>
<h1 data-ng-show="create">Add Node</h1>
<h1 data-ng-show="create">{{:: 'add-node' | translate}}</h1>
<h1 data-ng-hide="create">
{{node.host|capitalize}}
<i id="removeClient" class="pficon pficon-delete clickable" data-ng-show="access.manageClients" data-ng-click="unregisterNode()"></i>
@ -21,14 +21,14 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="lastRegistration">Last Registration</label>
<label class="col-md-2 control-label" for="lastRegistration">{{:: 'last-registration' | translate}}</label>
<div class="col-sm-6">
<input ng-disabled="true" class="form-control" type="text" id="lastRegistration" name="lastRegistration" data-ng-model="node.lastRegistration">
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
<button data-kc-save data-ng-show="create">Save</button>
<button data-kc-save data-ng-show="create">{{:: 'save' | translate}}</button>
</div>
</div>
</form>

View file

@ -1,17 +1,17 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>
<kc-tabs-client></kc-tabs-client>
<form class="form-horizontal" name="clusteringForm" novalidate kc-read-only="!access.manageClients">
<legend><span class="text">Basic configuration</span></legend>
<legend><span class="text">{{:: 'basic-configuration' | translate}}</span></legend>
<fieldset >
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="nodeReRegistrationTimeout">Node Re-registration Timeout</label>
<label class="col-md-2 control-label" for="nodeReRegistrationTimeout">{{:: 'node-reregistration-timeout' | translate}}</label>
<div class="col-sm-5">
<div class="row">
<div class="col-md-6 form-inline">
@ -19,42 +19,42 @@
max="31536000" data-ng-model="client.nodeReRegistrationTimeout"
id="nodeReRegistrationTimeout" name="nodeReRegistrationTimeout"/>
<select class="form-control" name="nodeReRegistrationTimeoutUnit" data-ng-model="client.nodeReRegistrationTimeoutUnit" >
<option data-ng-selected="!client.nodeReRegistrationTimeoutUnit">Seconds</option>
<option>Minutes</option>
<option>Hours</option>
<option>Days</option>
<option data-ng-selected="!client.nodeReRegistrationTimeoutUnit">{{:: 'seconds' | translate}}</option>
<option>{{:: 'minutes' | translate}}</option>
<option>{{:: 'hours' | translate}}</option>
<option>{{:: 'days' | translate}}</option>
</select>
</div>
</div>
</div>
<kc-tooltip>Interval to specify max time for registered clients cluster nodes to re-register. If cluster node won't send re-registration request to Keycloak within this time, it will be unregistered from Keycloak</kc-tooltip>
<kc-tooltip>{{:: 'node-reregistration-timeout.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
<button data-kc-save data-ng-disabled="!changed">Save</button>
<button data-kc-reset data-ng-disabled="!changed">Cancel</button>
<button data-kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button data-kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
</div>
</fieldset>
<fieldset>
<legend><span class="text">Registered cluster nodes</span></legend>
<legend><span class="text">{{:: 'registered-cluster-nodes' | translate}}</span></legend>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th class="kc-table-actions" colspan="5" data-ng-show="access.manageClients">
<div class="pull-right">
<a class="btn btn-default" tooltip="Manually register cluster node. This is usually not needed as cluster node should be registered automatically by adapter"
tooltip-trigger="mouseover mouseout" tooltip-placement="bottom" href="#/register-node/realms/{{realm.realm}}/clients/{{client.id}}/clustering">Register node manually</a>
<a class="btn btn-default" data-ng-click="testNodesAvailable()" data-ng-show="nodeRegistrations && nodeRegistrations.length > 0">Test cluster availability</a>
tooltip-trigger="mouseover mouseout" tooltip-placement="bottom" href="#/register-node/realms/{{realm.realm}}/clients/{{client.id}}/clustering">{{:: 'register-node-manually' | translate}}</a>
<a class="btn btn-default" data-ng-click="testNodesAvailable()" data-ng-show="nodeRegistrations && nodeRegistrations.length > 0">{{:: 'test-cluster-availability' | translate}}</a>
</div>
</th>
</tr>
<tr data-ng-hide="!nodeRegistrations || nodeRegistrations.length == 0">
<th>Node host</th>
<th>Last registration</th>
<th colspan="2">Actions</th>
<th>{{:: 'node-host' | translate}}</th>
<th>{{:: 'last-registration' | translate}}</th>
<th colspan="2">{{:: 'actions' | translate}}</th>
</tr>
</thead>
<tbody>
@ -62,14 +62,14 @@
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering/{{node.host}}">{{node.host}}</a></td>
<td>{{node.lastRegistration}}</td>
<td class="kc-action-cell">
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/clustering/{{node.host}}">Edit</button>
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/clustering/{{node.host}}">{{:: 'edit' | translate}}</button>
</td>
<td class="kc-action-cell">
<button class="btn btn-default btn-block btn-sm" data-ng-click="removeNode(node)">Delete</button>
<button class="btn btn-default btn-block btn-sm" data-ng-click="removeNode(node)">{{:: 'delete' | translate}}</button>
</td>
</tr>
<tr data-ng-show="!nodeRegistrations || nodeRegistrations.length == 0">
<td class="text-muted">No registered cluster nodes available</td>
<td class="text-muted">{{:: 'no-registered-cluster-nodes' | translate}}</td>
</tr>
</tbody>
</table>

View file

@ -6,8 +6,8 @@
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
<button kc-save data-ng-disabled="!changed">Save</button>
<button kc-reset data-ng-disabled="!changed">Cancel</button>
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
</div>
</form>

View file

@ -1,18 +1,18 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/credentials">Credentials</a></li>
<li class="active">Generate Client Private Key</li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/credentials">{{:: 'credentials' | translate}}</a></li>
<li class="active">{{:: 'gen-client-private-key' | translate}}</li>
</ol>
<h1>Generate Private Key</h1>
<h1>{{:: 'generate-private-key' | translate}}</h1>
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
<fieldset class="form-group col-sm-10">
<div class="form-group">
<label class="col-md-2 control-label" for="downloadKeyFormat">Archive Format</label>
<label class="col-md-2 control-label" for="downloadKeyFormat">{{:: 'archive-format' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="downloadKeyFormat"
@ -21,33 +21,33 @@
</select>
</div>
</div>
<kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
<kc-tooltip>{{:: 'archive-format.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="keyAlias">Key Alias</label>
<label class="col-md-2 control-label" for="keyAlias">{{:: 'key-alias' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="text" id="keyAlias" name="keyAlias" data-ng-model="jks.keyAlias" autofocus required>
</div>
<kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
<kc-tooltip>{{:: 'key-alias.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="keyPassword">Key Password</label>
<label class="col-md-2 control-label" for="keyPassword">{{:: 'key-password' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="password" id="keyPassword" name="keyPassword" data-ng-model="jks.keyPassword" autofocus required>
</div>
<kc-tooltip>Password to access the private key in the archive</kc-tooltip>
<kc-tooltip>{{:: 'key-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="storePassword">Store Password</label>
<label class="col-md-2 control-label" for="storePassword">{{:: 'store-password' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="password" id="storePassword" name="storePassword" data-ng-model="jks.storePassword" autofocus required>
</div>
<kc-tooltip>Password to access the archive itself</kc-tooltip>
<kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
<button class="btn btn-primary" type="submit" data-ng-click="download()">Generate and Download</button>
<button class="btn btn-default" type="submit" data-ng-click="cancel()">Cancel</button>
<button class="btn btn-primary" type="submit" data-ng-click="download()">{{:: 'generate-and-download' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div>
</div>
</fieldset>

View file

@ -1,18 +1,18 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/credentials">Credentials</a></li>
<li class="active">Client Certificate Import</li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/credentials">{{:: 'credentials' | translate}}</a></li>
<li class="active">{{:: 'client-certificate-import' | translate}}</li>
</ol>
<h1>Import Client Certificate</h1>
<h1>{{:: 'import-client-certificate' | translate}}</h1>
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
<div class="form-group">
<label class="col-md-2 control-label" for="uploadKeyFormat">Archive Format</label>
<label class="col-md-2 control-label" for="uploadKeyFormat">{{:: 'archive-format' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="uploadKeyFormat"
@ -21,27 +21,27 @@
</select>
</div>
</div>
<kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
<kc-tooltip>{{:: 'archive-format.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="uploadKeyAlias">Key Alias</label>
<label class="col-md-2 control-label" for="uploadKeyAlias">{{:: 'key-alias' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="text" id="uploadKeyAlias" name="uploadKeyAlias" data-ng-model="uploadKeyAlias" autofocus required>
</div>
<kc-tooltip>Archive alias for your certificate.</kc-tooltip>
<kc-tooltip>{{:: 'jwt-import.key-alias.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="uploadStorePassword">Store Password</label>
<label class="col-md-2 control-label" for="uploadStorePassword">{{:: 'store-password' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="password" id="uploadStorePassword" name="uploadStorePassword" data-ng-model="uploadStorePassword" autofocus required>
</div>
<kc-tooltip>Password to access the archive itself</kc-tooltip>
<kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Import File </label>
<label class="col-md-2 control-label">{{:: 'import-file' | translate}} </label>
<div class="col-md-6">
<div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
<label for="import-file" class="btn btn-default">{{:: 'select-file' | translate}} <i class="pficon pficon-import"></i></label>
<input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
</div>
<span class="kc-uploaded-file" data-ng-show="files.length > 0">
@ -51,8 +51,8 @@
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2">
<button type="submit" data-ng-click="uploadFile()" data-ng-disabled="files.length == 0" class="btn btn-primary">Import</button>
<button type="submit" data-ng-click="cancel()" class="btn btn-default">Cancel</button>
<button type="submit" data-ng-click="uploadFile()" data-ng-disabled="files.length == 0" class="btn btn-primary">{{:: 'import' | translate}}</button>
<button type="submit" data-ng-click="cancel()" class="btn btn-default">{{:: 'cancel' | translate}}</button>
</div>
</div>
</fieldset>

View file

@ -1,20 +1,20 @@
<div>
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageClients" data-ng-controller="ClientSignedJWTCtrl">
<div class="form-group">
<label class="col-md-2 control-label" for="signingCert">Certificate</label>
<kc-tooltip>Client Certificate for validate JWT issued by client and signed by Client private key from your keystore.</kc-tooltip>
<label class="col-md-2 control-label" for="signingCert">{{:: 'certificate' | translate}}</label>
<kc-tooltip>{{:: 'certificate.tooltip' | translate}}</kc-tooltip>
<div class="col-sm-10" data-ng-show="signingKeyInfo.certificate">
<textarea type="text" id="signingCert" name="signingCert" class="form-control" rows="5" kc-select-action="click" readonly>{{signingKeyInfo.certificate}}</textarea>
</div>
<div class="col-sm-10" data-ng-hide="signingKeyInfo.certificate">
No client certificate configured
{{:: 'no-client-certificate-configured' | translate}}
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
<button class="btn btn-default" type="submit" data-ng-click="generateSigningKey()">Generate new keys and certificate</button>
<button class="btn btn-default" type="submit" data-ng-click="importCertificate()">Import certificate</button>
<button class="btn btn-default" type="submit" data-ng-click="generateSigningKey()">{{:: 'gen-new-keys-and-cert' | translate}}</button>
<button class="btn btn-default" type="submit" data-ng-click="importCertificate()">{{:: 'import-certificate' | translate}}</button>
</div>
</div>
</form>

View file

@ -1,14 +1,14 @@
<div>
<form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageClients" data-ng-controller="ClientSecretCtrl">
<div class="form-group">
<label class="col-md-2 control-label" for="secret">Secret</label>
<label class="col-md-2 control-label" for="secret">{{:: 'secret' | translate}}</label>
<div class="col-sm-6">
<div class="row">
<div class="col-sm-6">
<input readonly kc-select-action="click" class="form-control" type="text" id="secret" name="secret" data-ng-model="secret">
</div>
<div class="col-sm-6" data-ng-show="access.manageClients">
<button type="submit" data-ng-click="changePassword()" class="btn btn-default">Regenerate Secret</button>
<button type="submit" data-ng-click="changePassword()" class="btn btn-default">{{:: 'regenerate-secret' | translate}}</button>
</div>
</div>
</div>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>
@ -10,7 +10,7 @@
<form class="form-horizontal" name="clientForm" novalidate kc-read-only="!access.manageClients">
<fieldset class="border-top">
<div class="form-group clearfix">
<label class="col-md-2 control-label" for="clientAuthenticatorType"> Client Authenticator</label>
<label class="col-md-2 control-label" for="clientAuthenticatorType"> {{:: 'client-authenticator' | translate}}</label>
<div class="col-md-2">
<div>
<select class="form-control" id="clientAuthenticatorType"
@ -20,7 +20,7 @@
</select>
</div>
</div>
<kc-tooltip>Client Authenticator used for authentication this client against Keycloak server</kc-tooltip>
<kc-tooltip>{{:: 'client-authenticator.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset>
</form>

View file

@ -1,8 +1,8 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li data-ng-show="create">Add Client</li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li data-ng-show="create">{{:: 'add-client' | translate}}</li>
<li data-ng-hide="create">{{client.clientId}}</li>
</ol>
@ -11,56 +11,56 @@
<form class="form-horizontal" name="clientForm" novalidate kc-read-only="!access.manageClients">
<fieldset class="border-top">
<div class="form-group" data-ng-show="create">
<label for="name" class="col-sm-2 control-label">Import</label>
<label for="name" class="col-sm-2 control-label">{{:: 'import' | translate}}</label>
<div class="col-md-6" data-ng-hide="importing">
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
<label for="import-file" class="btn btn-default">{{:: 'select-file' | translate}} <i class="pficon pficon-import"></i></label>
<input id="import-file" type="file" class="hidden" kc-on-read-file="importFile($fileContent)">
</div>
<div class="col-md-6" data-ng-show="importing">
<button class="btn btn-default" data-ng-click="viewImportDetails()">View details</button>
<button class="btn btn-default" data-ng-click="reset()">Clear import</button>
<button class="btn btn-default" data-ng-click="viewImportDetails()">{{:: 'view-details' | translate}}</button>
<button class="btn btn-default" data-ng-click="reset()">{{:: 'clear-import' | translate}}</button>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="clientId">Client ID <span class="required" data-ng-show="create">*</span></label>
<label class="col-md-2 control-label" for="clientId">{{:: 'client-id' | translate}} <span class="required" data-ng-show="create">*</span></label>
<div class="col-sm-6">
<input class="form-control" type="text" id="clientId" name="clientId" data-ng-model="client.clientId" autofocus required>
</div>
<kc-tooltip>Specifies ID referenced in URI and tokens. For example 'my-client'</kc-tooltip>
<kc-tooltip>{{:: 'client-id.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="name">Name </label>
<label class="col-md-2 control-label" for="name">{{:: 'name' | translate}} </label>
<div class="col-sm-6">
<input class="form-control" type="text" id="name" name="name" data-ng-model="client.name" autofocus>
</div>
<kc-tooltip>Specifies display name of the client. For example 'My Client'. Supports keys for localized values as well. For example: ${my_client}</kc-tooltip>
<kc-tooltip>{{:: 'client.name.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block">
<label class="col-md-2 control-label" for="enabled">Enabled</label>
<label class="col-md-2 control-label" for="enabled">{{:: 'enabled' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.enabled" name="enabled" id="enabled" onoffswitch />
<input ng-model="client.enabled" name="enabled" id="enabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Disabled clients cannot initiate a login or have obtain access tokens.</kc-tooltip>
<kc-tooltip>{{:: 'client.enabled.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block">
<label class="col-md-2 control-label" for="consentRequired">Consent Required</label>
<label class="col-md-2 control-label" for="consentRequired">{{:: 'consent-required' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.consentRequired" name="consentRequired" id="consentRequired" onoffswitch />
<input ng-model="client.consentRequired" name="consentRequired" id="consentRequired" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>If enabled users have to consent to client access.</kc-tooltip>
<kc-tooltip>{{:: 'consent-required.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block">
<label class="col-md-2 control-label" for="directGrantsOnly">Direct Grants Only</label>
<label class="col-md-2 control-label" for="directGrantsOnly">{{:: 'direct-grants-only' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.directGrantsOnly" name="directGrantsOnly" id="directGrantsOnly" onoffswitch />
<input ng-model="client.directGrantsOnly" name="directGrantsOnly" id="directGrantsOnly" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>When enabled, client can only obtain grants from grant REST API.</kc-tooltip>
<kc-tooltip>{{:: 'direct-grants-only.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="protocol">Client Protocol</label>
<label class="col-md-2 control-label" for="protocol">{{:: 'client-protocol' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="protocol"
@ -70,11 +70,10 @@
</select>
</div>
</div>
<kc-tooltip>'OpenID connect' allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server.
'SAML' enables web-based authentication and authorization scenarios including cross-domain single sign-on (SSO) and uses security tokens containing assertions to pass information.</kc-tooltip>
<kc-tooltip>{{:: 'client-protocol.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="protocol == 'openid-connect'">
<label class="col-md-2 control-label" for="accessType">Access Type</label>
<label class="col-md-2 control-label" for="accessType">{{:: 'access-type' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="accessType"
@ -84,38 +83,38 @@
</select>
</div>
</div>
<kc-tooltip>'Confidential' clients require a secret to initiate login protocol. 'Public' clients do not require a secret. 'Bearer-only' clients are web services that never initiate a login.</kc-tooltip>
<kc-tooltip>{{:: 'access-type.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="protocol == 'openid-connect' && !client.publicClient && !client.bearerOnly">
<label class="col-md-2 control-label" for="serviceAccountsEnabled">Service Accounts Enabled</label>
<kc-tooltip>Allows you to authenticate this client to Keycloak and retrieve access token dedicated to this client.</kc-tooltip>
<label class="col-md-2 control-label" for="serviceAccountsEnabled">{{:: 'service-accounts-enabled' | translate}}</label>
<kc-tooltip>{{:: 'service-accounts-enabled.tooltip' | translate}}</kc-tooltip>
<div class="col-md-6">
<input ng-model="client.serviceAccountsEnabled" name="serviceAccountsEnabled" id="serviceAccountsEnabled" onoffswitch />
<input ng-model="client.serviceAccountsEnabled" name="serviceAccountsEnabled" id="serviceAccountsEnabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlServerSignature">Include AuthnStatement</label>
<label class="col-md-2 control-label" for="samlServerSignature">{{:: 'include-authnstatement' | translate}}</label>
<div class="col-sm-6">
<input ng-model="samlAuthnStatement" ng-click="switchChange()" name="samlAuthnStatement" id="samlAuthnStatement" onoffswitch />
<input ng-model="samlAuthnStatement" ng-click="switchChange()" name="samlAuthnStatement" id="samlAuthnStatement" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Should a statement specifying the method and timestamp be included in login responses?</kc-tooltip>
<kc-tooltip>{{:: 'include-authnstatement.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlServerSignature">Sign Documents</label>
<label class="col-md-2 control-label" for="samlServerSignature">{{:: 'sign-documents' | translate}}</label>
<div class="col-sm-6">
<input ng-model="samlServerSignature" ng-click="switchChange()" name="samlServerSignature" id="samlServerSignature" onoffswitch />
<input ng-model="samlServerSignature" ng-click="switchChange()" name="samlServerSignature" id="samlServerSignature" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Should SAML documents be signed by the realm?</kc-tooltip>
<kc-tooltip>{{:: 'sign-documents.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlAssertionSignature">Sign Assertions</label>
<label class="col-md-2 control-label" for="samlAssertionSignature">{{:: 'sign-assertions' | translate}}</label>
<div class="col-sm-6">
<input ng-model="samlAssertionSignature" ng-click="switchChange()" name="samlAssertionSignature" id="samlAssertionSignature" onoffswitch />
<input ng-model="samlAssertionSignature" ng-click="switchChange()" name="samlAssertionSignature" id="samlAssertionSignature" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Should assertions inside SAML documents be signed? This setting isn't needed if document is already being signed.</kc-tooltip>
<kc-tooltip>{{:: 'sign-assertions.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="(samlAssertionSignature || samlServerSignature) && protocol == 'saml'">
<label class="col-md-2 control-label" for="signatureAlgorithm">Signature Algorithm</label>
<label class="col-md-2 control-label" for="signatureAlgorithm">{{:: 'signature-algorithm' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="signatureAlgorithm"
@ -125,10 +124,10 @@
</select>
</div>
</div>
<kc-tooltip>The signature algorithm to use to sign documents.</kc-tooltip>
<kc-tooltip>{{:: 'signature-algorithm.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="(samlAssertionSignature || samlServerSignature) && protocol == 'saml'">
<label class="col-md-2 control-label" for="canonicalization">Canonicalization Method</label>
<label class="col-md-2 control-label" for="canonicalization">{{:: 'canonicalization-method' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="canonicalization"
@ -137,45 +136,45 @@
</select>
</div>
</div>
<kc-tooltip>Canonicalization Method for XML signatures.</kc-tooltip>
<kc-tooltip>{{:: 'canonicalization-method.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlEncrypt">Encrypt Assertions</label>
<label class="col-md-2 control-label" for="samlEncrypt">{{:: 'encrypt-assertions' | translate}}</label>
<div class="col-sm-6">
<input ng-model="samlEncrypt" ng-click="switchChange()" name="samlEncrypt" id="samlEncrypt" onoffswitch />
<input ng-model="samlEncrypt" ng-click="switchChange()" name="samlEncrypt" id="samlEncrypt" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Should SAML assertions be encrypted with client's public key using AES?</kc-tooltip>
<kc-tooltip>{{:: 'encrypt-assertions.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlClientSignature">Client Signature Required</label>
<label class="col-md-2 control-label" for="samlClientSignature">{{:: 'client-signature-required' | translate}}</label>
<div class="col-sm-6">
<input ng-model="samlClientSignature" ng-click="switchChange()" name="samlClientSignature" id="samlClientSignature" onoffswitch />
<input ng-model="samlClientSignature" ng-click="switchChange()" name="samlClientSignature" id="samlClientSignature" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Will the client sign their saml requests and responses? And should they be validated?</kc-tooltip>
<kc-tooltip>{{:: 'client-signature-required.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlForcePostBinding">Force POST Binding</label>
<label class="col-md-2 control-label" for="samlForcePostBinding">{{:: 'force-post-binding' | translate}}</label>
<div class="col-sm-6">
<input ng-model="samlForcePostBinding" ng-click="switchChange()" name="samlForcePostBinding" id="samlForcePostBinding" onoffswitch />
<input ng-model="samlForcePostBinding" ng-click="switchChange()" name="samlForcePostBinding" id="samlForcePostBinding" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Always use POST binding for responses.</kc-tooltip>
<kc-tooltip>{{:: 'force-post-binding.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="frontchannelLogout">Front Channel Logout</label>
<label class="col-md-2 control-label" for="frontchannelLogout">{{:: 'front-channel-logout' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.frontchannelLogout" name="frontchannelLogout" id="frontchannelLogout" onoffswitch />
<input ng-model="client.frontchannelLogout" name="frontchannelLogout" id="frontchannelLogout" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>When true, logout requires a browser redirect to client. When false, server performs a background invocation for logout.</kc-tooltip>
<kc-tooltip>{{:: 'front-channel-logout.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlForceNameIdFormat">Force Name ID Format</label>
<label class="col-md-2 control-label" for="samlForceNameIdFormat">{{:: 'force-name-id-format' | translate}}</label>
<div class="col-sm-6">
<input ng-model="samlForceNameIdFormat" ng-click="switchChange()" name="samlForceNameIdFormat" id="samlForceNameIdFormat" onoffswitch />
<input ng-model="samlForceNameIdFormat" ng-click="switchChange()" name="samlForceNameIdFormat" id="samlForceNameIdFormat" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}"/>
</div>
<kc-tooltip>Ignore requested NameID subject format and use admin console configured one.</kc-tooltip>
<kc-tooltip>{{:: 'force-name-id-format.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="samlNameIdFormat">Name ID Format</label>
<label class="col-md-2 control-label" for="samlNameIdFormat">{{:: 'name-id-format' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="samlNameIdFormat"
@ -185,19 +184,19 @@
</select>
</div>
</div>
<kc-tooltip>The name ID format to use for the subject.</kc-tooltip>
<kc-tooltip>{{:: 'name-id-format.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="!client.bearerOnly">
<label class="col-md-2 control-label" for="rootUrl">Root URL</label>
<label class="col-md-2 control-label" for="rootUrl">{{:: 'root-url' | translate}}</label>
<div class="col-sm-6">
<input class="form-control" type="text" name="rootUrl" id="rootUrl" data-ng-model="client.rootUrl">
</div>
<kc-tooltip>Root URL appended to relative URLs</kc-tooltip>
<kc-tooltip>{{:: 'root-url.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-hide="client.bearerOnly || client.directGrantsOnly">
<label class="col-md-2 control-label" for="newRedirectUri"><span class="required" data-ng-show="protocol != 'saml'">*</span> Valid Redirect URIs</label>
<label class="col-md-2 control-label" for="newRedirectUri"><span class="required" data-ng-show="protocol != 'saml'">*</span> {{:: 'valid-redirect-uris' | translate}}</label>
<div class="col-sm-6">
<div class="input-group" ng-repeat="(i, redirectUri) in client.redirectUris track by $index">
@ -215,48 +214,48 @@
</div>
</div>
<kc-tooltip>Valid URI pattern a browser can redirect to after a successful login or logout. Simple wildcards are allowed i.e. 'http://example.com/*'. Relative path can be specified too i.e. /my/relative/path/*. Relative paths will generate a redirect URI using the request's host and port. For SAML, you must set valid URI patterns if you are relying on the consumer service URL embedded with the login request.</kc-tooltip>
<kc-tooltip>{{:: 'valid-redirect-uris.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="!client.bearerOnly && !create">
<label class="col-md-2 control-label" for="baseUrl">Base URL</label>
<label class="col-md-2 control-label" for="baseUrl">{{:: 'base-url' | translate}}</label>
<div class="col-sm-6">
<input class="form-control" type="text" name="baseUrl" id="baseUrl" data-ng-model="client.baseUrl">
</div>
<kc-tooltip>Default URL to use when the auth server needs to redirect or link back to the client.</kc-tooltip>
<kc-tooltip>{{:: 'base-url.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-hide="create || protocol == 'saml'">
<label class="col-md-2 control-label" for="adminUrl">Admin URL</label>
<label class="col-md-2 control-label" for="adminUrl">{{:: 'admin-url' | translate}}</label>
<div class="col-sm-6">
<input class="form-control" type="text" name="adminUrl" id="adminUrl"
data-ng-model="client.adminUrl">
</div>
<kc-tooltip>URL to the admin interface of the client. Set this if the client supports the adapter REST API. This REST API allows the auth server to push revocation policies and other adminstrative tasks. Usually this is set to the base URL of the client.</kc-tooltip>
<kc-tooltip>{{:: 'admin-url.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="masterSamlUrl">Master SAML Processing URL</label>
<label class="col-md-2 control-label" for="masterSamlUrl">{{:: 'master-saml-processing-url' | translate}}</label>
<div class="col-sm-6">
<input class="form-control" type="text" name="masterSamlUrl" id="masterSamlUrl"
data-ng-model="client.adminUrl">
</div>
<kc-tooltip>If configured, this URL will be used for every binding to both the SP's Assertion Consumer and Single Logout Services. This can be individually overiden for each binding and service in the Fine Grain SAML Endpoint Configuration.</kc-tooltip>
<kc-tooltip>{{:: 'master-saml-processing-url.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="urlReferenceName">IDP Initiated SSO URL Name</label>
<label class="col-md-2 control-label" for="urlReferenceName">{{:: 'idp-sso-url-ref' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.attributes.saml_idp_initiated_sso_url_name" class="form-control" type="text" name="urlReferenceName" id="urlReferenceName" />
</div>
<kc-tooltip>URL fragment name to reference client when you want to do IDP Initiated SSO. Leaving this empty will disable IDP Initiated SSO. The URL you will reference from your browser will be: {server-root}/realms/{realm}/protocol/saml/clients/{client-url-name}</kc-tooltip>
<kc-tooltip>{{:: 'idp-sso-url-ref.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="idpInitiatedRelayState">IDP Initiated SSO Relay State</label>
<label class="col-md-2 control-label" for="idpInitiatedRelayState">{{:: 'idp-sso-relay-state' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.attributes.saml_idp_initiated_sso_relay_state" class="form-control" type="text" name="idpInitiatedRelayState" id="idpInitiatedRelayState" />
</div>
<kc-tooltip>Relay state you want to send with SAML request when you want to do IDP Initiated SSO.</kc-tooltip>
<kc-tooltip>{{:: 'idp-sso-relay-state.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-show="!client.bearerOnly && !create && protocol == 'openid-connect'">
<label class="col-md-2 control-label" for="newWebOrigin">Web Origins</label>
<label class="col-md-2 control-label" for="newWebOrigin">{{:: 'web-origins' | translate}}</label>
<div class="col-sm-6">
<div class="input-group" ng-repeat="(i, webOrigin) in client.webOrigins track by $index">
@ -274,49 +273,49 @@
</div>
</div>
<kc-tooltip>Allowed CORS origins. To permit all origins of Valid Redirect URIs add '+'. To permit all origins add '*'.</kc-tooltip>
<kc-tooltip>{{:: 'web-origins.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset>
<fieldset data-ng-show="protocol == 'saml'">
<legend collapsed><span class="text">Fine Grain SAML Endpoint Configuration</span> <kc-tooltip>Expand this section to configure exact URLs for Assertion Consumer and Single Logout Service.</kc-tooltip></legend>
<legend collapsed><span class="text">{{:: 'fine-saml-endpoint-conf' | translate}}</span> <kc-tooltip>{{:: 'fine-saml-endpoint-conf.tooltip' | translate}}</kc-tooltip></legend>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="consumerServicePost">Assertion Consumer Service POST Binding URL</label>
<label class="col-md-2 control-label" for="consumerServicePost">{{:: 'assertion-consumer-post-binding-url' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.attributes.saml_assertion_consumer_url_post" class="form-control" type="text" name="consumerServicePost" id="consumerServicePost" />
</div>
<kc-tooltip>SAML POST Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.</kc-tooltip>
<kc-tooltip>{{:: 'assertion-consumer-post-binding-url.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="consumerServiceRedirect">Assertion Consumer Service Redirect Binding URL</label>
<label class="col-md-2 control-label" for="consumerServiceRedirect">{{:: 'assertion-consumer-redirect-binding-url' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.attributes.saml_assertion_consumer_url_redirect" class="form-control" type="text" name="consumerServiceRedirect" id="consumerServiceRedirect" />
</div>
<kc-tooltip>SAML Redirect Binding URL for the client's assertion consumer service (login responses). You can leave this blank if you do not have a URL for this binding.</kc-tooltip>
<kc-tooltip>{{:: 'assertion-consumer-redirect-binding-url.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="logoutPostBinding">Logout Service POST Binding URL</label>
<label class="col-md-2 control-label" for="logoutPostBinding">{{:: 'logout-service-post-binding-url' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.attributes.saml_single_logout_service_url_post" class="form-control" type="text" name="logoutPostBinding" id="logoutPostBinding" />
</div>
<kc-tooltip>SAML POST Binding URL for the client's single logout service. You can leave this blank if you are using a different binding</kc-tooltip>
<kc-tooltip>{{:: 'logout-service-post-binding-url.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-md-2 control-label" for="logoutPostBinding">Logout Service Redirect Binding URL</label>
<label class="col-md-2 control-label" for="logoutPostBinding">{{:: 'logout-service-redir-binding-url' | translate}}</label>
<div class="col-sm-6">
<input ng-model="client.attributes.saml_single_logout_service_url_redirect" class="form-control" type="text" name="logoutRedirectBinding" id="logoutRedirectBinding" />
</div>
<kc-tooltip>SAML Redirect Binding URL for the client's single logout service. You can leave this blank if you are using a different binding.</kc-tooltip>
<kc-tooltip>{{:: 'logout-service-redir-binding-url.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageClients">
<button kc-save data-ng-disabled="!changed">Save</button>
<button kc-cancel data-ng-click="cancel()">Cancel</button>
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div>
<div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
<button kc-save data-ng-disabled="!changed">Save</button>
<button kc-reset data-ng-disabled="!changed">Cancel</button>
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
</div>
</form>

View file

@ -1,31 +1,31 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li>Import Client</li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{:: 'import-client' | translate}}</li>
</ol>
<h1>Import Client</h1>
<h1>{{:: 'import-client' | translate}}</h1>
<form class="form-horizontal" name="realmForm" novalidate>
<fieldset class="border-top">
<div class="form-group input-select">
<label class="col-md-2 control-label" for="configFormats">Format Option</label>
<label class="col-md-2 control-label" for="configFormats">{{:: 'format-option' | translate}}</label>
<div class="col-md-6">
<div class="input-group">
<div>
<select class="form-control" id="configFormats" name="configFormats" ng-model="configFormat" ng-options="format.name for format in configFormats">
<option value="" selected> Select a Format </option>
<option value="" selected> {{:: 'select-format' | translate}} </option>
</select>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Import File </label>
<label class="col-md-2 control-label">{{:: 'import-file' | translate}} </label>
<div class="col-md-6">
<div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
<label for="import-file" class="btn btn-default">{{:: 'select-file' | translate}} <i class="pficon pficon-import"></i></label>
<input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
</div>
<span class="kc-uploaded-file" data-ng-show="files.length > 0">
@ -35,8 +35,8 @@
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="files.length > 0">
<button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Import</button>
<button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
<button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">{{:: 'import' | translate}}</button>
<button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">{{:: 'cancel' | translate}}</button>
</div>
</div>
</fieldset>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>
@ -10,12 +10,12 @@
<form class="form" name="realmForm" novalidate>
<fieldset>
<div class="form-group input-select">
<label class="col-md-1 control-label" for="configFormats">Format Option</label>
<label class="col-md-1 control-label" for="configFormats">{{:: 'format-option' | translate}}</label>
<div class="col-md-6">
<div class="input-group">
<div>
<select class="form-control" id="configFormats" name="configFormats" ng-change="changeFormat()" ng-model="configFormat" ng-options="a for a in configFormats">
<option value="" selected> Select a Format </option>
<option value="" selected> {{:: 'select-a-format' | translate}} </option>
</select>
</div>
</div>
@ -25,7 +25,7 @@
<fieldset class="margin-top">
<div class="form-group" ng-show="installation">
<div class="col-sm-12">
<a class="btn btn-primary btn-lg" data-ng-click="download()" type="submit" ng-show="installation">Download</a>
<a class="btn btn-primary btn-lg" data-ng-click="download()" type="submit" ng-show="installation">{{:: 'download' | translate}}</a>
<textarea class="form-control" rows="20" kc-select-action="click">{{installation}}</textarea>
</div>
</div>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<h1>
<span>Clients</span>
<kc-tooltip>Clients are trusted browser apps and web services in a realm. These clients can request a login. You can also define client specific roles.</kc-tooltip>
<span>{{:: 'clients' | translate}}</span>
<kc-tooltip>{{:: 'clients.tooltip' | translate}}</kc-tooltip>
</h1>
<table class="table table-striped table-bordered">
@ -11,7 +11,7 @@
<div class="form-inline">
<div class="form-group">
<div class="input-group">
<input type="text" placeholder="Search..." data-ng-model="search.clientId" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
<input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.clientId" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
<div class="input-group-addon">
<i class="fa fa-search" type="submit"></i>
</div>
@ -19,37 +19,37 @@
</div>
<div class="pull-right" data-ng-show="access.manageClients">
<a id="createClient" class="btn btn-default" href="#/create/client/{{realm.realm}}">Create</a>
<a id="importClient" class="btn btn-default" href="#/import/client/{{realm.realm}}" data-ng-show="importButton">Import</a>
<a id="createClient" class="btn btn-default" href="#/create/client/{{realm.realm}}">{{:: 'create' | translate}}</a>
<a id="importClient" class="btn btn-default" href="#/import/client/{{realm.realm}}" data-ng-show="importButton">{{:: 'import' | translate}}</a>
</div>
</div>
</th>
</tr>
<tr data-ng-hide="clients.length == 0">
<th>Client ID</th>
<th>Enabled</th>
<th>Base URL</th>
<th colspan="2">Actions</th>
<th>{{:: 'client-id' | translate}}</th>
<th>{{:: 'enabled' | translate}}</th>
<th>{{:: 'base-url' | translate}}</th>
<th colspan="2">{{:: 'actions' | translate}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="client in clients | filter:search | orderBy:'clientId'">
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></td>
<td>{{client.enabled}}</td>
<td translate="{{client.enabled}}"></td>
<td ng-class="{'text-muted': !client.baseUrl}">
<a href="{{client.rootUrl}}{{client.baseUrl}}" target="_blank" data-ng-show="client.baseUrl">{{client.rootUrl}}{{client.baseUrl}}</a>
<span data-ng-hide="client.baseUrl">Not defined</span>
<span data-ng-hide="client.baseUrl">{{:: 'not-defined' | translate}}</span>
</td>
<td class="kc-action-cell">
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}">Edit</button>
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}">{{:: 'edit' | translate}}</button>
</td>
<td class="kc-action-cell">
<button class="btn btn-default btn-block btn-sm" data-ng-click="removeClient(client)">Delete</button>
<button class="btn btn-default btn-block btn-sm" data-ng-click="removeClient(client)">{{:: 'delete' | translate}}</button>
</td>
</tr>
<tr data-ng-show="(clients | filter:search).length == 0">
<td class="text-muted" colspan="3" data-ng-show="search.clientId">No results</td>
<td class="text-muted" colspan="3" data-ng-hide="search.clientId">No clients available</td>
<td class="text-muted" colspan="3" data-ng-show="search.clientId">{{:: 'no-results' | translate}}</td>
<td class="text-muted" colspan="3" data-ng-hide="search.clientId">{{:: 'no-clients-available' | translate}}</td>
</tr>
</tbody>
</table>

View file

@ -1,13 +1,13 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">Mappers</a></li>
<li class="active">Add Builtin Protocol Mappers</li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">{{:: 'mappers' | translate}}</a></li>
<li class="active">{{:: 'add-builtin-protocol-mappers' | translate}}</li>
</ol>
<h1>Add Builtin Protocol Mapper</h1>
<h1>{{:: 'add-builtin-protocol-mapper' | translate}}</h1>
<table class="table table-striped table-bordered">
<thead>
@ -16,7 +16,7 @@
<div class="form-inline">
<div class="form-group">
<div class="input-group">
<input type="text" placeholder="Search..." data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
<input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
<div class="input-group-addon">
<i class="fa fa-search" type="submit"></i>
</div>
@ -26,10 +26,10 @@
</th>
</tr>
<tr data-ng-hide="mappers.length == 0">
<th>Name</th>
<th>Category</th>
<th>Type</th>
<th>Add</th>
<th>{{:: 'name' | translate}}</th>
<th>{{:: 'category' | translate}}</th>
<th>{{:: 'type' | translate}}</th>
<th>{{:: 'add' | translate}}</th>
</tr>
</thead>
<tbody>
@ -40,13 +40,13 @@
<td><input type="checkbox" ng-model="mapper.isChecked"></td>
</tr>
<tr data-ng-show="mappers.length == 0">
<td>No mappers available</td>
<td>{{:: 'no-mappers-available' | translate}}</td>
</tr>
</tbody>
</table>
<div data-ng-show="access.manageRealm">
<button class="btn btn-primary" data-ng-click="add()">Add Selected</button>
<button class="btn btn-primary" data-ng-click="add()">{{:: 'add-selected' | translate}}</button>
</div>
</div>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>
@ -14,7 +14,7 @@
<div class="form-inline">
<div class="form-group">
<div class="input-group">
<input type="text" placeholder="Search..." data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
<input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.name" class="form-control search" onkeyup="if(event.keyCode == 13){$(this).next('I').click();}">
<div class="input-group-addon">
<i class="fa fa-search" type="submit"></i>
</div>
@ -22,17 +22,17 @@
</div>
<div class="pull-right" data-ng-show="access.manageClients">
<a class="btn btn-default" href="#/create/client/{{realm.realm}}/{{client.id}}/mappers">Create</a>
<a class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/add-mappers">Add Builtin</a>
<a class="btn btn-default" href="#/create/client/{{realm.realm}}/{{client.id}}/mappers">{{:: 'create' | translate}}</a>
<a class="btn btn-default" href="#/realms/{{realm.realm}}/clients/{{client.id}}/add-mappers">{{:: 'add-builtin' | translate}}</a>
</div>
</div>
</th>
</tr>
<tr data-ng-hide="mappers.length == 0">
<th>Name</th>
<th>Category</th>
<th>Type</th>
<th colspan="2">Actions</th>
<th>{{:: 'name' | translate}}</th>
<th>{{:: 'category' | translate}}</th>
<th>{{:: 'type' | translate}}</th>
<th colspan="2">{{:: 'actions' | translate}}</th>
</tr>
</thead>
<tbody>
@ -41,14 +41,14 @@
<td>{{mapperTypes[mapper.protocolMapper].category}}</td>
<td>{{mapperTypes[mapper.protocolMapper].name}}</td>
<td class="kc-action-cell">
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/mappers/{{mapper.id}}">Edit</button>
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/mappers/{{mapper.id}}">{{:: 'edit' | translate}}</button>
</td>
<td class="kc-action-cell">
<button class="btn btn-default btn-block btn-sm" data-ng-click="removeMapper(mapper)">Delete</button>
<button class="btn btn-default btn-block btn-sm" data-ng-click="removeMapper(mapper)">{{:: 'delete' | translate}}</button>
</td>
</tr>
<tr data-ng-show="mappers.length == 0">
<td>No mappers available</td>
<td>{{:: 'no-mappers-available' | translate}}</td>
</tr>
</tbody>
</table>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>
@ -10,11 +10,11 @@
<form class="form-horizontal" name="sessionStats">
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="activeSessions">Offline Tokens</label>
<label class="col-md-2 control-label" for="activeSessions">{{:: 'offline-tokens' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="text" id="activeSessions" name="activeSessions" data-ng-model="count" ng-disabled="true">
</div>
<kc-tooltip>Total number of offline tokens for this client.</kc-tooltip>
<kc-tooltip>{{:: 'offline-tokens.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset>
</form>
@ -23,23 +23,23 @@
<tr>
<th class="kc-table-actions" colspan="3">
<div class="pull-right">
<a class="btn btn-default" ng-click="loadUsers()" tooltip-placement="left" tooltip-trigger="mouseover mouseout" tooltip="Warning, this is a potentially expensive operation depending on number of offline tokens.">Show Offline Tokens</a>
<a class="btn btn-default" ng-click="loadUsers()" tooltip-placement="left" tooltip-trigger="mouseover mouseout" tooltip="{{:: 'show-offline-tokens.tooltip' | translate}}">{{:: 'show-offline-tokens' | translate}}</a>
</div>
</th>
</tr>
<tr data-ng-show="sessions">
<th>User</th>
<th>From IP</th>
<th>Token Issued</th>
<th>{{:: 'user' | translate}}</th>
<th>{{:: 'from-ip' | translate}}</th>
<th>{{:: 'token-issued' | translate}}</th>
</tr>
</thead>
<tfoot data-ng-show="sessions && (sessions.length >= 5 || query.first != 0)">
<tr>
<td colspan="7">
<div class="table-nav">
<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">First page</button>
<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">Previous page</button>
<button data-ng-click="nextPage()" class="next" ng-disabled="sessions.length < query.max">Next page</button>
<button data-ng-click="firstPage()" class="first" ng-disabled="query.first == 0">{{:: 'first-page' | translate}}</button>
<button data-ng-click="previousPage()" class="prev" ng-disabled="query.first == 0">{{:: 'previous-page' | translate}}</button>
<button data-ng-click="nextPage()" class="next" ng-disabled="sessions.length < query.max">{{:: 'next-page' | translate}}</button>
</div>
</td>
</tr>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>
@ -10,18 +10,18 @@
<form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageRealm">
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="notBefore">Not Before</label>
<label class="col-md-2 control-label" for="notBefore">{{:: 'not-before' | translate}}</label>
<div class="col-md-6">
<input ng-disabled="true" class="form-control" type="text" id="notBefore" name="notBefore" data-ng-model="notBefore" autofocus>
</div>
<kc-tooltip>Revoke any tokens issued before this date for this client.</kc-tooltip>
<kc-tooltip>{{:: 'client-revoke.not-before.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageClients">
<button type="submit" data-ng-click="clear()" class="btn btn-default">Clear</button>
<button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-default">Set To Now</button>
<button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary" tooltip-trigger="mouseover mouseout" tooltip="If admin URL is configured for this client, push this policy to that client." tooltip-placement="bottom">Push</button>
<button type="submit" data-ng-click="clear()" class="btn btn-default">{{:: 'clear' | translate}}</button>
<button type="submit" data-ng-click="setNotBeforeNow()" class="btn btn-default">{{:: 'set-to-now' | translate}}</button>
<button type="submit" data-ng-click="pushRevocation()" class="btn btn-primary" tooltip-trigger="mouseover mouseout" tooltip="{{:: 'client-revoke.push.tooltip' | translate}}" tooltip-placement="bottom">{{:: 'push' | translate}}</button>
</div>
</div>
</form>

View file

@ -1,14 +1,14 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">Roles</a></li>
<li data-ng-show="create">Add role</li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">{{:: 'roles' | translate}}</a></li>
<li data-ng-show="create">{{:: 'add-role' | translate}}</li>
<li data-ng-hide="create">{{role.name}}</li>
</ol>
<h1 data-ng-show="create">Add Role</h1>
<h1 data-ng-show="create">{{:: 'add-role' | translate}}</h1>
<h1 data-ng-hide="create">{{role.name|capitalize}}<i class="pficon pficon-delete clickable" data-ng-show="!create && access.manageClients"
data-ng-hide="changed" data-ng-click="remove()"></i></h1>
@ -16,7 +16,7 @@
<fieldset class="border-top">
<div class="form-group">
<label class="col-md-2 control-label" for="name">Role name <span class="required" data-ng-show="create">*</span></label>
<label class="col-md-2 control-label" for="name">{{:: 'role-name' | translate}} <span class="required" data-ng-show="create">*</span></label>
<div class="col-md-6">
<input class="form-control" type="text" id="name" name="name" data-ng-model="role.name" autofocus
@ -24,7 +24,7 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="description">Description </label>
<label class="col-md-2 control-label" for="description">{{:: 'description' | translate}} </label>
<div class="col-md-6">
<textarea class="form-control" rows="5" cols="50" id="description" name="description" data-ng-model="role.description"></textarea>
@ -33,64 +33,64 @@
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="scopeParamRequired">Scope Param Required </label>
<kc-tooltip>This role will be granted just if scope parameter with role name is used during authorization/token request.</kc-tooltip>
<label class="col-md-2 control-label" for="scopeParamRequired">{{:: 'scope-param-required' | translate}} </label>
<kc-tooltip>{{:: 'scope-param-required.tooltip' | translate}}</kc-tooltip>
<div class="col-md-6">
<input ng-model="role.scopeParamRequired" name="scopeParamRequired" id="scopeParamRequired" onoffswitch />
<input ng-model="role.scopeParamRequired" name="scopeParamRequired" id="scopeParamRequired" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
</div>
</div>
<div class="form-group clearfix block" data-ng-hide="create">
<label class="col-md-2 control-label" for="compositeSwitch" class="control-label">Composite Roles</label>
<label class="col-md-2 control-label" for="compositeSwitch" class="control-label">{{:: 'composite-roles' | translate}}</label>
<div class="col-md-6">
<input ng-model="compositeSwitch" name="compositeSwitch" id="compositeSwitch" ng-disabled="compositeSwitchDisabled" onoffswitch />
<input ng-model="compositeSwitch" name="compositeSwitch" id="compositeSwitch" ng-disabled="compositeSwitchDisabled" onoffswitch on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
</div>
<kc-tooltip>When this role is (un)assigned to a user any role associated with it will be (un)assigned implicitly.</kc-tooltip>
<kc-tooltip>{{:: 'composite-roles.tooltip' | translate}}</kc-tooltip>
</div>
</fieldset>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="create && access.manageClients">
<button kc-save>Save</button>
<button kc-cancel data-ng-click="cancel()">Cancel</button>
<button kc-save>{{:: 'save' | translate}}</button>
<button kc-cancel data-ng-click="cancel()">{{:: 'cancel' | translate}}</button>
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="!create && access.manageClients">
<button kc-save data-ng-disabled="!changed">Save</button>
<button kc-reset data-ng-disabled="!changed">Cancel</button>
<button kc-save data-ng-disabled="!changed">{{:: 'save' | translate}}</button>
<button kc-reset data-ng-disabled="!changed">{{:: 'cancel' | translate}}</button>
</div>
</div>
<fieldset data-ng-show="!create && (compositeSwitch || role.composite)">
<legend uncollapsed><span class="text">Composite Roles</span> </legend>
<legend uncollapsed><span class="text">{{:: 'composite-roles' | translate}}</span> </legend>
<div class="form-group">
<label class="col-md-2 control-label" class="control-label">Realm Roles</label>
<label class="col-md-2 control-label" class="control-label">{{:: 'realm-roles' | translate}}</label>
<div class="col-md-10">
<div class="row">
<div class="col-md-4">
<label class="control-label" for="available">Available Roles</label>
<kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
<label class="control-label" for="available">{{:: 'available-roles' | translate}}</label>
<kc-tooltip>{{:: 'composite.available-realm-roles.tooltip' | translate}}</kc-tooltip>
<select id="available" class="form-control" multiple size="5"
ng-multiple="true"
ng-model="selectedRealmRoles"
ng-options="r.name for r in realmRoles">
</select>
<button ng-disabled="selectedRealmRoles.length == 0" class="btn btn-default" type="submit" ng-click="addRealmRole()">
Add selected <i class="fa fa-angle-double-right"></i>
{{:: 'add-selected' | translate}} <i class="fa fa-angle-double-right"></i>
</button>
</div>
<div class="col-md-4">
<label class="control-label" for="assigned">Associated Roles</label>
<kc-tooltip>Realm level roles associated with this composite role.</kc-tooltip>
<label class="control-label" for="assigned">{{:: 'associated-roles' | translate}}</label>
<kc-tooltip>{{:: 'composite.associated-realm-roles.tooltip' | translate}}</kc-tooltip>
<select id="assigned" class="form-control" multiple size=5
ng-multiple="true"
ng-model="selectedRealmMappings"
ng-options="r.name for r in realmMappings">
</select>
<button ng-disabled="selectedRealmMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteRealmRole()">
<i class="fa fa-angle-double-left"></i> Remove selected
<i class="fa fa-angle-double-left"></i> {{:: 'remove-selected' | translate}}
</button>
</div>
</div>
@ -99,37 +99,37 @@
<div class="form-group" ng-show="clients.length > 0 && !create && (compositeSwitch || role.composite)">
<label class="col-md-2 control-label" class="control-label">
<span>Client Roles</span>
<span>{{:: 'client-roles' | translate}}</span>
<select class="form-control" id="clients" name="clients" ng-change="changeClient()" ng-model="compositeClient" ng-options="a.clientId for a in clients" ng-disabled="false"></select>
</label>
<div class="col-md-10">
<div class="row" data-ng-hide="compositeClient">
<div class="col-md-4"><span class="text-muted">Select client to view roles for client</span></div>
<div class="col-md-4"><span class="text-muted">{{:: 'select-client-to-view-roles' | translate}}</span></div>
</div>
<div class="row" data-ng-show="compositeClient">
<div class="col-md-4">
<label class="control-label" for="available-client">Available Roles</label>
<kc-tooltip>Roles from this client that you can associate to this composite role.</kc-tooltip>
<label class="control-label" for="available-client">{{:: 'available-roles' | translate}}</label>
<kc-tooltip>{{:: 'available-roles.tooltip' | translate}}</kc-tooltip>
<select id="available-client" class="form-control" multiple size="5"
ng-multiple="true"
ng-model="selectedClientRoles"
ng-options="r.name for r in clientRoles">
</select>
<button ng-disabled="selectedClientRoles.length == 0" class="btn btn-default" type="submit" ng-click="addClientRole()">
Add selected <i class="fa fa-angle-double-right"></i>
{{:: 'add-selected' | translate}} <i class="fa fa-angle-double-right"></i>
</button>
</div>
<div class="col-md-4">
<label class="control-label" for="assigned-client">Associated Roles</label>
<kc-tooltip>Client roles associated with this composite role.</kc-tooltip>
<label class="control-label" for="assigned-client">{{:: 'associated-roles' | translate}}</label>
<kc-tooltip>{{:: 'client.associated-roles.tooltip' | translate}}</kc-tooltip>
<select id="assigned-client" class="form-control" multiple size=5
ng-multiple="true"
ng-model="selectedClientMappings"
ng-options="r.name for r in clientMappings">
</select>
<button ng-disabled="selectedClientMappings.length == 0" class="btn btn-default" type="submit" ng-click="deleteClientRole()">
<i class="fa fa-angle-double-left"></i> Remove selected
<i class="fa fa-angle-double-left"></i> {{:: 'remove-selected' | translate}}
</button>
</div>
</div>

View file

@ -1,7 +1,7 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li>{{client.clientId}}</li>
</ol>
@ -12,28 +12,28 @@
<tr>
<th class="kc-table-actions" colspan="4" data-ng-show="access.manageClients">
<div class="pull-right">
<a class="btn btn-default" href="#/create/role/{{realm.realm}}/clients/{{client.id}}">Add Role</a>
<a class="btn btn-default" href="#/create/role/{{realm.realm}}/clients/{{client.id}}">{{:: 'add-role' | translate}}</a>
</div>
</th>
</tr>
<tr data-ng-hide="!roles || roles.length == 0">
<th>Role Name</th>
<th>Composite</th>
<th>Description</th>
<th>Actions</th>
<th>{{:: 'role-name' | translate}}</th>
<th>{{:: 'composite' | translate}}</th>
<th>{{:: 'description' | translate}}</th>
<th>{{:: 'actions' | translate}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="role in roles">
<td><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles/{{role.id}}">{{role.name}}</a></td>
<td>{{role.composite}}</td>
<td translate="{{role.composite}}"></td>
<td>{{role.description}}</td>
<td class="kc-action-cell">
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/roles/{{role.id}}">Edit</button>
<button class="btn btn-default btn-block btn-sm" kc-open="/realms/{{realm.realm}}/clients/{{client.id}}/roles/{{role.id}}">{{:: 'edit' | translate}}</button>
</td>
</tr>
<tr data-ng-show="!roles || roles.length == 0">
<td>No client roles available</td>
<td>{{:: 'no-client-roles-available' | translate}}</td>
</tr>
</tbody>
</table>

View file

@ -1,18 +1,18 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">SAML Keys</a></li>
<li class="active">SAML {{keyType}} Key Export</li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">{{:: 'saml-keys' | translate}}</a></li>
<li class="active">SAML {{keyType}} {{:: 'key-export' | translate}}</li>
</ol>
<h1>Export SAML Key {{client.clientId|capitalize}}</h1>
<h1>{{:: 'export-saml-key' | translate}} {{client.clientId|capitalize}}</h1>
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
<fieldset class="form-group col-sm-10">
<div class="form-group">
<label class="col-md-2 control-label" for="downloadKeyFormat">Archive Format</label>
<label class="col-md-2 control-label" for="downloadKeyFormat">{{:: 'archive-format' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="downloadKeyFormat"
@ -21,39 +21,39 @@
</select>
</div>
</div>
<kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
<kc-tooltip>{{:: 'archive-format.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="keyAlias">Key Alias</label>
<label class="col-md-2 control-label" for="keyAlias">{{:: 'key-alias' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="text" id="keyAlias" name="keyAlias" data-ng-model="jks.keyAlias" autofocus required>
</div>
<kc-tooltip>Archive alias for your private key and certificate.</kc-tooltip>
<kc-tooltip>{{:: 'key-alias.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group" data-ng-hide="!keyInfo.privateKey">
<label class="col-md-2 control-label" for="keyPassword">Key Password</label>
<label class="col-md-2 control-label" for="keyPassword">{{:: 'key-password' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="password" id="keyPassword" name="keyPassword" data-ng-model="jks.keyPassword" autofocus required>
</div>
<kc-tooltip>Password to access the private key in the archive</kc-tooltip>
<kc-tooltip>{{:: 'key-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="realmAlias">Realm Certificate Alias</label>
<label class="col-md-2 control-label" for="realmAlias">{{:: 'realm-certificate-alias' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="text" id="realmAlias" name="realmAlias" data-ng-model="jks.realmAlias" autofocus required>
</div>
<kc-tooltip>Realm certificate is stored in archive too. This is the alias to it.</kc-tooltip>
<kc-tooltip>{{:: 'realm-certificate-alias.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="storePassword">Store Password</label>
<label class="col-md-2 control-label" for="storePassword">{{:: 'store-password' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="password" id="storePassword" name="storePassword" data-ng-model="jks.storePassword" autofocus required>
</div>
<kc-tooltip>Password to access the archive itself</kc-tooltip>
<kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="access.manageRealm">
<button class="btn btn-primary" type="submit" data-ng-click="download()">Download</button>
<button class="btn btn-primary" type="submit" data-ng-click="download()">{{:: 'download' | translate}}</button>
</div>
</div>
</fieldset>

View file

@ -1,18 +1,18 @@
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
<ol class="breadcrumb">
<li><a href="#/realms/{{realm.realm}}/clients">Clients</a></li>
<li><a href="#/realms/{{realm.realm}}/clients">{{:: 'clients' | translate}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{client.clientId}}</a></li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">SAML Keys</a></li>
<li class="active">SAML {{keyType}} Key Import</li>
<li><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">{{:: 'saml-keys' | translate}}</a></li>
<li class="active">SAML {{keyType}} {{:: 'key-import' | translate}}</li>
</ol>
<h1>Import SAML Key {{client.clientId|capitalize}}</h1>
<h1>{{:: 'import-saml-key' | translate}} {{client.clientId|capitalize}}</h1>
<form class="form-horizontal" name="keyForm" novalidate kc-read-only="!access.manageRealm">
<fieldset>
<div class="form-group">
<label class="col-md-2 control-label" for="uploadKeyFormat">Archive Format</label>
<label class="col-md-2 control-label" for="uploadKeyFormat">{{:: 'archive-format' | translate}}</label>
<div class="col-sm-6">
<div>
<select class="form-control" id="uploadKeyFormat"
@ -21,24 +21,24 @@
</select>
</div>
</div>
<kc-tooltip>Java keystore or PKCS12 archive format.</kc-tooltip>
<kc-tooltip>{{:: 'archive-format.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="uploadKeyAlias">Key Alias</label>
<label class="col-md-2 control-label" for="uploadKeyAlias">{{:: 'key-alias' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="text" id="uploadKeyAlias" name="uploadKeyAlias" data-ng-model="uploadKeyAlias" autofocus required>
</div>
<kc-tooltip>Archive alias for your certificate.</kc-tooltip>
<kc-tooltip>{{:: 'key-alias.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="uploadStorePassword">Store Password</label>
<label class="col-md-2 control-label" for="uploadStorePassword">{{:: 'store-password' | translate}}</label>
<div class="col-md-6">
<input class="form-control" type="password" id="uploadStorePassword" name="uploadStorePassword" data-ng-model="uploadStorePassword" autofocus required>
</div>
<kc-tooltip>Password to access the archive itself</kc-tooltip>
<kc-tooltip>{{:: 'store-password.tooltip' | translate}}</kc-tooltip>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Import File </label>
<label class="col-md-2 control-label">{{:: 'import-file' | translate}} </label>
<div class="col-md-6">
<div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
@ -51,8 +51,8 @@
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2" data-ng-show="files.length > 0">
<button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">Import</button>
<button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
<button type="submit" data-ng-click="uploadFile()" class="btn btn-primary">{{:: 'import' | translate}}</button>
<button type="submit" data-ng-click="clearFileSelect()" class="btn btn-default">{{:: 'cancel' | translate}}</button>
</div>
</div>
</fieldset>

Some files were not shown because too many files have changed in this diff Show more