tomcat6 adapter
This commit is contained in:
parent
791a740f32
commit
88355d7eb4
98 changed files with 3617 additions and 652 deletions
|
@ -56,6 +56,7 @@
|
||||||
<module-def name="org.keycloak.keycloak-adapter-spi">
|
<module-def name="org.keycloak.keycloak-adapter-spi">
|
||||||
<maven-resource group="org.keycloak" artifact="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-tomcat-adapter-spi"/>
|
||||||
|
<maven-resource group="org.keycloak" artifact="keycloak-as7-adapter-spi"/>
|
||||||
</module-def>
|
</module-def>
|
||||||
|
|
||||||
<module-def name="org.keycloak.keycloak-adapter-core">
|
<module-def name="org.keycloak.keycloak-adapter-core">
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-adapter-spi</artifactId>
|
<artifactId>keycloak-adapter-spi</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-as7-adapter-spi</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
|
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
<module name="org.jboss.logging"/>
|
<module name="org.jboss.logging"/>
|
||||||
<module name="org.picketbox"/>
|
<module name="org.picketbox"/>
|
||||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
<module name="org.keycloak.keycloak-core"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ public interface AdapterTokenStore extends AdapterSessionStore {
|
||||||
*
|
*
|
||||||
* @param account
|
* @param account
|
||||||
*/
|
*/
|
||||||
void saveAccountInfo(KeycloakAccount account);
|
void saveAccountInfo(OidcKeycloakAccount account);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle logout on store side and possibly propagate logout call to Keycloak
|
* Handle logout on store side and possibly propagate logout call to Keycloak
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package org.keycloak.adapters;
|
||||||
|
|
||||||
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface OidcKeycloakAccount extends KeycloakAccount {
|
||||||
|
KeycloakSecurityContext getKeycloakSecurityContext();
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.adapters;
|
package org.keycloak.adapters;
|
||||||
|
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -11,6 +9,6 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public interface KeycloakAccount {
|
public interface KeycloakAccount {
|
||||||
Principal getPrincipal();
|
Principal getPrincipal();
|
||||||
|
|
||||||
Set<String> getRoles();
|
Set<String> getRoles();
|
||||||
KeycloakSecurityContext getKeycloakSecurityContext();
|
|
||||||
}
|
}
|
85
integration/as7-eap6/as7-adapter-spi/pom.xml
Executable file
85
integration/as7-eap6/as7-adapter-spi/pom.xml
Executable file
|
@ -0,0 +1,85 @@
|
||||||
|
<?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>
|
||||||
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>keycloak-as7-adapter-spi</artifactId>
|
||||||
|
<name>Keycloak AS7 SPI</name>
|
||||||
|
<description/>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-adapter-spi</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.logging</groupId>
|
||||||
|
<artifactId>jboss-logging</artifactId>
|
||||||
|
<version>${jboss.logging.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.web</groupId>
|
||||||
|
<artifactId>jbossweb</artifactId>
|
||||||
|
<version>7.0.17.Final</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.as</groupId>
|
||||||
|
<artifactId>jboss-as-web</artifactId>
|
||||||
|
<version>7.1.2.Final</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compiler.source}</source>
|
||||||
|
<target>${maven.compiler.target}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -9,7 +9,6 @@ import org.jboss.security.SecurityContext;
|
||||||
import org.jboss.security.SecurityContextAssociation;
|
import org.jboss.security.SecurityContextAssociation;
|
||||||
import org.jboss.security.SimpleGroup;
|
import org.jboss.security.SimpleGroup;
|
||||||
import org.jboss.security.SimplePrincipal;
|
import org.jboss.security.SimplePrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
import org.keycloak.adapters.KeycloakAccount;
|
||||||
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ public class JBossWebPrincipalFactory extends GenericPrincipalFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet, final KeycloakSecurityContext securityContext) {
|
public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet) {
|
||||||
KeycloakAccount account = new KeycloakAccount() {
|
KeycloakAccount account = new KeycloakAccount() {
|
||||||
@Override
|
@Override
|
||||||
public Principal getPrincipal() {
|
public Principal getPrincipal() {
|
||||||
|
@ -49,11 +48,6 @@ public class JBossWebPrincipalFactory extends GenericPrincipalFactory {
|
||||||
public Set<String> getRoles() {
|
public Set<String> getRoles() {
|
||||||
return roleSet;
|
return roleSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public KeycloakSecurityContext getKeycloakSecurityContext() {
|
|
||||||
return securityContext;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Subject subject = new Subject();
|
Subject subject = new Subject();
|
||||||
Set<Principal> principals = subject.getPrincipals();
|
Set<Principal> principals = subject.getPrincipals();
|
|
@ -18,6 +18,10 @@
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-core</artifactId>
|
<artifactId>keycloak-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-as7-adapter-spi</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-adapter-spi</artifactId>
|
<artifactId>keycloak-adapter-spi</artifactId>
|
||||||
|
|
1
integration/as7-eap6/pom.xml
Normal file → Executable file
1
integration/as7-eap6/pom.xml
Normal file → Executable file
|
@ -14,6 +14,7 @@
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
<module>as7-adapter-spi</module>
|
||||||
<module>as7-adapter</module>
|
<module>as7-adapter</module>
|
||||||
<module>as7-subsystem</module>
|
<module>as7-subsystem</module>
|
||||||
<module>as7-server-subsystem</module>
|
<module>as7-server-subsystem</module>
|
||||||
|
|
|
@ -28,10 +28,6 @@
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-adapter-spi</artifactId>
|
<artifactId>keycloak-adapter-spi</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-adapter-core</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
|
|
|
@ -7,8 +7,8 @@ import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.CookieTokenStore;
|
import org.keycloak.adapters.CookieTokenStore;
|
||||||
import org.keycloak.adapters.HttpFacade;
|
import org.keycloak.adapters.HttpFacade;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public class JettyCookieTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
||||||
CookieTokenStore.setTokenCookie(deployment, facade, securityContext);
|
CookieTokenStore.setTokenCookie(deployment, facade, securityContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
import org.keycloak.adapters.AdapterUtils;
|
||||||
import org.keycloak.adapters.HttpFacade;
|
import org.keycloak.adapters.HttpFacade;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public class JettyRequestAuthenticator extends RequestAuthenticator {
|
||||||
principal = skp;
|
principal = skp;
|
||||||
final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
|
final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
|
||||||
final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
||||||
KeycloakAccount account = new KeycloakAccount() {
|
OidcKeycloakAccount account = new OidcKeycloakAccount() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Principal getPrincipal() {
|
public Principal getPrincipal() {
|
||||||
|
|
|
@ -7,8 +7,8 @@ import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterSessionStore;
|
import org.keycloak.adapters.AdapterSessionStore;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
import org.keycloak.adapters.AdapterUtils;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ public class JettySessionTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
|
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
|
||||||
request.getSession().setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
request.getSession().setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
||||||
}
|
}
|
||||||
|
|
6
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/account/SimpleKeycloakAccount.java
Normal file → Executable file
6
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/account/SimpleKeycloakAccount.java
Normal file → Executable file
|
@ -1,6 +1,6 @@
|
||||||
package org.keycloak.adapters.springsecurity.account;
|
package org.keycloak.adapters.springsecurity.account;
|
||||||
|
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -8,12 +8,12 @@ import java.security.Principal;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete, serializable {@link KeycloakAccount} implementation.
|
* Concrete, serializable {@link org.keycloak.adapters.OidcKeycloakAccount} implementation.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:srossillo@smartling.com">Scott Rossillo</a>
|
* @author <a href="mailto:srossillo@smartling.com">Scott Rossillo</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class SimpleKeycloakAccount implements KeycloakAccount, Serializable {
|
public class SimpleKeycloakAccount implements OidcKeycloakAccount, Serializable {
|
||||||
|
|
||||||
private Set<String> roles;
|
private Set<String> roles;
|
||||||
private Principal principal;
|
private Principal principal;
|
||||||
|
|
|
@ -8,20 +8,18 @@ import org.keycloak.adapters.HttpFacade;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
import org.keycloak.adapters.KeycloakAccount;
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount;
|
import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount;
|
||||||
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request authenticator adapter for Spring Security.
|
* Request authenticator adapter for Spring Security.
|
||||||
|
@ -64,7 +62,7 @@ public class SpringSecurityRequestAuthenticator extends RequestAuthenticator {
|
||||||
|
|
||||||
final RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
|
final RefreshableKeycloakSecurityContext securityContext = principal.getKeycloakSecurityContext();
|
||||||
final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
||||||
final KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, securityContext);
|
final OidcKeycloakAccount account = new SimpleKeycloakAccount(principal, roles, securityContext);
|
||||||
|
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
||||||
this.tokenStore.saveAccountInfo(account);
|
this.tokenStore.saveAccountInfo(account);
|
||||||
|
|
2
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java
Normal file → Executable file
2
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakPreAuthActionsFilter.java
Normal file → Executable file
|
@ -70,7 +70,7 @@ public class KeycloakPreAuthActionsFilter extends GenericFilterBean implements A
|
||||||
HttpFacade facade = new SimpleHttpFacade((HttpServletRequest)request, (HttpServletResponse)response);
|
HttpFacade facade = new SimpleHttpFacade((HttpServletRequest)request, (HttpServletResponse)response);
|
||||||
PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deploymentContext, facade);
|
PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deploymentContext, facade);
|
||||||
if (handler.handleRequest()) {
|
if (handler.handleRequest()) {
|
||||||
log.info("Pre-auth filter handled request: {}", ((HttpServletRequest) request).getRequestURI());
|
log.debug("Pre-auth filter handled request: {}", ((HttpServletRequest) request).getRequestURI());
|
||||||
} else {
|
} else {
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
5
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/token/KeycloakAuthenticationToken.java
Normal file → Executable file
5
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/token/KeycloakAuthenticationToken.java
Normal file → Executable file
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.adapters.springsecurity.token;
|
package org.keycloak.adapters.springsecurity.token;
|
||||||
|
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
import org.keycloak.adapters.KeycloakAccount;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
@ -51,7 +52,7 @@ public class KeycloakAuthenticationToken extends AbstractAuthenticationToken imp
|
||||||
return principal;
|
return principal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeycloakAccount getAccount() {
|
public OidcKeycloakAccount getAccount() {
|
||||||
return (KeycloakAccount) this.getDetails();
|
return (OidcKeycloakAccount) this.getDetails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/token/SpringSecurityTokenStore.java
Normal file → Executable file
8
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/token/SpringSecurityTokenStore.java
Normal file → Executable file
|
@ -2,8 +2,8 @@ package org.keycloak.adapters.springsecurity.token;
|
||||||
|
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -58,12 +58,12 @@ public class SpringSecurityTokenStore implements AdapterTokenStore {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("Remote logged in already. Establishing state from security context.");
|
logger.debug("Remote logged in already. Establishing state from security context.");
|
||||||
token = (KeycloakAuthenticationToken) context.getAuthentication();
|
token = (KeycloakAuthenticationToken) context.getAuthentication();
|
||||||
keycloakSecurityContext = token.getAccount().getKeycloakSecurityContext();
|
keycloakSecurityContext = token.getAccount().getKeycloakSecurityContext();
|
||||||
|
|
||||||
if (!deployment.getRealm().equals(keycloakSecurityContext.getRealm())) {
|
if (!deployment.getRealm().equals(keycloakSecurityContext.getRealm())) {
|
||||||
logger.info("Account from security context is from a different realm than for the request.");
|
logger.debug("Account from security context is from a different realm than for the request.");
|
||||||
logout();
|
logout();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ public class SpringSecurityTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
|
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
|
|
4
integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandlerTest.java
Normal file → Executable file
4
integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/authentication/KeycloakLogoutHandlerTest.java
Normal file → Executable file
|
@ -2,8 +2,8 @@ package org.keycloak.adapters.springsecurity.authentication;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
|
import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
|
||||||
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
||||||
|
@ -38,7 +38,7 @@ public class KeycloakLogoutHandlerTest {
|
||||||
private AdapterDeploymentContextBean adapterDeploymentContextBean;
|
private AdapterDeploymentContextBean adapterDeploymentContextBean;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeycloakAccount keycloakAccount;
|
private OidcKeycloakAccount keycloakAccount;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeycloakDeployment keycloakDeployment;
|
private KeycloakDeployment keycloakDeployment;
|
||||||
|
|
|
@ -6,9 +6,9 @@ import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.HttpFacade;
|
import org.keycloak.adapters.HttpFacade;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||||
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||||
|
@ -82,7 +82,7 @@ public class SpringSecurityRequestAuthenticatorTest {
|
||||||
public void testCompleteOAuthAuthentication() throws Exception {
|
public void testCompleteOAuthAuthentication() throws Exception {
|
||||||
authenticator.completeOAuthAuthentication(principal);
|
authenticator.completeOAuthAuthentication(principal);
|
||||||
verify(request).setAttribute(eq(KeycloakSecurityContext.class.getName()), eq(refreshableKeycloakSecurityContext));
|
verify(request).setAttribute(eq(KeycloakSecurityContext.class.getName()), eq(refreshableKeycloakSecurityContext));
|
||||||
verify(tokenStore).saveAccountInfo(any(KeycloakAccount.class)); // FIXME: should verify account
|
verify(tokenStore).saveAccountInfo(any(OidcKeycloakAccount.class)); // FIXME: should verify account
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
4
integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/client/KeycloakClientRequestFactoryTest.java
Normal file → Executable file
4
integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/client/KeycloakClientRequestFactoryTest.java
Normal file → Executable file
|
@ -4,7 +4,7 @@ import org.apache.http.client.methods.HttpUriRequest;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
||||||
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
|
@ -28,7 +28,7 @@ public class KeycloakClientRequestFactoryTest {
|
||||||
private KeycloakClientRequestFactory factory;
|
private KeycloakClientRequestFactory factory;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeycloakAccount account;
|
private OidcKeycloakAccount account;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeycloakAuthenticationToken keycloakAuthenticationToken;
|
private KeycloakAuthenticationToken keycloakAuthenticationToken;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
import org.keycloak.adapters.KeycloakAccount;
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
|
import org.keycloak.adapters.springsecurity.AdapterDeploymentContextBean;
|
||||||
import org.keycloak.adapters.springsecurity.KeycloakAuthenticationException;
|
import org.keycloak.adapters.springsecurity.KeycloakAuthenticationException;
|
||||||
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
||||||
|
@ -67,7 +68,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||||
private AuthenticationFailureHandler failureHandler;
|
private AuthenticationFailureHandler failureHandler;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeycloakAccount keycloakAccount;
|
private OidcKeycloakAccount keycloakAccount;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeycloakDeployment keycloakDeployment;
|
private KeycloakDeployment keycloakDeployment;
|
||||||
|
|
8
integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/token/SpringSecurityTokenStoreTest.java
Normal file → Executable file
8
integration/spring-security/src/test/java/org/keycloak/adapters/springsecurity/token/SpringSecurityTokenStoreTest.java
Normal file → Executable file
|
@ -3,8 +3,8 @@ package org.keycloak.adapters.springsecurity.token;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
import org.keycloak.adapters.springsecurity.account.KeycloakRole;
|
||||||
|
@ -17,8 +17,6 @@ import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||||
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@ -66,7 +64,7 @@ public class SpringSecurityTokenStoreTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSaveAccountInfo() throws Exception {
|
public void testSaveAccountInfo() throws Exception {
|
||||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, Collections.singleton("FOO"), keycloakSecurityContext);
|
OidcKeycloakAccount account = new SimpleKeycloakAccount(principal, Collections.singleton("FOO"), keycloakSecurityContext);
|
||||||
Authentication authentication;
|
Authentication authentication;
|
||||||
|
|
||||||
store.saveAccountInfo(account);
|
store.saveAccountInfo(account);
|
||||||
|
@ -78,7 +76,7 @@ public class SpringSecurityTokenStoreTest {
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void testSaveAccountInfoInvalidAuthenticationType() throws Exception {
|
public void testSaveAccountInfoInvalidAuthenticationType() throws Exception {
|
||||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, Collections.singleton("FOO"), keycloakSecurityContext);
|
OidcKeycloakAccount account = new SimpleKeycloakAccount(principal, Collections.singleton("FOO"), keycloakSecurityContext);
|
||||||
Authentication authentication = new PreAuthenticatedAuthenticationToken("foo", "bar", Collections.singleton(new KeycloakRole("ROLE_FOO")));
|
Authentication authentication = new PreAuthenticatedAuthenticationToken("foo", "bar", Collections.singleton(new KeycloakRole("ROLE_FOO")));
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
store.saveAccountInfo(account);
|
store.saveAccountInfo(account);
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
import org.apache.catalina.Realm;
|
import org.apache.catalina.Realm;
|
||||||
import org.apache.catalina.realm.GenericPrincipal;
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
import javax.security.auth.Subject;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
|
@ -20,7 +19,7 @@ import java.util.Set;
|
||||||
*/
|
*/
|
||||||
public abstract class GenericPrincipalFactory {
|
public abstract class GenericPrincipalFactory {
|
||||||
|
|
||||||
public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet, final KeycloakSecurityContext securityContext) {
|
public GenericPrincipal createPrincipal(Realm realm, final Principal identity, final Set<String> roleSet) {
|
||||||
Subject subject = new Subject();
|
Subject subject = new Subject();
|
||||||
Set<Principal> principals = subject.getPrincipals();
|
Set<Principal> principals = subject.getPrincipals();
|
||||||
principals.add(identity);
|
principals.add(identity);
|
|
@ -11,8 +11,8 @@ import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
import org.keycloak.adapters.AdapterUtils;
|
||||||
import org.keycloak.adapters.CookieTokenStore;
|
import org.keycloak.adapters.CookieTokenStore;
|
||||||
import org.keycloak.adapters.HttpFacade;
|
import org.keycloak.adapters.HttpFacade;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore {
|
||||||
|
|
||||||
securityContext.setCurrentRequestInfo(deployment, this);
|
securityContext.setCurrentRequestInfo(deployment, this);
|
||||||
Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
||||||
GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), authenticatedPrincipal, roles, securityContext);
|
GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), authenticatedPrincipal, roles);
|
||||||
|
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
||||||
request.setUserPrincipal(principal);
|
request.setUserPrincipal(principal);
|
||||||
|
@ -69,7 +69,7 @@ public class CatalinaCookieTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
||||||
CookieTokenStore.setTokenCookie(deployment, facade, securityContext);
|
CookieTokenStore.setTokenCookie(deployment, facade, securityContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,16 @@
|
||||||
package org.keycloak.adapters.tomcat;
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
import org.apache.catalina.authenticator.Constants;
|
|
||||||
import org.apache.catalina.connector.Request;
|
import org.apache.catalina.connector.Request;
|
||||||
import org.keycloak.KeycloakPrincipal;
|
import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
import org.keycloak.adapters.AdapterUtils;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
import org.keycloak.adapters.OAuthRequestAuthenticator;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
import org.keycloak.enums.TokenStore;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -49,7 +46,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
|
||||||
protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> skp) {
|
protected void completeOAuthAuthentication(final KeycloakPrincipal<RefreshableKeycloakSecurityContext> skp) {
|
||||||
final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
|
final RefreshableKeycloakSecurityContext securityContext = skp.getKeycloakSecurityContext();
|
||||||
final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(securityContext);
|
||||||
KeycloakAccount account = new KeycloakAccount() {
|
OidcKeycloakAccount account = new OidcKeycloakAccount() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Principal getPrincipal() {
|
public Principal getPrincipal() {
|
||||||
|
@ -79,7 +76,7 @@ public class CatalinaRequestAuthenticator extends RequestAuthenticator {
|
||||||
if (log.isLoggable(Level.FINE)) {
|
if (log.isLoggable(Level.FINE)) {
|
||||||
log.fine("Completing bearer authentication. Bearer roles: " + roles);
|
log.fine("Completing bearer authentication. Bearer roles: " + roles);
|
||||||
}
|
}
|
||||||
Principal generalPrincipal = principalFactory.createPrincipal(request.getContext().getRealm(), principal, roles, securityContext);
|
Principal generalPrincipal = principalFactory.createPrincipal(request.getContext().getRealm(), principal, roles);
|
||||||
request.setUserPrincipal(generalPrincipal);
|
request.setUserPrincipal(generalPrincipal);
|
||||||
request.setAuthType(method);
|
request.setAuthType(method);
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
||||||
|
|
|
@ -5,12 +5,11 @@ import org.apache.catalina.connector.Request;
|
||||||
import org.apache.catalina.realm.GenericPrincipal;
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -69,7 +68,7 @@ public class CatalinaSessionTokenStore extends CatalinaAdapterSessionStore imple
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void cleanSession(Session catalinaSession) {
|
protected void cleanSession(Session catalinaSession) {
|
||||||
catalinaSession.getSession().removeAttribute(KeycloakAccount.class.getName());
|
catalinaSession.getSession().removeAttribute(OidcKeycloakAccount.class.getName());
|
||||||
catalinaSession.setPrincipal(null);
|
catalinaSession.setPrincipal(null);
|
||||||
catalinaSession.setAuthType(null);
|
catalinaSession.setAuthType(null);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +97,7 @@ public class CatalinaSessionTokenStore extends CatalinaAdapterSessionStore imple
|
||||||
GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
|
GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
|
||||||
// in clustered environment in JBossWeb, principal is not serialized or saved
|
// in clustered environment in JBossWeb, principal is not serialized or saved
|
||||||
if (principal == null) {
|
if (principal == null) {
|
||||||
principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), account.getRoles(), securityContext);
|
principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), account.getRoles());
|
||||||
session.setPrincipal(principal);
|
session.setPrincipal(principal);
|
||||||
session.setAuthType("KEYCLOAK");
|
session.setAuthType("KEYCLOAK");
|
||||||
|
|
||||||
|
@ -110,7 +109,7 @@ public class CatalinaSessionTokenStore extends CatalinaAdapterSessionStore imple
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SerializableKeycloakAccount implements KeycloakAccount, Serializable {
|
public static class SerializableKeycloakAccount implements OidcKeycloakAccount, Serializable {
|
||||||
protected Set<String> roles;
|
protected Set<String> roles;
|
||||||
protected Principal principal;
|
protected Principal principal;
|
||||||
protected RefreshableKeycloakSecurityContext securityContext;
|
protected RefreshableKeycloakSecurityContext securityContext;
|
||||||
|
@ -138,10 +137,10 @@ public class CatalinaSessionTokenStore extends CatalinaAdapterSessionStore imple
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
|
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) account.getKeycloakSecurityContext();
|
||||||
Set<String> roles = account.getRoles();
|
Set<String> roles = account.getRoles();
|
||||||
GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), roles, securityContext);
|
GenericPrincipal principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), roles);
|
||||||
|
|
||||||
SerializableKeycloakAccount sAccount = new SerializableKeycloakAccount(roles, account.getPrincipal(), securityContext);
|
SerializableKeycloakAccount sAccount = new SerializableKeycloakAccount(roles, account.getPrincipal(), securityContext);
|
||||||
Session session = request.getSessionInternal(true);
|
Session session = request.getSessionInternal(true);
|
||||||
|
|
|
@ -21,9 +21,8 @@ import org.jboss.logging.Logger;
|
||||||
import org.keycloak.KeycloakPrincipal;
|
import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.AdapterUtils;
|
import org.keycloak.adapters.AdapterUtils;
|
||||||
import org.keycloak.adapters.HttpFacade;
|
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -34,7 +33,7 @@ import java.util.Set;
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class KeycloakUndertowAccount implements Account, Serializable, KeycloakAccount {
|
public class KeycloakUndertowAccount implements Account, Serializable, OidcKeycloakAccount {
|
||||||
protected static Logger log = Logger.getLogger(KeycloakUndertowAccount.class);
|
protected static Logger log = Logger.getLogger(KeycloakUndertowAccount.class);
|
||||||
protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
|
protected KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal;
|
||||||
protected Set<String> accountRoles;
|
protected Set<String> accountRoles;
|
||||||
|
|
|
@ -9,8 +9,8 @@ import io.undertow.servlet.handlers.ServletRequestContext;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ public class ServletSessionTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
|
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
|
||||||
HttpSession session = getSession(true);
|
HttpSession session = getSession(true);
|
||||||
session.setAttribute(KeycloakUndertowAccount.class.getName(), account);
|
session.setAttribute(KeycloakUndertowAccount.class.getName(), account);
|
||||||
|
|
|
@ -6,8 +6,8 @@ import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.CookieTokenStore;
|
import org.keycloak.adapters.CookieTokenStore;
|
||||||
import org.keycloak.adapters.HttpFacade;
|
import org.keycloak.adapters.HttpFacade;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class UndertowCookieTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
RefreshableKeycloakSecurityContext secContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
RefreshableKeycloakSecurityContext secContext = (RefreshableKeycloakSecurityContext)account.getKeycloakSecurityContext();
|
||||||
CookieTokenStore.setTokenCookie(deployment, facade, secContext);
|
CookieTokenStore.setTokenCookie(deployment, facade, secContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import io.undertow.server.session.Session;
|
||||||
import io.undertow.util.Sessions;
|
import io.undertow.util.Sessions;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.KeycloakAccount;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public class UndertowSessionTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveAccountInfo(KeycloakAccount account) {
|
public void saveAccountInfo(OidcKeycloakAccount account) {
|
||||||
Session session = Sessions.getOrCreateSession(exchange);
|
Session session = Sessions.getOrCreateSession(exchange);
|
||||||
session.setAttribute(KeycloakUndertowAccount.class.getName(), account);
|
session.setAttribute(KeycloakUndertowAccount.class.getName(), account);
|
||||||
sessionManagement.login(session.getSessionManager());
|
sessionManagement.login(session.getSessionManager());
|
||||||
|
|
15
pom.xml
15
pom.xml
|
@ -774,6 +774,11 @@
|
||||||
<artifactId>keycloak-as7-adapter</artifactId>
|
<artifactId>keycloak-as7-adapter</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-as7-adapter-spi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-installed-adapter</artifactId>
|
<artifactId>keycloak-installed-adapter</artifactId>
|
||||||
|
@ -879,6 +884,11 @@
|
||||||
<artifactId>keycloak-tomcat6-adapter</artifactId>
|
<artifactId>keycloak-tomcat6-adapter</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat6-saml-adapter</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-tomcat7-adapter</artifactId>
|
<artifactId>keycloak-tomcat7-adapter</artifactId>
|
||||||
|
@ -979,6 +989,11 @@
|
||||||
<artifactId>keycloak-saml-adapter-core</artifactId>
|
<artifactId>keycloak-saml-adapter-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat-core-saml-adapter</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-undertow-saml-adapter</artifactId>
|
<artifactId>keycloak-undertow-saml-adapter</artifactId>
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class InitiateLogin implements AuthChallenge {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean errorPage() {
|
public boolean errorPage() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -104,14 +104,9 @@ public abstract class SamlAuthenticator {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SamlUtil.sendSaml(true, facade, deployment.getIDP().getSingleLogoutService().getRequestBindingUrl(), binding, logoutBuilder.buildDocument(), deployment.getIDP().getSingleLogoutService().getRequestBinding());
|
SamlUtil.sendSaml(true, facade, deployment.getIDP().getSingleLogoutService().getRequestBindingUrl(), binding, logoutBuilder.buildDocument(), deployment.getIDP().getSingleLogoutService().getRequestBinding());
|
||||||
} catch (ProcessingException e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
log.error("Could not send global logout SAML request", e);
|
||||||
} catch (ConfigurationException e) {
|
return AuthOutcome.FAILED;
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (ParsingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
return AuthOutcome.NOT_ATTEMPTED;
|
return AuthOutcome.NOT_ATTEMPTED;
|
||||||
}
|
}
|
||||||
|
@ -134,18 +129,24 @@ public abstract class SamlAuthenticator {
|
||||||
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
|
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
|
||||||
if (!requestUri.equals(requestAbstractType.getDestination().toString())) {
|
if (!requestUri.equals(requestAbstractType.getDestination().toString())) {
|
||||||
log.error("expected destination '" + requestUri + "' got '" + requestAbstractType.getDestination() + "'");
|
log.error("expected destination '" + requestUri + "' got '" + requestAbstractType.getDestination() + "'");
|
||||||
throw new RuntimeException("destination not equal to request.");
|
return AuthOutcome.FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestAbstractType instanceof LogoutRequestType) {
|
if (requestAbstractType instanceof LogoutRequestType) {
|
||||||
if (deployment.getIDP().getSingleLogoutService().validateRequestSignature()) {
|
if (deployment.getIDP().getSingleLogoutService().validateRequestSignature()) {
|
||||||
|
try {
|
||||||
validateSamlSignature(holder, postBinding, GeneralConstants.SAML_REQUEST_KEY);
|
validateSamlSignature(holder, postBinding, GeneralConstants.SAML_REQUEST_KEY);
|
||||||
|
} catch (VerificationException e) {
|
||||||
|
log.error("Failed to verify saml request signature", e);
|
||||||
|
return AuthOutcome.FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
|
LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
|
||||||
return logoutRequest(logout, relayState);
|
return logoutRequest(logout, relayState);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("unknown SAML request type");
|
log.error("unknown SAML request type");
|
||||||
|
return AuthOutcome.FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,12 +174,9 @@ public abstract class SamlAuthenticator {
|
||||||
try {
|
try {
|
||||||
SamlUtil.sendSaml(false, facade, deployment.getIDP().getSingleLogoutService().getResponseBindingUrl(), binding, builder.buildDocument(),
|
SamlUtil.sendSaml(false, facade, deployment.getIDP().getSingleLogoutService().getResponseBindingUrl(), binding, builder.buildDocument(),
|
||||||
deployment.getIDP().getSingleLogoutService().getResponseBinding());
|
deployment.getIDP().getSingleLogoutService().getResponseBinding());
|
||||||
} catch (ConfigurationException e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
log.error("Could not send logout response SAML request", e);
|
||||||
} catch (ProcessingException e) {
|
return AuthOutcome.FAILED;
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
return AuthOutcome.NOT_ATTEMPTED;
|
return AuthOutcome.NOT_ATTEMPTED;
|
||||||
|
|
||||||
|
@ -202,17 +200,28 @@ public abstract class SamlAuthenticator {
|
||||||
StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
|
StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
|
||||||
// validate destination
|
// validate destination
|
||||||
if (!requestUri.equals(statusResponse.getDestination())) {
|
if (!requestUri.equals(statusResponse.getDestination())) {
|
||||||
throw new RuntimeException("destination not equal to request");
|
log.error("Request URI does not match SAML request destination");
|
||||||
|
return AuthOutcome.FAILED;
|
||||||
}
|
}
|
||||||
if (statusResponse instanceof ResponseType) {
|
if (statusResponse instanceof ResponseType) {
|
||||||
if (deployment.getIDP().getSingleSignOnService().validateResponseSignature()) {
|
if (deployment.getIDP().getSingleSignOnService().validateResponseSignature()) {
|
||||||
|
try {
|
||||||
validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
|
validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
|
||||||
|
} catch (VerificationException e) {
|
||||||
|
log.error("Failed to verify saml response signature", e);
|
||||||
|
return AuthOutcome.FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return handleLoginResponse((ResponseType)statusResponse);
|
return handleLoginResponse((ResponseType)statusResponse);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (deployment.getIDP().getSingleLogoutService().validateResponseSignature()) {
|
if (deployment.getIDP().getSingleLogoutService().validateResponseSignature()) {
|
||||||
|
try {
|
||||||
validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
|
validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
|
||||||
|
} catch (VerificationException e) {
|
||||||
|
log.error("Failed to verify saml response signature", e);
|
||||||
|
return AuthOutcome.FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// todo need to check that it is actually a LogoutResponse
|
// todo need to check that it is actually a LogoutResponse
|
||||||
return handleLogoutResponse(holder, statusResponse, relayState);
|
return handleLogoutResponse(holder, statusResponse, relayState);
|
||||||
|
@ -220,17 +229,12 @@ public abstract class SamlAuthenticator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateSamlSignature(SAMLDocumentHolder holder, boolean postBinding, String paramKey) {
|
private void validateSamlSignature(SAMLDocumentHolder holder, boolean postBinding, String paramKey) throws VerificationException {
|
||||||
try {
|
|
||||||
if (postBinding) {
|
if (postBinding) {
|
||||||
verifyPostBindingSignature(holder.getSamlDocument(), deployment.getIDP().getSignatureValidationKey());
|
verifyPostBindingSignature(holder.getSamlDocument(), deployment.getIDP().getSignatureValidationKey());
|
||||||
} else {
|
} else {
|
||||||
verifyRedirectBindingSignature(deployment.getIDP().getSignatureValidationKey(), paramKey);
|
verifyRedirectBindingSignature(deployment.getIDP().getSignatureValidationKey(), paramKey);
|
||||||
}
|
}
|
||||||
} catch (VerificationException e) {
|
|
||||||
log.error("validation failed", e);
|
|
||||||
throw new RuntimeException("invalid document signature");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AuthOutcome handleLoginResponse(ResponseType responseType) {
|
protected AuthOutcome handleLoginResponse(ResponseType responseType) {
|
||||||
|
@ -240,12 +244,9 @@ public abstract class SamlAuthenticator {
|
||||||
if (AssertionUtil.hasExpired(assertion)) {
|
if (AssertionUtil.hasExpired(assertion)) {
|
||||||
return initiateLogin();
|
return initiateLogin();
|
||||||
}
|
}
|
||||||
} catch (ParsingException e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
log.error("Error extracting SAML assertion, e");
|
||||||
} catch (ProcessingException e) {
|
return AuthOutcome.FAILED;
|
||||||
throw new RuntimeException(e);
|
|
||||||
} catch (ConfigurationException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SubjectType subject = assertion.getSubject();
|
SubjectType subject = assertion.getSubject();
|
||||||
|
@ -269,6 +270,7 @@ public abstract class SamlAuthenticator {
|
||||||
if (attributeValues != null) {
|
if (attributeValues != null) {
|
||||||
for (Object attrValue : attributeValues) {
|
for (Object attrValue : attributeValues) {
|
||||||
String role = getAttributeValue(attrValue);
|
String role = getAttributeValue(attrValue);
|
||||||
|
log.info("Add role: " + role);
|
||||||
roles.add(role);
|
roles.add(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,22 +316,7 @@ public abstract class SamlAuthenticator {
|
||||||
final SamlPrincipal principal = new SamlPrincipal(principalName, principalName, subjectNameID.getFormat().toString(), attributes, friendlyAttributes);
|
final SamlPrincipal principal = new SamlPrincipal(principalName, principalName, subjectNameID.getFormat().toString(), attributes, friendlyAttributes);
|
||||||
String index = authn == null ? null : authn.getSessionIndex();
|
String index = authn == null ? null : authn.getSessionIndex();
|
||||||
final String sessionIndex = index;
|
final String sessionIndex = index;
|
||||||
SamlSession account = new SamlSession() {
|
SamlSession account = new SamlSession(principal, roles, sessionIndex);
|
||||||
@Override
|
|
||||||
public SamlPrincipal getPrincipal() {
|
|
||||||
return principal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getRoles() {
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSessionIndex() {
|
|
||||||
return sessionIndex;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
sessionStore.saveAccount(account);
|
sessionStore.saveAccount(account);
|
||||||
completeAuthentication(account);
|
completeAuthentication(account);
|
||||||
|
|
||||||
|
@ -343,7 +330,7 @@ public abstract class SamlAuthenticator {
|
||||||
} else {
|
} else {
|
||||||
log.debug("IDP initiated invocation");
|
log.debug("IDP initiated invocation");
|
||||||
}
|
}
|
||||||
|
log.debug("AUTHENTICATED authn");
|
||||||
|
|
||||||
return AuthOutcome.AUTHENTICATED;
|
return AuthOutcome.AUTHENTICATED;
|
||||||
}
|
}
|
||||||
|
@ -351,7 +338,7 @@ public abstract class SamlAuthenticator {
|
||||||
protected abstract void completeAuthentication(SamlSession account);
|
protected abstract void completeAuthentication(SamlSession account);
|
||||||
|
|
||||||
private String getAttributeValue(Object attrValue) {
|
private String getAttributeValue(Object attrValue) {
|
||||||
String value;
|
String value = null;
|
||||||
if (attrValue instanceof String) {
|
if (attrValue instanceof String) {
|
||||||
value = (String)attrValue;
|
value = (String)attrValue;
|
||||||
} else if (attrValue instanceof Node) {
|
} else if (attrValue instanceof Node) {
|
||||||
|
@ -360,8 +347,9 @@ public abstract class SamlAuthenticator {
|
||||||
} else if (attrValue instanceof NameIDType) {
|
} else if (attrValue instanceof NameIDType) {
|
||||||
NameIDType nameIdType = (NameIDType) attrValue;
|
NameIDType nameIdType = (NameIDType) attrValue;
|
||||||
value = nameIdType.getValue();
|
value = nameIdType.getValue();
|
||||||
} else
|
} else {
|
||||||
throw new RuntimeException("Unknown attribute value type: " + attrValue.getClass().getName());
|
log.warn("Unable to extract unknown SAML assertion attribute value type: " + attrValue.getClass().getName());
|
||||||
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,29 @@ import java.util.Set;
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface SamlSession extends Serializable {
|
public class SamlSession implements Serializable {
|
||||||
SamlPrincipal getPrincipal();
|
private SamlPrincipal principal;
|
||||||
Set<String> getRoles();
|
private Set<String> roles;
|
||||||
String getSessionIndex();
|
private String sessionIndex;
|
||||||
|
|
||||||
|
public SamlSession() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SamlSession(SamlPrincipal principal, Set<String> roles, String sessionIndex) {
|
||||||
|
this.principal = principal;
|
||||||
|
this.roles = roles;
|
||||||
|
this.sessionIndex = sessionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SamlPrincipal getPrincipal() {
|
||||||
|
return principal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getRoles() {
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSessionIndex() {
|
||||||
|
return sessionIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>undertow</module>
|
<module>undertow</module>
|
||||||
|
<module>tomcat</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
22
saml/client-adapter/tomcat/pom.xml
Executable file
22
saml/client-adapter/tomcat/pom.xml
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
<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 Tomcat Integration</name>
|
||||||
|
<description/>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>keycloak-tomcat-saml-integration-pom</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>tomcat-core</module>
|
||||||
|
<module>tomcat6</module>
|
||||||
|
<module>tomcat7</module>
|
||||||
|
<module>tomcat8</module>
|
||||||
|
</modules>
|
||||||
|
</project>
|
93
saml/client-adapter/tomcat/tomcat-core/pom.xml
Executable file
93
saml/client-adapter/tomcat/tomcat-core/pom.xml
Executable file
|
@ -0,0 +1,93 @@
|
||||||
|
<?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>
|
||||||
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>keycloak-tomcat-core-saml-adapter</artifactId>
|
||||||
|
<name>Keycloak Tomcat Core SAML Integration</name>
|
||||||
|
<properties>
|
||||||
|
<!-- <tomcat.version>8.0.14</tomcat.version> -->
|
||||||
|
<!-- <tomcat.version>7.0.52</tomcat.version> -->
|
||||||
|
<tomcat.version>6.0.41</tomcat.version>
|
||||||
|
</properties>
|
||||||
|
<description />
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.logging</groupId>
|
||||||
|
<artifactId>jboss-logging</artifactId>
|
||||||
|
<version>${jboss.logging.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-adapter-spi</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.iharder</groupId>
|
||||||
|
<artifactId>base64</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</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.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>catalina</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,255 @@
|
||||||
|
package org.keycloak.adapters.saml;
|
||||||
|
|
||||||
|
import org.apache.catalina.Context;
|
||||||
|
import org.apache.catalina.Lifecycle;
|
||||||
|
import org.apache.catalina.LifecycleEvent;
|
||||||
|
import org.apache.catalina.LifecycleListener;
|
||||||
|
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||||
|
import org.apache.catalina.connector.Request;
|
||||||
|
import org.apache.catalina.connector.Response;
|
||||||
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
|
import org.keycloak.adapters.AuthChallenge;
|
||||||
|
import org.keycloak.adapters.AuthOutcome;
|
||||||
|
import org.keycloak.adapters.HttpFacade;
|
||||||
|
import org.keycloak.adapters.InMemorySessionIdMapper;
|
||||||
|
import org.keycloak.adapters.SessionIdMapper;
|
||||||
|
import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
|
||||||
|
import org.keycloak.adapters.saml.config.parsers.ResourceLoader;
|
||||||
|
import org.keycloak.adapters.tomcat.CatalinaHttpFacade;
|
||||||
|
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
|
||||||
|
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||||
|
import org.keycloak.constants.AdapterConstants;
|
||||||
|
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||||
|
|
||||||
|
import javax.servlet.RequestDispatcher;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keycloak authentication valve
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:ungarida@gmail.com">Davide Ungari</a>
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator implements LifecycleListener {
|
||||||
|
|
||||||
|
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
|
||||||
|
|
||||||
|
private final static Logger log = Logger.getLogger(""+AbstractSamlAuthenticatorValve.class);
|
||||||
|
protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
|
||||||
|
protected SamlDeploymentContext deploymentContext;
|
||||||
|
protected SessionIdMapper mapper = new InMemorySessionIdMapper();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void lifecycleEvent(LifecycleEvent event) {
|
||||||
|
if (Lifecycle.START_EVENT.equals(event.getType())) {
|
||||||
|
cache = false;
|
||||||
|
} else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
|
||||||
|
keycloakInit();
|
||||||
|
} else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
|
||||||
|
beforeStop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logoutInternal(Request request) {
|
||||||
|
KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||||
|
if (ksc != null) {
|
||||||
|
CatalinaHttpFacade facade = new CatalinaHttpFacade(null, request);
|
||||||
|
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||||
|
SamlSessionStore tokenStore = getTokenStore(request, facade, deployment);
|
||||||
|
tokenStore.logoutAccount();
|
||||||
|
}
|
||||||
|
request.setUserPrincipal(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UseSpecificCatch")
|
||||||
|
public void keycloakInit() {
|
||||||
|
// Possible scenarios:
|
||||||
|
// 1) The deployment has a keycloak.config.resolver specified and it exists:
|
||||||
|
// Outcome: adapter uses the resolver
|
||||||
|
// 2) The deployment has a keycloak.config.resolver and isn't valid (doesn't exists, isn't a resolver, ...) :
|
||||||
|
// Outcome: adapter is left unconfigured
|
||||||
|
// 3) The deployment doesn't have a keycloak.config.resolver , but has a keycloak.json (or equivalent)
|
||||||
|
// Outcome: adapter uses it
|
||||||
|
// 4) The deployment doesn't have a keycloak.config.resolver nor keycloak.json (or equivalent)
|
||||||
|
// Outcome: adapter is left unconfigured
|
||||||
|
|
||||||
|
String configResolverClass = context.getServletContext().getInitParameter("keycloak.config.resolver");
|
||||||
|
if (configResolverClass != null) {
|
||||||
|
try {
|
||||||
|
throw new RuntimeException("Not implemented yet");
|
||||||
|
//KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
|
||||||
|
//deploymentContext = new SamlDeploymentContext(configResolver);
|
||||||
|
//log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
|
||||||
|
//deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
InputStream is = getConfigInputStream(context);
|
||||||
|
final SamlDeployment deployment;
|
||||||
|
if (is == null) {
|
||||||
|
log.info("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
|
||||||
|
deployment = new DefaultSamlDeployment();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
ResourceLoader loader = new ResourceLoader() {
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceAsStream(String resource) {
|
||||||
|
return context.getServletContext().getResourceAsStream(resource);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
deployment = new DeploymentBuilder().build(is, loader);
|
||||||
|
} catch (ParsingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deploymentContext = new SamlDeploymentContext(deployment);
|
||||||
|
log.fine("Keycloak is using a per-deployment configuration.");
|
||||||
|
}
|
||||||
|
|
||||||
|
context.getServletContext().setAttribute(SamlDeploymentContext.class.getName(), deploymentContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void beforeStop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream getConfigFromServletContext(ServletContext servletContext) {
|
||||||
|
String xml = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||||
|
if (xml == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
log.finest("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||||
|
log.finest(xml);
|
||||||
|
return new ByteArrayInputStream(xml.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream getConfigInputStream(Context context) {
|
||||||
|
InputStream is = getConfigFromServletContext(context.getServletContext());
|
||||||
|
if (is == null) {
|
||||||
|
String path = context.getServletContext().getInitParameter("keycloak.config.file");
|
||||||
|
if (path == null) {
|
||||||
|
log.fine("**** using /WEB-INF/keycloak-saml.xml");
|
||||||
|
is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak-saml.xml");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
is = new FileInputStream(path);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
log.log(Level.SEVERE, "NOT FOUND {0}", path);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||||
|
log.fine("*********************** SAML ************");
|
||||||
|
try {
|
||||||
|
super.invoke(request, response);
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract GenericPrincipalFactory createPrincipalFactory();
|
||||||
|
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
|
||||||
|
protected void forwardToLogoutPage(Request request, HttpServletResponse response,SamlDeployment deployment) {
|
||||||
|
RequestDispatcher disp = request.getRequestDispatcher(deployment.getLogoutPage());
|
||||||
|
//make sure the login page is never cached
|
||||||
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
|
response.setHeader("Pragma", "no-cache");
|
||||||
|
response.setHeader("Expires", "0");
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
disp.forward(request, response);
|
||||||
|
} catch (ServletException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||||
|
log.info("authenticateInternal");
|
||||||
|
CatalinaHttpFacade facade = new CatalinaHttpFacade(response, request);
|
||||||
|
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||||
|
if (deployment == null || !deployment.isConfigured()) {
|
||||||
|
log.fine("deployment not configured");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SamlSessionStore tokenStore = getTokenStore(request, facade, deployment);
|
||||||
|
|
||||||
|
|
||||||
|
CatalinaSamlAuthenticator authenticator = new CatalinaSamlAuthenticator(facade, deployment, tokenStore);
|
||||||
|
AuthOutcome outcome = authenticator.authenticate();
|
||||||
|
if (outcome == AuthOutcome.AUTHENTICATED) {
|
||||||
|
log.fine("AUTHENTICATED");
|
||||||
|
if (facade.isEnded()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (outcome == AuthOutcome.LOGGED_OUT) {
|
||||||
|
logoutInternal(request);
|
||||||
|
if (deployment.getLogoutPage() != null) {
|
||||||
|
forwardToLogoutPage(request, response, deployment);
|
||||||
|
|
||||||
|
}
|
||||||
|
log.fine("Logging OUT");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthChallenge challenge = authenticator.getChallenge();
|
||||||
|
if (challenge != null) {
|
||||||
|
log.fine("challenge");
|
||||||
|
if (loginConfig == null) {
|
||||||
|
loginConfig = request.getContext().getLoginConfig();
|
||||||
|
}
|
||||||
|
if (challenge.errorPage()) {
|
||||||
|
log.fine("error page");
|
||||||
|
if (forwardToErrorPageInternal(request, response, loginConfig))return false;
|
||||||
|
}
|
||||||
|
log.fine("sending challenge");
|
||||||
|
challenge.challenge(facade);
|
||||||
|
}
|
||||||
|
log.fine("No challenge, but failed authentication");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keycloakSaveRequest(Request request) throws IOException {
|
||||||
|
saveRequest(request, request.getSessionInternal(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean keycloakRestoreRequest(Request request) {
|
||||||
|
try {
|
||||||
|
return restoreRequest(request, request.getSessionInternal());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SamlSessionStore getTokenStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
|
||||||
|
SamlSessionStore store = (SamlSessionStore)request.getNote(TOKEN_STORE_NOTE);
|
||||||
|
if (store != null) {
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
store = new CatalinaSamlSessionStore(userSessionManagement, createPrincipalFactory(), mapper, request, this, facade);
|
||||||
|
|
||||||
|
request.setNote(TOKEN_STORE_NOTE, store);
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.keycloak.adapters.saml;
|
||||||
|
|
||||||
|
import org.keycloak.adapters.HttpFacade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class CatalinaSamlAuthenticator extends SamlAuthenticator {
|
||||||
|
public CatalinaSamlAuthenticator(HttpFacade facade, SamlDeployment deployment, SamlSessionStore sessionStore) {
|
||||||
|
super(facade, deployment, sessionStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void completeAuthentication(SamlSession account) {
|
||||||
|
// complete
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
package org.keycloak.adapters.saml;
|
||||||
|
|
||||||
|
import org.apache.catalina.Manager;
|
||||||
|
import org.apache.catalina.Session;
|
||||||
|
import org.apache.catalina.connector.Request;
|
||||||
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.adapters.HttpFacade;
|
||||||
|
import org.keycloak.adapters.SessionIdMapper;
|
||||||
|
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
|
||||||
|
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||||
|
import org.keycloak.util.KeycloakUriBuilder;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||||
|
protected static Logger log = Logger.getLogger(SamlSessionStore.class);
|
||||||
|
public static final String SAML_REDIRECT_URI = "SAML_REDIRECT_URI";
|
||||||
|
|
||||||
|
private final CatalinaUserSessionManagement sessionManagement;
|
||||||
|
protected final GenericPrincipalFactory principalFactory;
|
||||||
|
private final SessionIdMapper idMapper;
|
||||||
|
protected final Request request;
|
||||||
|
protected final AbstractSamlAuthenticatorValve valve;
|
||||||
|
protected final HttpFacade facade;
|
||||||
|
|
||||||
|
public CatalinaSamlSessionStore(CatalinaUserSessionManagement sessionManagement, GenericPrincipalFactory principalFactory,
|
||||||
|
SessionIdMapper idMapper, Request request, AbstractSamlAuthenticatorValve valve, HttpFacade facade) {
|
||||||
|
this.sessionManagement = sessionManagement;
|
||||||
|
this.principalFactory = principalFactory;
|
||||||
|
this.idMapper = idMapper;
|
||||||
|
this.request = request;
|
||||||
|
this.valve = valve;
|
||||||
|
this.facade = facade;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logoutAccount() {
|
||||||
|
Session sessionInternal = request.getSessionInternal(false);
|
||||||
|
if (sessionInternal == null) return;
|
||||||
|
HttpSession session = sessionInternal.getSession();
|
||||||
|
if (session != null) {
|
||||||
|
SamlSession samlSession = (SamlSession)session.getAttribute(SamlSession.class.getName());
|
||||||
|
if (samlSession != null) {
|
||||||
|
if (samlSession.getSessionIndex() != null) {
|
||||||
|
idMapper.removeSession(session.getId());
|
||||||
|
}
|
||||||
|
session.removeAttribute(SamlSession.class.getName());
|
||||||
|
}
|
||||||
|
session.removeAttribute(SAML_REDIRECT_URI);
|
||||||
|
}
|
||||||
|
sessionInternal.setPrincipal(null);
|
||||||
|
sessionInternal.setAuthType(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logoutByPrincipal(String principal) {
|
||||||
|
Set<String> sessions = idMapper.getUserSessions(principal);
|
||||||
|
if (sessions != null) {
|
||||||
|
List<String> ids = new LinkedList<String>();
|
||||||
|
ids.addAll(sessions);
|
||||||
|
logoutSessionIds(ids);
|
||||||
|
for (String id : ids) {
|
||||||
|
idMapper.removeSession(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logoutBySsoId(List<String> ssoIds) {
|
||||||
|
if (ssoIds == null) return;
|
||||||
|
List<String> sessionIds = new LinkedList<String>();
|
||||||
|
for (String id : ssoIds) {
|
||||||
|
String sessionId = idMapper.getSessionFromSSO(id);
|
||||||
|
if (sessionId != null) {
|
||||||
|
sessionIds.add(sessionId);
|
||||||
|
idMapper.removeSession(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
logoutSessionIds(sessionIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void logoutSessionIds(List<String> sessionIds) {
|
||||||
|
if (sessionIds == null || sessionIds.isEmpty()) return;
|
||||||
|
Manager sessionManager = request.getContext().getManager();
|
||||||
|
sessionManagement.logoutHttpSessions(sessionManager, sessionIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoggedIn() {
|
||||||
|
Session session = request.getSessionInternal(false);
|
||||||
|
if (session == null) return false;
|
||||||
|
if (session == null) {
|
||||||
|
log.debug("session was null, returning null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final SamlSession samlSession = (SamlSession)session.getSession().getAttribute(SamlSession.class.getName());
|
||||||
|
if (samlSession == null) {
|
||||||
|
log.debug("SamlSession was not in session, returning null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
|
||||||
|
if (samlSession.getPrincipal().getName().equals(principal.getName()))
|
||||||
|
// in clustered environment in JBossWeb, principal is not serialized or saved
|
||||||
|
if (principal == null) {
|
||||||
|
principal = principalFactory.createPrincipal(request.getContext().getRealm(), samlSession.getPrincipal(), samlSession.getRoles());
|
||||||
|
session.setPrincipal(principal);
|
||||||
|
session.setAuthType("KEYCLOAK-SAML");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (!principal.getUserPrincipal().getName().equals(samlSession.getPrincipal().getName())) {
|
||||||
|
throw new RuntimeException("Unknown State");
|
||||||
|
}
|
||||||
|
log.debug("************principal already in");
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
for (String role : principal.getRoles()) {
|
||||||
|
log.debug("principal role: " + role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
request.setUserPrincipal(principal);
|
||||||
|
request.setAuthType("KEYCLOAK-SAML");
|
||||||
|
restoreRequest();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveAccount(SamlSession account) {
|
||||||
|
Session session = request.getSessionInternal(true);
|
||||||
|
session.getSession().setAttribute(SamlSession.class.getName(), account);
|
||||||
|
GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
|
||||||
|
// in clustered environment in JBossWeb, principal is not serialized or saved
|
||||||
|
if (principal == null) {
|
||||||
|
principal = principalFactory.createPrincipal(request.getContext().getRealm(), account.getPrincipal(), account.getRoles());
|
||||||
|
session.setPrincipal(principal);
|
||||||
|
session.setAuthType("KEYCLOAK-SAML");
|
||||||
|
|
||||||
|
}
|
||||||
|
request.setUserPrincipal(principal);
|
||||||
|
request.setAuthType("KEYCLOAK-SAML");
|
||||||
|
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), session.getId());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SamlSession getAccount() {
|
||||||
|
HttpSession session = getSession(true);
|
||||||
|
return (SamlSession)session.getAttribute(SamlSession.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRedirectUri() {
|
||||||
|
return (String)getSession(true).getAttribute(SAML_REDIRECT_URI);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveRequest() {
|
||||||
|
try {
|
||||||
|
valve.keycloakSaveRequest(request);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSession(true).setAttribute(SAML_REDIRECT_URI, facade.getRequest().getURI());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean restoreRequest() {
|
||||||
|
getSession(true).removeAttribute(SAML_REDIRECT_URI);
|
||||||
|
return valve.keycloakRestoreRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HttpSession getSession(boolean create) {
|
||||||
|
Session session = request.getSessionInternal(create);
|
||||||
|
if (session == null) return null;
|
||||||
|
return session.getSession();
|
||||||
|
}
|
||||||
|
}
|
80
saml/client-adapter/tomcat/tomcat6/pom.xml
Executable file
80
saml/client-adapter/tomcat/tomcat6/pom.xml
Executable file
|
@ -0,0 +1,80 @@
|
||||||
|
<?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>
|
||||||
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>keycloak-tomcat6-saml-adapter</artifactId>
|
||||||
|
<name>Keycloak Tomcat 6 Saml Integration</name>
|
||||||
|
<properties>
|
||||||
|
<tomcat.version>6.0.41</tomcat.version>
|
||||||
|
</properties>
|
||||||
|
<description />
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.logging</groupId>
|
||||||
|
<artifactId>jboss-logging</artifactId>
|
||||||
|
<version>${jboss.logging.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat-core-saml-adapter</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.iharder</groupId>
|
||||||
|
<artifactId>base64</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>catalina</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.keycloak.adapters.saml.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.LifecycleException;
|
||||||
|
import org.apache.catalina.connector.Request;
|
||||||
|
import org.apache.catalina.connector.Response;
|
||||||
|
import org.apache.catalina.core.StandardContext;
|
||||||
|
import org.apache.catalina.deploy.LoginConfig;
|
||||||
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
|
import org.keycloak.adapters.saml.AbstractSamlAuthenticatorValve;
|
||||||
|
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keycloak authentication valve
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class SamlAuthenticatorValve extends AbstractSamlAuthenticatorValve {
|
||||||
|
@Override
|
||||||
|
public boolean authenticate(Request request, Response response, LoginConfig config) throws IOException {
|
||||||
|
return authenticateInternal(request, response, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||||
|
if (loginConfig == null) return false;
|
||||||
|
LoginConfig config = (LoginConfig)loginConfig;
|
||||||
|
if (config.getErrorPage() == null) return false;
|
||||||
|
forwardToErrorPage(request, (Response)response, config);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() throws LifecycleException {
|
||||||
|
StandardContext standardContext = (StandardContext) context;
|
||||||
|
standardContext.addLifecycleListener(this);
|
||||||
|
super.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logout(Request request) throws ServletException {
|
||||||
|
logoutInternal(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GenericPrincipalFactory createPrincipalFactory() {
|
||||||
|
return new GenericPrincipalFactory() {
|
||||||
|
@Override
|
||||||
|
protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
|
||||||
|
return new GenericPrincipal(null, userPrincipal.getName(), null, roles, userPrincipal, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
88
saml/client-adapter/tomcat/tomcat7/pom.xml
Executable file
88
saml/client-adapter/tomcat/tomcat7/pom.xml
Executable file
|
@ -0,0 +1,88 @@
|
||||||
|
<?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>
|
||||||
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>keycloak-tomcat7-saml-adapter</artifactId>
|
||||||
|
<name>Keycloak Tomcat 7 SAML Integration</name>
|
||||||
|
<properties>
|
||||||
|
<!--<tomcat.version>8.0.14</tomcat.version>-->
|
||||||
|
<tomcat.version>7.0.52</tomcat.version>
|
||||||
|
</properties>
|
||||||
|
<description />
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.logging</groupId>
|
||||||
|
<artifactId>jboss-logging</artifactId>
|
||||||
|
<version>${jboss.logging.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat-core-saml-adapter</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.iharder</groupId>
|
||||||
|
<artifactId>base64</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.keycloak.adapters.saml.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.connector.Request;
|
||||||
|
import org.apache.catalina.connector.Response;
|
||||||
|
import org.apache.catalina.core.StandardContext;
|
||||||
|
import org.apache.catalina.deploy.LoginConfig;
|
||||||
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
|
import org.keycloak.adapters.saml.AbstractSamlAuthenticatorValve;
|
||||||
|
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keycloak authentication valve
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class SamlAuthenticatorValve extends AbstractSamlAuthenticatorValve {
|
||||||
|
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
|
||||||
|
return authenticateInternal(request, response, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||||
|
if (loginConfig == null) return false;
|
||||||
|
LoginConfig config = (LoginConfig)loginConfig;
|
||||||
|
if (config.getErrorPage() == null) return false;
|
||||||
|
forwardToErrorPage(request, (Response)response, config);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void initInternal() {
|
||||||
|
StandardContext standardContext = (StandardContext) context;
|
||||||
|
standardContext.addLifecycleListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logout(Request request) throws ServletException {
|
||||||
|
logoutInternal(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GenericPrincipalFactory createPrincipalFactory() {
|
||||||
|
return new GenericPrincipalFactory() {
|
||||||
|
@Override
|
||||||
|
protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
|
||||||
|
return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
87
saml/client-adapter/tomcat/tomcat8/pom.xml
Executable file
87
saml/client-adapter/tomcat/tomcat8/pom.xml
Executable file
|
@ -0,0 +1,87 @@
|
||||||
|
<?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>
|
||||||
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>keycloak-tomcat8-saml-adapter</artifactId>
|
||||||
|
<name>Keycloak Tomcat 8 SAML Integration</name>
|
||||||
|
<properties>
|
||||||
|
<tomcat.version>8.0.14</tomcat.version>
|
||||||
|
</properties>
|
||||||
|
<description />
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.logging</groupId>
|
||||||
|
<artifactId>jboss-logging</artifactId>
|
||||||
|
<version>${jboss.logging.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
<version>${tomcat.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat-core-saml-adapter</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.iharder</groupId>
|
||||||
|
<artifactId>base64</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,71 @@
|
||||||
|
package org.keycloak.adapters.saml.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||||
|
import org.apache.catalina.connector.Request;
|
||||||
|
import org.apache.catalina.core.StandardContext;
|
||||||
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
|
import org.apache.tomcat.util.descriptor.web.LoginConfig;
|
||||||
|
import org.keycloak.adapters.saml.AbstractSamlAuthenticatorValve;
|
||||||
|
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keycloak authentication valve
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class SamlAuthenticatorValve extends AbstractSamlAuthenticatorValve {
|
||||||
|
public boolean authenticate(Request request, HttpServletResponse response) throws IOException {
|
||||||
|
return authenticateInternal(request, response, request.getContext().getLoginConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||||
|
if (loginConfig == null) return false;
|
||||||
|
LoginConfig config = (LoginConfig)loginConfig;
|
||||||
|
if (config.getErrorPage() == null) return false;
|
||||||
|
// had to do this to get around compiler/IDE issues :(
|
||||||
|
try {
|
||||||
|
Method method = null;
|
||||||
|
/*
|
||||||
|
for (Method m : getClass().getDeclaredMethods()) {
|
||||||
|
if (m.getName().equals("forwardToErrorPage")) {
|
||||||
|
method = m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
method = FormAuthenticator.class.getDeclaredMethod("forwardToErrorPage", Request.class, HttpServletResponse.class, LoginConfig.class);
|
||||||
|
method.setAccessible(true);
|
||||||
|
method.invoke(this, request, response, config);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initInternal() {
|
||||||
|
StandardContext standardContext = (StandardContext) context;
|
||||||
|
standardContext.addLifecycleListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logout(Request request) {
|
||||||
|
logoutInternal(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GenericPrincipalFactory createPrincipalFactory() {
|
||||||
|
return new GenericPrincipalFactory() {
|
||||||
|
@Override
|
||||||
|
protected GenericPrincipal createPrincipal(Principal userPrincipal, List<String> roles) {
|
||||||
|
return new GenericPrincipal(userPrincipal.getName(), null, roles, userPrincipal, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -174,6 +174,7 @@ public class SamlService {
|
||||||
|
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
event.event(EventType.LOGIN);
|
event.event(EventType.LOGIN);
|
||||||
|
event.client(issuer);
|
||||||
event.error(Errors.CLIENT_NOT_FOUND);
|
event.error(Errors.CLIENT_NOT_FOUND);
|
||||||
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
|
return ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
package org.keycloak.testsuite.keycloaksaml;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class SamlAdapterTest {
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static SamlKeycloakRule keycloakRule = new SamlKeycloakRule() {
|
||||||
|
@Override
|
||||||
|
public void initWars() {
|
||||||
|
ClassLoader classLoader = SamlAdapterTest.class.getClassLoader();
|
||||||
|
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/simple-post", "/sales-post", "post.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/signed-post", "/sales-post-sig", "post-sig.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/signed-post-email", "/sales-post-sig-email", "post-sig-email.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/signed-post-transient", "/sales-post-sig-transient", "post-sig-transient.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/signed-post-persistent", "/sales-post-sig-persistent", "post-sig-persistent.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/signed-metadata", "/sales-metadata", "post-metadata.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/signed-get", "/employee-sig", "employee-sig.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/mappers", "/employee2", "employee2.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/signed-front-get", "/employee-sig-front", "employee-sig-front.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/bad-client-signed-post", "/bad-client-sales-post-sig", "bad-client-post-sig.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/bad-realm-signed-post", "/bad-realm-sales-post-sig", "bad-realm-post-sig.war", classLoader);
|
||||||
|
initializeSamlSecuredWar("/keycloak-saml/encrypted-post", "/sales-post-enc", "post-enc.war", classLoader);
|
||||||
|
SamlAdapterTestStrategy.uploadSP("http://localhost:8081/auth", this);
|
||||||
|
server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRealmJson() {
|
||||||
|
return "/keycloak-saml/testsaml.json";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public SamlAdapterTestStrategy testStrategy = new SamlAdapterTestStrategy("http://localhost:8081/auth", "http://localhost:8081", keycloakRule);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostBadRealmSignature() {
|
||||||
|
testStrategy.testPostBadRealmSignature( new SamlAdapterTestStrategy.CheckAuthError() {
|
||||||
|
@Override
|
||||||
|
public void check(WebDriver driver) {
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("Forbidden"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSimpleUnauthorized() {
|
||||||
|
testStrategy.testPostSimpleUnauthorized( new SamlAdapterTestStrategy.CheckAuthError() {
|
||||||
|
@Override
|
||||||
|
public void check(WebDriver driver) {
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("Forbidden"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetadataPostSignedLoginLogout() throws Exception {
|
||||||
|
testStrategy.testMetadataPostSignedLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectSignedLoginLogout() {
|
||||||
|
testStrategy.testRedirectSignedLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogoutEmailNameID() {
|
||||||
|
testStrategy.testPostSignedLoginLogoutEmailNameID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostEncryptedLoginLogout() {
|
||||||
|
testStrategy.testPostEncryptedLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectSignedLoginLogoutFrontNoSSO() {
|
||||||
|
testStrategy.testRedirectSignedLoginLogoutFrontNoSSO();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSimpleLoginLogout() {
|
||||||
|
testStrategy.testPostSimpleLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogoutTransientNameID() {
|
||||||
|
testStrategy.testPostSignedLoginLogoutTransientNameID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSimpleLoginLogoutIdpInitiated() {
|
||||||
|
testStrategy.testPostSimpleLoginLogoutIdpInitiated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAttributes() throws Exception {
|
||||||
|
testStrategy.testAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogoutPersistentNameID() {
|
||||||
|
testStrategy.testPostSignedLoginLogoutPersistentNameID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRelayStateEncoding() throws Exception {
|
||||||
|
testStrategy.testRelayStateEncoding();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostBadClientSignature() {
|
||||||
|
testStrategy.testPostBadClientSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectSignedLoginLogoutFront() {
|
||||||
|
testStrategy.testRedirectSignedLoginLogoutFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogout() {
|
||||||
|
testStrategy.testPostSignedLoginLogout();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,409 @@
|
||||||
|
package org.keycloak.testsuite.keycloaksaml;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExternalResource;
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.adapters.saml.SamlPrincipal;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
|
import org.keycloak.models.Constants;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.protocol.oidc.TokenManager;
|
||||||
|
import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
|
||||||
|
import org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper;
|
||||||
|
import org.keycloak.protocol.saml.mappers.HardcodedRole;
|
||||||
|
import org.keycloak.protocol.saml.mappers.RoleListMapper;
|
||||||
|
import org.keycloak.protocol.saml.mappers.RoleNameMapper;
|
||||||
|
import org.keycloak.representations.AccessToken;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
|
||||||
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
import org.keycloak.services.resources.admin.AdminRoot;
|
||||||
|
import org.keycloak.testsuite.KeycloakServer;
|
||||||
|
import org.keycloak.testsuite.pages.LoginPage;
|
||||||
|
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||||
|
import org.keycloak.testsuite.rule.KeycloakRule;
|
||||||
|
import org.keycloak.testsuite.rule.WebResource;
|
||||||
|
import org.keycloak.testsuite.rule.WebRule;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
|
||||||
|
import javax.ws.rs.client.Client;
|
||||||
|
import javax.ws.rs.client.ClientBuilder;
|
||||||
|
import javax.ws.rs.client.ClientRequestContext;
|
||||||
|
import javax.ws.rs.client.ClientRequestFilter;
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
|
import javax.ws.rs.client.WebTarget;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class SamlAdapterTestStrategy extends ExternalResource {
|
||||||
|
protected String AUTH_SERVER_URL = "http://localhost:8081/auth";
|
||||||
|
protected String APP_SERVER_BASE_URL = "http://localhost:8081";
|
||||||
|
protected AbstractKeycloakRule keycloakRule;
|
||||||
|
|
||||||
|
public SamlAdapterTestStrategy(String AUTH_SERVER_URL, String APP_SERVER_BASE_URL, AbstractKeycloakRule keycloakRule) {
|
||||||
|
this.AUTH_SERVER_URL = AUTH_SERVER_URL;
|
||||||
|
this.APP_SERVER_BASE_URL = APP_SERVER_BASE_URL;
|
||||||
|
this.keycloakRule = keycloakRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebRule webRule = new WebRule(this);
|
||||||
|
|
||||||
|
|
||||||
|
@WebResource
|
||||||
|
protected WebDriver driver;
|
||||||
|
@WebResource
|
||||||
|
protected LoginPage loginPage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void before() throws Throwable {
|
||||||
|
super.before();
|
||||||
|
webRule.before();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void after() {
|
||||||
|
super.after();
|
||||||
|
webRule.after();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RealmModel baseAdapterTestInitialization(KeycloakSession session, RealmManager manager, RealmModel adminRealm, Class<?> clazz) {
|
||||||
|
RealmRepresentation representation = KeycloakServer.loadJson(clazz.getResourceAsStream("/keycloak-saml/testsaml.json"), RealmRepresentation.class);
|
||||||
|
RealmModel demoRealm = manager.importRealm(representation);
|
||||||
|
return demoRealm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected void checkLoggedOut(String mainUrl) {
|
||||||
|
String pageSource = driver.getPageSource();
|
||||||
|
System.out.println("*** logout pagesource ***");
|
||||||
|
System.out.println(pageSource);
|
||||||
|
System.out.println("driver url: " + driver.getCurrentUrl());
|
||||||
|
Assert.assertTrue(pageSource.contains("request-path: /logout.jsp"));
|
||||||
|
driver.navigate().to(mainUrl);
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPostSimpleLoginLogout() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
|
||||||
|
System.out.println(driver.getPageSource());
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPostSimpleUnauthorized(CheckAuthError error) {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("unauthorized", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
|
||||||
|
System.out.println(driver.getPageSource());
|
||||||
|
error.check(driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPostSimpleLoginLogoutIdpInitiated() {
|
||||||
|
driver.navigate().to(AUTH_SERVER_URL + "/realms/demo/protocol/saml/clients/sales-post");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post/");
|
||||||
|
System.out.println(driver.getPageSource());
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPostSignedLoginLogout() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig/");
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig/");
|
||||||
|
|
||||||
|
}
|
||||||
|
public void testPostSignedLoginLogoutTransientNameID() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
|
||||||
|
System.out.println(driver.getPageSource());
|
||||||
|
Assert.assertFalse(driver.getPageSource().contains("bburke"));
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-transient?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-transient/");
|
||||||
|
|
||||||
|
}
|
||||||
|
public void testPostSignedLoginLogoutPersistentNameID() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
|
||||||
|
System.out.println(driver.getPageSource());
|
||||||
|
Assert.assertFalse(driver.getPageSource().contains("bburke"));
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-persistent?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-persistent/");
|
||||||
|
|
||||||
|
}
|
||||||
|
public void testPostSignedLoginLogoutEmailNameID() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-email/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig-email/");
|
||||||
|
System.out.println(driver.getPageSource());
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig-email?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-sig-email/");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRelayStateEncoding() throws Exception {
|
||||||
|
// this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
|
||||||
|
// at the relay state
|
||||||
|
SamlSPFacade.samlResponse = null;
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee/");
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
System.out.println(driver.getCurrentUrl());
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee/");
|
||||||
|
Assert.assertEquals(SamlSPFacade.sentRelayState, SamlSPFacade.RELAY_STATE);
|
||||||
|
Assert.assertNotNull(SamlSPFacade.samlResponse);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAttributes() throws Exception {
|
||||||
|
{
|
||||||
|
SendUsernameServlet.sentPrincipal = null;
|
||||||
|
SendUsernameServlet.checkRoles = null;
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
List<String> requiredRoles = new LinkedList<>();
|
||||||
|
requiredRoles.add("manager");
|
||||||
|
requiredRoles.add("employee");
|
||||||
|
requiredRoles.add("user");
|
||||||
|
SendUsernameServlet.checkRoles = requiredRoles;
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee2/");
|
||||||
|
SendUsernameServlet.checkRoles = null;
|
||||||
|
SamlPrincipal principal = (SamlPrincipal) SendUsernameServlet.sentPrincipal;
|
||||||
|
Assert.assertNotNull(principal);
|
||||||
|
Assert.assertEquals("bburke@redhat.com", principal.getAttribute(X500SAMLProfileConstants.EMAIL.get()));
|
||||||
|
Assert.assertEquals("bburke@redhat.com", principal.getFriendlyAttribute("email"));
|
||||||
|
Assert.assertEquals("617", principal.getAttribute("phone"));
|
||||||
|
Assert.assertNull(principal.getFriendlyAttribute("phone"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/employee2/");
|
||||||
|
|
||||||
|
}
|
||||||
|
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
|
||||||
|
@Override
|
||||||
|
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||||
|
ClientModel app = appRealm.getClientByClientId(APP_SERVER_BASE_URL + "/employee2/");
|
||||||
|
for (ProtocolMapperModel mapper : app.getProtocolMappers()) {
|
||||||
|
if (mapper.getName().equals("role-list")) {
|
||||||
|
app.removeProtocolMapper(mapper);
|
||||||
|
mapper.setId(null);
|
||||||
|
mapper.getConfig().put(RoleListMapper.SINGLE_ROLE_ATTRIBUTE, "true");
|
||||||
|
mapper.getConfig().put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "memberOf");
|
||||||
|
app.addProtocolMapper(mapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
app.addProtocolMapper(HardcodedAttributeMapper.create("hardcoded-attribute", "hardcoded-attribute", "Basic", null, "hard", false, null));
|
||||||
|
app.addProtocolMapper(HardcodedRole.create("hardcoded-role", "hardcoded-role"));
|
||||||
|
app.addProtocolMapper(RoleNameMapper.create("renamed-role", "manager", "el-jefe"));
|
||||||
|
app.addProtocolMapper(RoleNameMapper.create("renamed-employee-role", APP_SERVER_BASE_URL + "/employee/.employee", "pee-on"));
|
||||||
|
}
|
||||||
|
}, "demo");
|
||||||
|
|
||||||
|
System.out.println(">>>>>>>>>> single role attribute <<<<<<<<");
|
||||||
|
|
||||||
|
{
|
||||||
|
SendUsernameServlet.sentPrincipal = null;
|
||||||
|
SendUsernameServlet.checkRoles = null;
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee2/");
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
List<String> requiredRoles = new LinkedList<>();
|
||||||
|
requiredRoles.add("el-jefe");
|
||||||
|
requiredRoles.add("user");
|
||||||
|
requiredRoles.add("hardcoded-role");
|
||||||
|
requiredRoles.add("pee-on");
|
||||||
|
SendUsernameServlet.checkRoles = requiredRoles;
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee2/");
|
||||||
|
SendUsernameServlet.checkRoles = null;
|
||||||
|
SamlPrincipal principal = (SamlPrincipal) SendUsernameServlet.sentPrincipal;
|
||||||
|
Assert.assertNotNull(principal);
|
||||||
|
Assert.assertEquals("hard", principal.getAttribute("hardcoded-attribute"));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRedirectSignedLoginLogout() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig/");
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRedirectSignedLoginLogoutFrontNoSSO() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig-front/");
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig-front/");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRedirectSignedLoginLogoutFront() {
|
||||||
|
// visit 1st app an logg in
|
||||||
|
System.out.println("visit 1st app ");
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig/");
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
System.out.println("login to form");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig/");
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
|
||||||
|
// visit 2nd app
|
||||||
|
System.out.println("visit 2nd app ");
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/employee-sig-front/");
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
|
||||||
|
// visit 3rd app
|
||||||
|
System.out.println("visit 3rd app ");
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-sig/");
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
|
||||||
|
// logout of first app
|
||||||
|
System.out.println("GLO");
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/employee-sig/");
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/employee-sig-front/");
|
||||||
|
String currentUrl = driver.getCurrentUrl();
|
||||||
|
Assert.assertTrue(currentUrl.startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-sig/");
|
||||||
|
Assert.assertTrue(driver.getCurrentUrl().startsWith(AUTH_SERVER_URL + "/realms/demo/protocol/saml"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPostEncryptedLoginLogout() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-enc/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-post-enc/");
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-post-enc?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-post-enc/");
|
||||||
|
|
||||||
|
}
|
||||||
|
public void testPostBadClientSignature() {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/bad-client-sales-post-sig/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
Assert.assertEquals(driver.getTitle(), "We're sorry...");
|
||||||
|
|
||||||
|
}
|
||||||
|
public static interface CheckAuthError {
|
||||||
|
void check(WebDriver driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPostBadRealmSignature(CheckAuthError error) {
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/bad-realm-sales-post-sig/");
|
||||||
|
System.out.println(driver.getPageSource());
|
||||||
|
error.check(driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createToken(String AUTH_SERVER_URL, AbstractKeycloakRule keycloakRule) {
|
||||||
|
KeycloakSession session = keycloakRule.startSession();
|
||||||
|
try {
|
||||||
|
RealmManager manager = new RealmManager(session);
|
||||||
|
|
||||||
|
RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
|
||||||
|
ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
|
||||||
|
TokenManager tm = new TokenManager();
|
||||||
|
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
||||||
|
ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
|
||||||
|
clientSession.setNote(OIDCLoginProtocol.ISSUER, AUTH_SERVER_URL + "/realms/master");
|
||||||
|
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false, null, null);
|
||||||
|
AccessToken token = tm.createClientAccessToken(session, tm.getAccess(null, true, adminConsole, admin), adminRealm, adminConsole, admin, userSession, clientSession);
|
||||||
|
return tm.encodeToken(adminRealm, token);
|
||||||
|
} finally {
|
||||||
|
keycloakRule.stopSession(session, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testMetadataPostSignedLoginLogout() throws Exception {
|
||||||
|
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-metadata/");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), AUTH_SERVER_URL + "/realms/demo/protocol/saml");
|
||||||
|
loginPage.login("bburke", "password");
|
||||||
|
Assert.assertEquals(driver.getCurrentUrl(), APP_SERVER_BASE_URL + "/sales-metadata/");
|
||||||
|
String pageSource = driver.getPageSource();
|
||||||
|
Assert.assertTrue(pageSource.contains("bburke"));
|
||||||
|
driver.navigate().to(APP_SERVER_BASE_URL + "/sales-metadata?GLO=true");
|
||||||
|
checkLoggedOut(APP_SERVER_BASE_URL + "/sales-metadata/");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void uploadSP(String AUTH_SERVER_URL, AbstractKeycloakRule keycloakRule) {
|
||||||
|
String token = createToken(AUTH_SERVER_URL, keycloakRule);
|
||||||
|
final String authHeader = "Bearer " + token;
|
||||||
|
ClientRequestFilter authFilter = new ClientRequestFilter() {
|
||||||
|
@Override
|
||||||
|
public void filter(ClientRequestContext requestContext) throws IOException {
|
||||||
|
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Client client = ClientBuilder.newBuilder().register(authFilter).build();
|
||||||
|
UriBuilder authBase = UriBuilder.fromUri(AUTH_SERVER_URL + "");
|
||||||
|
WebTarget adminRealms = client.target(AdminRoot.realmsUrl(authBase));
|
||||||
|
|
||||||
|
|
||||||
|
MultipartFormDataOutput formData = new MultipartFormDataOutput();
|
||||||
|
InputStream is = SamlAdapterTestStrategy.class.getResourceAsStream("/keycloak-saml/sp-metadata.xml");
|
||||||
|
Assert.assertNotNull(is);
|
||||||
|
formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
|
||||||
|
|
||||||
|
WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload");
|
||||||
|
System.out.println(upload.getUri());
|
||||||
|
Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA));
|
||||||
|
Assert.assertEquals(204, response.getStatus());
|
||||||
|
response.close();
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,450 +0,0 @@
|
||||||
package org.keycloak.testsuite.keycloaksaml;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.ClassRule;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.keycloak.Config;
|
|
||||||
import org.keycloak.adapters.saml.SamlPrincipal;
|
|
||||||
import org.keycloak.models.ClientModel;
|
|
||||||
import org.keycloak.models.ClientSessionModel;
|
|
||||||
import org.keycloak.models.Constants;
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.models.UserSessionModel;
|
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
|
||||||
import org.keycloak.protocol.oidc.TokenManager;
|
|
||||||
import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
|
|
||||||
import org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper;
|
|
||||||
import org.keycloak.protocol.saml.mappers.HardcodedRole;
|
|
||||||
import org.keycloak.protocol.saml.mappers.RoleListMapper;
|
|
||||||
import org.keycloak.protocol.saml.mappers.RoleNameMapper;
|
|
||||||
import org.keycloak.representations.AccessToken;
|
|
||||||
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
|
|
||||||
import org.keycloak.services.managers.RealmManager;
|
|
||||||
import org.keycloak.services.resources.admin.AdminRoot;
|
|
||||||
import org.keycloak.testsuite.pages.LoginPage;
|
|
||||||
import org.keycloak.testsuite.rule.KeycloakRule;
|
|
||||||
import org.keycloak.testsuite.rule.WebResource;
|
|
||||||
import org.keycloak.testsuite.rule.WebRule;
|
|
||||||
import org.openqa.selenium.WebDriver;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.ws.rs.client.Client;
|
|
||||||
import javax.ws.rs.client.ClientBuilder;
|
|
||||||
import javax.ws.rs.client.ClientRequestContext;
|
|
||||||
import javax.ws.rs.client.ClientRequestFilter;
|
|
||||||
import javax.ws.rs.client.Entity;
|
|
||||||
import javax.ws.rs.client.WebTarget;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class SamlBindingTest {
|
|
||||||
|
|
||||||
@ClassRule
|
|
||||||
public static SamlKeycloakRule keycloakRule = new SamlKeycloakRule() {
|
|
||||||
@Override
|
|
||||||
public void initWars() {
|
|
||||||
ClassLoader classLoader = SamlBindingTest.class.getClassLoader();
|
|
||||||
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/simple-post", "/sales-post", "post.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/signed-post", "/sales-post-sig", "post-sig.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/signed-post-email", "/sales-post-sig-email", "post-sig-email.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/signed-post-transient", "/sales-post-sig-transient", "post-sig-transient.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/signed-post-persistent", "/sales-post-sig-persistent", "post-sig-persistent.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/signed-metadata", "/sales-metadata", "post-metadata.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/signed-get", "/employee-sig", "employee-sig.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/mappers", "/employee2", "employee2.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/signed-front-get", "/employee-sig-front", "employee-sig-front.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/bad-client-signed-post", "/bad-client-sales-post-sig", "bad-client-post-sig.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/bad-realm-signed-post", "/bad-realm-sales-post-sig", "bad-realm-post-sig.war", classLoader);
|
|
||||||
initializeSamlSecuredWar("/keycloak-saml/encrypted-post", "/sales-post-enc", "post-enc.war", classLoader);
|
|
||||||
uploadSP();
|
|
||||||
server.getServer().deploy(createDeploymentInfo("employee.war", "/employee", SamlSPFacade.class));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRealmJson() {
|
|
||||||
return "/keycloak-saml/testsaml.json";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static class SamlSPFacade extends HttpServlet {
|
|
||||||
public static String samlResponse;
|
|
||||||
public static String RELAY_STATE = "http://test.com/foo/bar";
|
|
||||||
public static String sentRelayState;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
handler(req, resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
handler(req, resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handler(HttpServletRequest req, HttpServletResponse resp) {
|
|
||||||
System.out.println("********* HERE ******");
|
|
||||||
if (req.getParameterMap().isEmpty()) {
|
|
||||||
System.out.println("redirecting");
|
|
||||||
resp.setStatus(302);
|
|
||||||
// Redirect
|
|
||||||
// UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVLRTsIwFP2Vpe%2BjG4wxG0YyWYxL0BBAH3wx3XYnTbp29nYof%2B8YEvEBNOlD03vOveec2ynyWjYsae1WreC9BbTOZy0Vsr4Qk9YopjkKZIrXgMwWbJ08LNhw4LHGaKsLLcmRch3MEcFYoRVxktN1rhW2NZg1mJ0o4Gm1iMnW2oZRKnXB5VajZZEX%2BRTqRuo9ACVO2mkUih%2F4l9C8s0MNcFkjLaHW9KSUHlwR506bAnrPMam4RCBOlsYkS1%2BD3MvLcDJxAx9KN4jCkXszrG5cP%2BCVH4y8IM8PYFx2dsQOfuiILWQKLVc2JkPPH7te6HrRxh%2BzUdidwSSIXoiz%2FBZyK1Qp1Nv1yPIjCNn9ZrN0V1AKA4UlzjMY7N13IDKbHjyxXoA5291%2FtzH7I%2FApPet%2FHNawx65hli61FMXeSaTUH%2FMubtvlYU0LfcA1t5cl%2BAO%2FfxGlW%2FVQ1ipsoBCVgJLQ2XHo7385%2BwI%3D");
|
|
||||||
UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVJbT8IwFP4rS99HuwluNIwEIUYSLwugD76Y2h2kSdfOng7l31uGRn0ATfrQ9HznfJfTEYpaN3zS%2Bo1ZwGsL6KP3WhvkXaEgrTPcClTIjagBuZd8Obm55mmP8cZZb6XV5NByGiwQwXllDYkmX9epNdjW4JbgtkrC%2FeK6IBvvG06ptlLojUXPc5YnFOpG2x0AJdEsaFRG7PuPoUWwQx0IXSOtoLb0SynduyLRpXUSOs8FWQuNQKL5rCDz2VO%2FymEgIY2zlJ3H%2FSx9jkU%2BzOK0ys8yNmSSsUEAYxnsqC18tyO2MDfohfEFSVkyiNlZzM5XacrDSbJePug%2Fkqj8FHKhTKXMy%2BnIng8g5FerVRmXd8sViR7AYec8AMh4tPfDO3L3Y2%2F%2F3cT4j7BH9Mf8A1nDb8PA%2Bay0WsldNNHavk1D1D5k4V0LXbi18MclJL2ke1FVvO6gvDXYgFRrBRWh4wPp7z85%2FgA%3D");
|
|
||||||
builder.queryParam("RelayState", RELAY_STATE);
|
|
||||||
resp.setHeader("Location", builder.build().toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
System.out.println("received response");
|
|
||||||
samlResponse = req.getParameter("SAMLResponse");
|
|
||||||
sentRelayState = req.getParameter("RelayState");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public WebRule webRule = new WebRule(this);
|
|
||||||
@WebResource
|
|
||||||
protected WebDriver driver;
|
|
||||||
@WebResource
|
|
||||||
protected LoginPage loginPage;
|
|
||||||
|
|
||||||
protected void checkLoggedOut(String mainUrl) {
|
|
||||||
String pageSource = driver.getPageSource();
|
|
||||||
System.out.println("*** logout pagesource ***");
|
|
||||||
System.out.println(pageSource);
|
|
||||||
System.out.println("driver url: " + driver.getCurrentUrl());
|
|
||||||
Assert.assertTrue(pageSource.contains("request-path: /logout.jsp"));
|
|
||||||
driver.navigate().to(mainUrl);
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Test
|
|
||||||
public void ideTesting() throws Exception {
|
|
||||||
Thread.sleep(100000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPostSimpleLoginLogout() {
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post/");
|
|
||||||
System.out.println(driver.getPageSource());
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-post/");
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void testPostSimpleLoginLogoutIdpInitiated() {
|
|
||||||
driver.navigate().to("http://localhost:8081/auth/realms/demo/protocol/saml/clients/sales-post");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post/");
|
|
||||||
System.out.println(driver.getPageSource());
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-post/");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPostSignedLoginLogout() {
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-post-sig/");
|
|
||||||
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void testPostSignedLoginLogoutTransientNameID() {
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig-transient/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-transient/");
|
|
||||||
System.out.println(driver.getPageSource());
|
|
||||||
Assert.assertFalse(driver.getPageSource().contains("bburke"));
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig-transient?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-post-sig-transient/");
|
|
||||||
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void testPostSignedLoginLogoutPersistentNameID() {
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig-persistent/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-persistent/");
|
|
||||||
System.out.println(driver.getPageSource());
|
|
||||||
Assert.assertFalse(driver.getPageSource().contains("bburke"));
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("principal=G-"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig-persistent?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-post-sig-persistent/");
|
|
||||||
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void testPostSignedLoginLogoutEmailNameID() {
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig-email/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig-email/");
|
|
||||||
System.out.println(driver.getPageSource());
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("principal=bburke@redhat.com"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig-email?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-post-sig-email/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRelayStateEncoding() throws Exception {
|
|
||||||
// this test has a hardcoded SAMLRequest and we hack a SP face servlet to get the SAMLResponse so we can look
|
|
||||||
// at the relay state
|
|
||||||
SamlSPFacade.samlResponse = null;
|
|
||||||
driver.navigate().to("http://localhost:8081/employee/");
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
System.out.println(driver.getCurrentUrl());
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee/");
|
|
||||||
Assert.assertEquals(SamlSPFacade.sentRelayState, SamlSPFacade.RELAY_STATE);
|
|
||||||
Assert.assertNotNull(SamlSPFacade.samlResponse);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAttributes() throws Exception {
|
|
||||||
{
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.sentPrincipal = null;
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
|
|
||||||
driver.navigate().to("http://localhost:8081/employee2/");
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
List<String> requiredRoles = new LinkedList<>();
|
|
||||||
requiredRoles.add("manager");
|
|
||||||
requiredRoles.add("employee");
|
|
||||||
requiredRoles.add("user");
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.checkRoles = requiredRoles;
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee2/");
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
|
|
||||||
SamlPrincipal principal = (SamlPrincipal)SamlKeycloakRule.SendUsernameServlet.sentPrincipal;
|
|
||||||
Assert.assertNotNull(principal);
|
|
||||||
Assert.assertEquals("bburke@redhat.com", principal.getAttribute(X500SAMLProfileConstants.EMAIL.get()));
|
|
||||||
Assert.assertEquals("bburke@redhat.com", principal.getFriendlyAttribute("email"));
|
|
||||||
Assert.assertEquals("617", principal.getAttribute("phone"));
|
|
||||||
Assert.assertNull(principal.getFriendlyAttribute("phone"));
|
|
||||||
driver.navigate().to("http://localhost:8081/employee2/?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/employee2/");
|
|
||||||
|
|
||||||
}
|
|
||||||
keycloakRule.update(new KeycloakRule.KeycloakSetup() {
|
|
||||||
@Override
|
|
||||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
|
||||||
ClientModel app = appRealm.getClientByClientId("http://localhost:8081/employee2/");
|
|
||||||
for (ProtocolMapperModel mapper : app.getProtocolMappers()) {
|
|
||||||
if (mapper.getName().equals("role-list")) {
|
|
||||||
app.removeProtocolMapper(mapper);
|
|
||||||
mapper.setId(null);
|
|
||||||
mapper.getConfig().put(RoleListMapper.SINGLE_ROLE_ATTRIBUTE, "true");
|
|
||||||
mapper.getConfig().put(AttributeStatementHelper.SAML_ATTRIBUTE_NAME, "memberOf");
|
|
||||||
app.addProtocolMapper(mapper);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
app.addProtocolMapper(HardcodedAttributeMapper.create("hardcoded-attribute", "hardcoded-attribute", "Basic", null, "hard", false, null));
|
|
||||||
app.addProtocolMapper(HardcodedRole.create("hardcoded-role", "hardcoded-role"));
|
|
||||||
app.addProtocolMapper(RoleNameMapper.create("renamed-role", "manager", "el-jefe"));
|
|
||||||
app.addProtocolMapper(RoleNameMapper.create("renamed-employee-role", "http://localhost:8081/employee/.employee", "pee-on"));
|
|
||||||
}
|
|
||||||
}, "demo");
|
|
||||||
|
|
||||||
System.out.println(">>>>>>>>>> single role attribute <<<<<<<<");
|
|
||||||
|
|
||||||
{
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.sentPrincipal = null;
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
|
|
||||||
driver.navigate().to("http://localhost:8081/employee2/");
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
List<String> requiredRoles = new LinkedList<>();
|
|
||||||
requiredRoles.add("el-jefe");
|
|
||||||
requiredRoles.add("user");
|
|
||||||
requiredRoles.add("hardcoded-role");
|
|
||||||
requiredRoles.add("pee-on");
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.checkRoles = requiredRoles;
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.checkRoles = requiredRoles;
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee2/");
|
|
||||||
SamlKeycloakRule.SendUsernameServlet.checkRoles = null;
|
|
||||||
SamlPrincipal principal = (SamlPrincipal)SamlKeycloakRule.SendUsernameServlet.sentPrincipal;
|
|
||||||
Assert.assertNotNull(principal);
|
|
||||||
Assert.assertEquals("hard", principal.getAttribute("hardcoded-attribute"));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRedirectSignedLoginLogout() {
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig/");
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/employee-sig/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRedirectSignedLoginLogoutFrontNoSSO() {
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig-front/");
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig-front?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/employee-sig-front/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRedirectSignedLoginLogoutFront() {
|
|
||||||
// visit 1st app an logg in
|
|
||||||
System.out.println("visit 1st app ");
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig/");
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
System.out.println("login to form");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
|
|
||||||
// visit 2nd app
|
|
||||||
System.out.println("visit 2nd app ");
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig-front/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/employee-sig-front/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
|
|
||||||
// visit 3rd app
|
|
||||||
System.out.println("visit 3rd app ");
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-sig/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
|
|
||||||
// logout of first app
|
|
||||||
System.out.println("GLO");
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/employee-sig/");
|
|
||||||
driver.navigate().to("http://localhost:8081/employee-sig-front/");
|
|
||||||
String currentUrl = driver.getCurrentUrl();
|
|
||||||
Assert.assertTrue(currentUrl.startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-sig/");
|
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/auth/realms/demo/protocol/saml"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPostEncryptedLoginLogout() {
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-enc/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-post-enc/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("bburke"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-post-enc?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-post-enc/");
|
|
||||||
|
|
||||||
}
|
|
||||||
@Test
|
|
||||||
public void testPostBadClientSignature() {
|
|
||||||
driver.navigate().to("http://localhost:8081/bad-client-sales-post-sig/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
Assert.assertEquals(driver.getTitle(), "We're sorry...");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPostBadRealmSignature() {
|
|
||||||
driver.navigate().to("http://localhost:8081/bad-realm-sales-post-sig/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/bad-realm-sales-post-sig/");
|
|
||||||
Assert.assertTrue(driver.getPageSource().contains("null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createToken() {
|
|
||||||
KeycloakSession session = keycloakRule.startSession();
|
|
||||||
try {
|
|
||||||
RealmManager manager = new RealmManager(session);
|
|
||||||
|
|
||||||
RealmModel adminRealm = manager.getRealm(Config.getAdminRealm());
|
|
||||||
ClientModel adminConsole = adminRealm.getClientByClientId(Constants.ADMIN_CONSOLE_CLIENT_ID);
|
|
||||||
TokenManager tm = new TokenManager();
|
|
||||||
UserModel admin = session.users().getUserByUsername("admin", adminRealm);
|
|
||||||
ClientSessionModel clientSession = session.sessions().createClientSession(adminRealm, adminConsole);
|
|
||||||
clientSession.setNote(OIDCLoginProtocol.ISSUER, "http://localhost:8081/auth/realms/master");
|
|
||||||
UserSessionModel userSession = session.sessions().createUserSession(adminRealm, admin, "admin", null, "form", false, null, null);
|
|
||||||
AccessToken token = tm.createClientAccessToken(session, tm.getAccess(null, true, adminConsole, admin), adminRealm, adminConsole, admin, userSession, clientSession);
|
|
||||||
return tm.encodeToken(adminRealm, token);
|
|
||||||
} finally {
|
|
||||||
keycloakRule.stopSession(session, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMetadataPostSignedLoginLogout() throws Exception {
|
|
||||||
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-metadata/");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/auth/realms/demo/protocol/saml");
|
|
||||||
loginPage.login("bburke", "password");
|
|
||||||
Assert.assertEquals(driver.getCurrentUrl(), "http://localhost:8081/sales-metadata/");
|
|
||||||
String pageSource = driver.getPageSource();
|
|
||||||
Assert.assertTrue(pageSource.contains("bburke"));
|
|
||||||
driver.navigate().to("http://localhost:8081/sales-metadata?GLO=true");
|
|
||||||
checkLoggedOut("http://localhost:8081/sales-metadata/");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void uploadSP() {
|
|
||||||
String token = createToken();
|
|
||||||
final String authHeader = "Bearer " + token;
|
|
||||||
ClientRequestFilter authFilter = new ClientRequestFilter() {
|
|
||||||
@Override
|
|
||||||
public void filter(ClientRequestContext requestContext) throws IOException {
|
|
||||||
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Client client = ClientBuilder.newBuilder().register(authFilter).build();
|
|
||||||
UriBuilder authBase = UriBuilder.fromUri("http://localhost:8081/auth");
|
|
||||||
WebTarget adminRealms = client.target(AdminRoot.realmsUrl(authBase));
|
|
||||||
|
|
||||||
|
|
||||||
MultipartFormDataOutput formData = new MultipartFormDataOutput();
|
|
||||||
InputStream is = SamlBindingTest.class.getResourceAsStream("/keycloak-saml/sp-metadata.xml");
|
|
||||||
Assert.assertNotNull(is);
|
|
||||||
formData.addFormData("file", is, MediaType.APPLICATION_XML_TYPE);
|
|
||||||
|
|
||||||
WebTarget upload = adminRealms.path("demo/client-importers/saml2-entity-descriptor/upload");
|
|
||||||
System.out.println(upload.getUri());
|
|
||||||
Response response = upload.request().post(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA));
|
|
||||||
Assert.assertEquals(204, response.getStatus());
|
|
||||||
response.close();
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,20 +12,11 @@ import io.undertow.servlet.api.LoginConfig;
|
||||||
import io.undertow.servlet.api.SecurityConstraint;
|
import io.undertow.servlet.api.SecurityConstraint;
|
||||||
import io.undertow.servlet.api.ServletInfo;
|
import io.undertow.servlet.api.ServletInfo;
|
||||||
import io.undertow.servlet.api.WebResourceCollection;
|
import io.undertow.servlet.api.WebResourceCollection;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.keycloak.adapters.saml.undertow.SamlServletExtension;
|
import org.keycloak.adapters.saml.undertow.SamlServletExtension;
|
||||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||||
import org.picketlink.identity.federation.bindings.wildfly.sp.SPServletExtension;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.Principal;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -33,61 +24,6 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
|
public abstract class SamlKeycloakRule extends AbstractKeycloakRule {
|
||||||
|
|
||||||
public static class SendUsernameServlet extends HttpServlet {
|
|
||||||
|
|
||||||
public static Principal sentPrincipal;
|
|
||||||
public static List<String> checkRoles;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
if (checkRoles != null) {
|
|
||||||
for (String role : checkRoles) {
|
|
||||||
System.out.println("check role: " + role);
|
|
||||||
Assert.assertTrue(req.isUserInRole(role));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
resp.setContentType("text/plain");
|
|
||||||
OutputStream stream = resp.getOutputStream();
|
|
||||||
Principal principal = req.getUserPrincipal();
|
|
||||||
stream.write("request-path: ".getBytes());
|
|
||||||
stream.write(req.getPathInfo().getBytes());
|
|
||||||
stream.write("\n".getBytes());
|
|
||||||
stream.write("principal=".getBytes());
|
|
||||||
if (principal == null) {
|
|
||||||
stream.write("null".getBytes());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String name = principal.getName();
|
|
||||||
stream.write(name.getBytes());
|
|
||||||
sentPrincipal = principal;
|
|
||||||
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
if (checkRoles != null) {
|
|
||||||
for (String role : checkRoles) {
|
|
||||||
Assert.assertTrue(req.isUserInRole(role));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
resp.setContentType("text/plain");
|
|
||||||
OutputStream stream = resp.getOutputStream();
|
|
||||||
Principal principal = req.getUserPrincipal();
|
|
||||||
stream.write("request-path: ".getBytes());
|
|
||||||
stream.write(req.getPathInfo().getBytes());
|
|
||||||
stream.write("\n".getBytes());
|
|
||||||
stream.write("principal=".getBytes());
|
|
||||||
if (principal == null) {
|
|
||||||
stream.write("null".getBytes());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String name = principal.getName();
|
|
||||||
stream.write(name.getBytes());
|
|
||||||
sentPrincipal = principal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class TestResourceManager implements ResourceManager {
|
public static class TestResourceManager implements ResourceManager {
|
||||||
|
|
||||||
private final String basePath;
|
private final String basePath;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package org.keycloak.testsuite.keycloaksaml;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class SamlSPFacade extends HttpServlet {
|
||||||
|
public static String samlResponse;
|
||||||
|
public static String RELAY_STATE = "http://test.com/foo/bar";
|
||||||
|
public static String sentRelayState;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
handler(req, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
handler(req, resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handler(HttpServletRequest req, HttpServletResponse resp) {
|
||||||
|
System.out.println("********* HERE ******");
|
||||||
|
if (req.getParameterMap().isEmpty()) {
|
||||||
|
System.out.println("redirecting");
|
||||||
|
resp.setStatus(302);
|
||||||
|
// Redirect
|
||||||
|
// UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVLRTsIwFP2Vpe%2BjG4wxG0YyWYxL0BBAH3wx3XYnTbp29nYof%2B8YEvEBNOlD03vOveec2ynyWjYsae1WreC9BbTOZy0Vsr4Qk9YopjkKZIrXgMwWbJ08LNhw4LHGaKsLLcmRch3MEcFYoRVxktN1rhW2NZg1mJ0o4Gm1iMnW2oZRKnXB5VajZZEX%2BRTqRuo9ACVO2mkUih%2F4l9C8s0MNcFkjLaHW9KSUHlwR506bAnrPMam4RCBOlsYkS1%2BD3MvLcDJxAx9KN4jCkXszrG5cP%2BCVH4y8IM8PYFx2dsQOfuiILWQKLVc2JkPPH7te6HrRxh%2BzUdidwSSIXoiz%2FBZyK1Qp1Nv1yPIjCNn9ZrN0V1AKA4UlzjMY7N13IDKbHjyxXoA5291%2FtzH7I%2FApPet%2FHNawx65hli61FMXeSaTUH%2FMubtvlYU0LfcA1t5cl%2BAO%2FfxGlW%2FVQ1ipsoBCVgJLQ2XHo7385%2BwI%3D");
|
||||||
|
UriBuilder builder = UriBuilder.fromUri("http://localhost:8081/auth/realms/demo/protocol/saml?SAMLRequest=jVJbT8IwFP4rS99HuwluNIwEIUYSLwugD76Y2h2kSdfOng7l31uGRn0ATfrQ9HznfJfTEYpaN3zS%2Bo1ZwGsL6KP3WhvkXaEgrTPcClTIjagBuZd8Obm55mmP8cZZb6XV5NByGiwQwXllDYkmX9epNdjW4JbgtkrC%2FeK6IBvvG06ptlLojUXPc5YnFOpG2x0AJdEsaFRG7PuPoUWwQx0IXSOtoLb0SynduyLRpXUSOs8FWQuNQKL5rCDz2VO%2FymEgIY2zlJ3H%2FSx9jkU%2BzOK0ys8yNmSSsUEAYxnsqC18tyO2MDfohfEFSVkyiNlZzM5XacrDSbJePug%2Fkqj8FHKhTKXMy%2BnIng8g5FerVRmXd8sViR7AYec8AMh4tPfDO3L3Y2%2F%2F3cT4j7BH9Mf8A1nDb8PA%2Bay0WsldNNHavk1D1D5k4V0LXbi18MclJL2ke1FVvO6gvDXYgFRrBRWh4wPp7z85%2FgA%3D");
|
||||||
|
builder.queryParam("RelayState", RELAY_STATE);
|
||||||
|
resp.setHeader("Location", builder.build().toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println("received response");
|
||||||
|
samlResponse = req.getParameter("SAMLResponse");
|
||||||
|
sentRelayState = req.getParameter("RelayState");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.keycloak.testsuite.keycloaksaml;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class SendUsernameServlet extends HttpServlet {
|
||||||
|
|
||||||
|
public static Principal sentPrincipal;
|
||||||
|
public static List<String> checkRoles;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
System.out.println("In SendUsername Servlet doGet()");
|
||||||
|
if (checkRoles != null) {
|
||||||
|
for (String role : checkRoles) {
|
||||||
|
System.out.println("check role: " + role);
|
||||||
|
Assert.assertTrue(req.isUserInRole(role));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
resp.setContentType("text/plain");
|
||||||
|
OutputStream stream = resp.getOutputStream();
|
||||||
|
Principal principal = req.getUserPrincipal();
|
||||||
|
stream.write("request-path: ".getBytes());
|
||||||
|
stream.write(req.getPathInfo().getBytes());
|
||||||
|
stream.write("\n".getBytes());
|
||||||
|
stream.write("principal=".getBytes());
|
||||||
|
if (principal == null) {
|
||||||
|
stream.write("null".getBytes());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String name = principal.getName();
|
||||||
|
stream.write(name.getBytes());
|
||||||
|
sentPrincipal = principal;
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
|
||||||
|
System.out.println("In SendUsername Servlet doPost()");
|
||||||
|
if (checkRoles != null) {
|
||||||
|
for (String role : checkRoles) {
|
||||||
|
System.out.println("check role: " + role);
|
||||||
|
Assert.assertTrue(req.isUserInRole(role));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
resp.setContentType("text/plain");
|
||||||
|
OutputStream stream = resp.getOutputStream();
|
||||||
|
Principal principal = req.getUserPrincipal();
|
||||||
|
stream.write("request-path: ".getBytes());
|
||||||
|
stream.write(req.getPathInfo().getBytes());
|
||||||
|
stream.write("\n".getBytes());
|
||||||
|
stream.write("principal=".getBytes());
|
||||||
|
if (principal == null) {
|
||||||
|
stream.write("null".getBytes());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String name = principal.getName();
|
||||||
|
stream.write(name.getBytes());
|
||||||
|
sentPrincipal = principal;
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,15 @@
|
||||||
"http://localhost:8081/employee/": [ "employee" ],
|
"http://localhost:8081/employee/": [ "employee" ],
|
||||||
"http://localhost:8081/employee2/": [ "employee" ]
|
"http://localhost:8081/employee2/": [ "employee" ]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"username" : "unauthorized",
|
||||||
|
"enabled": true,
|
||||||
|
"email" : "unauthorized@redhat.com",
|
||||||
|
"credentials" : [
|
||||||
|
{ "type" : "password",
|
||||||
|
"value" : "password" }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"applications": [
|
"applications": [
|
||||||
|
|
|
@ -103,6 +103,24 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-tomcat6-adapter</artifactId>
|
<artifactId>keycloak-tomcat6-adapter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-tomcat6-saml-adapter</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-servlet-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>catalina</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.undertow</groupId>
|
<groupId>io.undertow</groupId>
|
||||||
|
|
193
testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatSamlTest.java
Executable file
193
testsuite/tomcat6/src/test/java/org/keycloak/testsuite/TomcatSamlTest.java
Executable file
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
package org.keycloak.testsuite;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
import org.keycloak.testsuite.adapter.AdapterTestStrategy;
|
||||||
|
import org.keycloak.testsuite.keycloaksaml.SamlAdapterTestStrategy;
|
||||||
|
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
*/
|
||||||
|
public class TomcatSamlTest {
|
||||||
|
@ClassRule
|
||||||
|
public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() {
|
||||||
|
@Override
|
||||||
|
protected void configure(KeycloakSession session, RealmManager manager, RealmModel adminRealm) {
|
||||||
|
SamlAdapterTestStrategy.baseAdapterTestInitialization(session, manager, adminRealm, getClass());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static TomcatServer tomcat = null;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void initTomcat() throws Exception {
|
||||||
|
URL dir = TomcatSamlTest.class.getResource("/keycloak-saml/testsaml.json");
|
||||||
|
String baseDir = new File(dir.getFile()).getParentFile().toString();
|
||||||
|
System.out.println("Tomcat basedir: " + baseDir);
|
||||||
|
tomcat = new TomcatServer(8082, baseDir);
|
||||||
|
System.setProperty("app.server.base.url", "http://localhost:8082");
|
||||||
|
System.setProperty("my.host.name", "localhost");
|
||||||
|
tomcat.deploySaml("/sales-post", "simple-post");
|
||||||
|
tomcat.deploySaml("/sales-post-sig", "signed-post");
|
||||||
|
tomcat.deploySaml("/sales-post-sig-email", "signed-post-email");
|
||||||
|
tomcat.deploySaml("/sales-post-sig-transient", "signed-post-transient");
|
||||||
|
tomcat.deploySaml("/sales-post-sig-persistent", "signed-post-persistent");
|
||||||
|
tomcat.deploySaml("/sales-metadata", "signed-metadata");
|
||||||
|
tomcat.deploySaml("/employee-sig", "signed-get");
|
||||||
|
tomcat.deploySaml("/employee2", "mappers");
|
||||||
|
tomcat.deploySaml("/employee-sig-front", "signed-front-get");
|
||||||
|
tomcat.deploySaml("/bad-client-sales-post-sig", "bad-client-signed-post");
|
||||||
|
tomcat.deploySaml("/bad-realm-sales-post-sig", "bad-realm-signed-post");
|
||||||
|
tomcat.deploySaml("/sales-post-enc", "encrypted-post");
|
||||||
|
SamlAdapterTestStrategy.uploadSP("http://localhost:8081/auth", keycloakRule);
|
||||||
|
|
||||||
|
|
||||||
|
tomcat.start();
|
||||||
|
//tomcat.getServer().await();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void shutdownTomcat() throws Exception {
|
||||||
|
tomcat.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public SamlAdapterTestStrategy testStrategy = new SamlAdapterTestStrategy("http://localhost:8081/auth", "http://localhost:8082", keycloakRule);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSimpleLoginLogout() {
|
||||||
|
testStrategy.testPostSimpleLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSimpleLoginLogoutIdpInitiated() {
|
||||||
|
testStrategy.testPostSimpleLoginLogoutIdpInitiated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogout() {
|
||||||
|
testStrategy.testPostSignedLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogoutTransientNameID() {
|
||||||
|
testStrategy.testPostSignedLoginLogoutTransientNameID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogoutPersistentNameID() {
|
||||||
|
testStrategy.testPostSignedLoginLogoutPersistentNameID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSignedLoginLogoutEmailNameID() {
|
||||||
|
testStrategy.testPostSignedLoginLogoutEmailNameID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAttributes() throws Exception {
|
||||||
|
testStrategy.testAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectSignedLoginLogout() {
|
||||||
|
testStrategy.testRedirectSignedLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectSignedLoginLogoutFrontNoSSO() {
|
||||||
|
testStrategy.testRedirectSignedLoginLogoutFrontNoSSO();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedirectSignedLoginLogoutFront() {
|
||||||
|
testStrategy.testRedirectSignedLoginLogoutFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostEncryptedLoginLogout() {
|
||||||
|
testStrategy.testPostEncryptedLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostBadClientSignature() {
|
||||||
|
testStrategy.testPostBadClientSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostBadRealmSignature() {
|
||||||
|
testStrategy.testPostBadRealmSignature( new SamlAdapterTestStrategy.CheckAuthError() {
|
||||||
|
@Override
|
||||||
|
public void check(WebDriver driver) {
|
||||||
|
Assert.assertEquals(driver.getPageSource(), "");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostSimpleUnauthorized() {
|
||||||
|
testStrategy.testPostSimpleUnauthorized( new SamlAdapterTestStrategy.CheckAuthError() {
|
||||||
|
@Override
|
||||||
|
public void check(WebDriver driver) {
|
||||||
|
Assert.assertTrue(driver.getPageSource().contains("forbidden"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//@Test
|
||||||
|
public void testMetadataPostSignedLoginLogout() throws Exception {
|
||||||
|
testStrategy.testMetadataPostSignedLoginLogout();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getBaseDirectory() {
|
||||||
|
String dirPath = null;
|
||||||
|
String relativeDirPath = "testsuite" + File.separator + "tomcat6" + File.separator + "target";
|
||||||
|
|
||||||
|
if (System.getProperties().containsKey("maven.home")) {
|
||||||
|
dirPath = System.getProperty("user.dir").replaceFirst("testsuite.tomcat6.*", Matcher.quoteReplacement(relativeDirPath));
|
||||||
|
} else {
|
||||||
|
for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
|
||||||
|
if (c.contains(File.separator + "testsuite" + File.separator + "tomcat6")) {
|
||||||
|
dirPath = c.replaceFirst("testsuite.tomcat6.*", Matcher.quoteReplacement(relativeDirPath));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String absolutePath = new File(dirPath).getAbsolutePath();
|
||||||
|
return absolutePath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import org.apache.catalina.connector.Connector;
|
||||||
import org.apache.catalina.core.StandardContext;
|
import org.apache.catalina.core.StandardContext;
|
||||||
import org.apache.catalina.startup.Embedded;
|
import org.apache.catalina.startup.Embedded;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.adapters.saml.tomcat.SamlAuthenticatorValve;
|
||||||
import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
|
import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
|
||||||
|
|
||||||
public class TomcatServer {
|
public class TomcatServer {
|
||||||
|
@ -40,7 +41,7 @@ public class TomcatServer {
|
||||||
public TomcatServer(int port, String appBase) {
|
public TomcatServer(int port, String appBase) {
|
||||||
|
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
|
||||||
server = new Embedded();
|
server = new Embedded();
|
||||||
server.setName("TomcatEmbeddedServer");
|
server.setName("TomcatEmbeddedServer");
|
||||||
server.setCatalinaBase(TomcatTest.getBaseDirectory());
|
server.setCatalinaBase(TomcatTest.getBaseDirectory());
|
||||||
|
@ -64,6 +65,20 @@ public class TomcatServer {
|
||||||
rootContext.setDefaultWebXml("web.xml");
|
rootContext.setDefaultWebXml("web.xml");
|
||||||
host.addChild(rootContext);
|
host.addChild(rootContext);
|
||||||
}
|
}
|
||||||
|
public void deploySaml(String contextPath, String appDir) {
|
||||||
|
if (contextPath == null) {
|
||||||
|
throw new IllegalArgumentException("Context path or appbase should not be null");
|
||||||
|
}
|
||||||
|
if (!contextPath.startsWith("/")) {
|
||||||
|
contextPath = "/" + contextPath;
|
||||||
|
}
|
||||||
|
StandardContext rootContext = (StandardContext) server.createContext(contextPath, appDir);
|
||||||
|
SamlAuthenticatorValve valve = new SamlAuthenticatorValve();
|
||||||
|
rootContext.addValve(valve);
|
||||||
|
//rootContext.addLifecycleListener(valve);
|
||||||
|
rootContext.setDefaultWebXml("web.xml");
|
||||||
|
host.addChild(rootContext);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the tomcat embedded server
|
* Start the tomcat embedded server
|
||||||
|
|
|
@ -24,6 +24,7 @@ package org.keycloak.testsuite;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -39,6 +40,7 @@ import java.util.regex.Matcher;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
//@Ignore
|
||||||
public class TomcatTest {
|
public class TomcatTest {
|
||||||
@ClassRule
|
@ClassRule
|
||||||
public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() {
|
public static AbstractKeycloakRule keycloakRule = new AbstractKeycloakRule() {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/bad-client-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:8081/bad-client-sales-post-sig/" password="test123"/>
|
||||||
|
<Certificate alias="http://localhost:8081/bad-client-sales-post-sig/"/>
|
||||||
|
</KeyStore>
|
||||||
|
</Key>
|
||||||
|
</Keys>
|
||||||
|
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
||||||
|
<RoleMapping>
|
||||||
|
<Attribute name="Role"/>
|
||||||
|
</RoleMapping>
|
||||||
|
<IDP entityID="idp">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/bad-realm-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:8081/bad-realm-sales-post-sig/" password="test123"/>
|
||||||
|
<Certificate alias="http://localhost:8081/bad-realm-sales-post-sig/"/>
|
||||||
|
</KeyStore>
|
||||||
|
</Key>
|
||||||
|
</Keys>
|
||||||
|
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
||||||
|
<RoleMapping>
|
||||||
|
<Attribute name="Role"/>
|
||||||
|
</RoleMapping>
|
||||||
|
<IDP entityID="idp">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
3
testsuite/tomcat6/src/test/resources/keycloak-saml/context.xml
Executable file
3
testsuite/tomcat6/src/test/resources/keycloak-saml/context.xml
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
<Context path="/customer-portal">
|
||||||
|
<Valve className="org.keycloak.adapters.saml.tomcat.SamlAuthenticatorValve"/>
|
||||||
|
</Context>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/sales-post-enc/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||||
|
logoutPage="/logout.jsp"
|
||||||
|
forceAuthentication="false">
|
||||||
|
<Keys>
|
||||||
|
<Key signing="true" encryption="true">
|
||||||
|
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
||||||
|
<PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
|
||||||
|
<Certificate alias="http://localhost:8080/sales-post-enc/"/>
|
||||||
|
</KeyStore>
|
||||||
|
</Key>
|
||||||
|
</Keys>
|
||||||
|
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
||||||
|
<RoleMapping>
|
||||||
|
<Attribute name="Role"/>
|
||||||
|
</RoleMapping>
|
||||||
|
<IDP entityID="idp">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/employee2/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||||
|
logoutPage="/logout.jsp"
|
||||||
|
forceAuthentication="false">
|
||||||
|
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
||||||
|
<RoleMapping>
|
||||||
|
<Attribute name="memberOf"/>
|
||||||
|
<Attribute name="Role"/>
|
||||||
|
</RoleMapping>
|
||||||
|
<IDP entityID="idp">
|
||||||
|
<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"
|
||||||
|
/>
|
||||||
|
</IDP>
|
||||||
|
</SP>
|
||||||
|
</keycloak-saml-adapter>
|
56
testsuite/tomcat6/src/test/resources/keycloak-saml/mappers/WEB-INF/web.xml
Executable file
56
testsuite/tomcat6/src/test/resources/keycloak-saml/mappers/WEB-INF/web.xml
Executable file
|
@ -0,0 +1,56 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>user</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>employee</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>pee-on</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>hardcoded-role</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/employee-sig-front/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
logoutPage="/logout.jsp"
|
||||||
|
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||||
|
forceAuthentication="false">
|
||||||
|
<Keys>
|
||||||
|
<Key signing="true" >
|
||||||
|
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
||||||
|
<PrivateKey alias="http://localhost:8080/employee-sig/" password="test123"/>
|
||||||
|
<Certificate alias="http://localhost:8080/employee-sig/"/>
|
||||||
|
</KeyStore>
|
||||||
|
</Key>
|
||||||
|
</Keys>
|
||||||
|
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
||||||
|
<RoleMapping>
|
||||||
|
<Attribute name="Role"/>
|
||||||
|
</RoleMapping>
|
||||||
|
<IDP entityID="idp">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="REDIRECT"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
requestBinding="REDIRECT"
|
||||||
|
responseBinding="REDIRECT"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/employee-sig/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
logoutPage="/logout.jsp"
|
||||||
|
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||||
|
forceAuthentication="false">
|
||||||
|
<Keys>
|
||||||
|
<Key signing="true" >
|
||||||
|
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
||||||
|
<PrivateKey alias="http://localhost:8080/employee-sig/" password="test123"/>
|
||||||
|
<Certificate alias="http://localhost:8080/employee-sig/"/>
|
||||||
|
</KeyStore>
|
||||||
|
</Key>
|
||||||
|
</Keys>
|
||||||
|
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
||||||
|
<RoleMapping>
|
||||||
|
<Attribute name="Role"/>
|
||||||
|
</RoleMapping>
|
||||||
|
<IDP entityID="idp">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="REDIRECT"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
requestBinding="REDIRECT"
|
||||||
|
responseBinding="REDIRECT"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/sales-metadata/"
|
||||||
|
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">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,44 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/sales-post-sig-email/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
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">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/sales-post-sig-persistent/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
nameIDPolicyFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
|
||||||
|
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">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/sales-post-sig-transient/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
nameIDPolicyFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
||||||
|
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">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/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">
|
||||||
|
<SingleSignOnService signRequest="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
requestBinding="POST"
|
||||||
|
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SingleLogoutService
|
||||||
|
validateRequestSignature="true"
|
||||||
|
validateResponseSignature="true"
|
||||||
|
signRequest="true"
|
||||||
|
signResponse="true"
|
||||||
|
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>
|
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<keycloak-saml-adapter>
|
||||||
|
<SP entityID="http://localhost:8082/sales-post/"
|
||||||
|
sslPolicy="EXTERNAL"
|
||||||
|
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
||||||
|
logoutPage="/logout.jsp"
|
||||||
|
forceAuthentication="false">
|
||||||
|
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
||||||
|
<RoleMapping>
|
||||||
|
<Attribute name="Role"/>
|
||||||
|
</RoleMapping>
|
||||||
|
<IDP entityID="idp">
|
||||||
|
<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"
|
||||||
|
/>
|
||||||
|
</IDP>
|
||||||
|
</SP>
|
||||||
|
</keycloak-saml-adapter>
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>adapter-test</module-name>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<servlet-class>org.keycloak.testsuite.keycloaksaml.SendUsernameServlet</servlet-class>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>SendUsernameServlet</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<security-constraint>
|
||||||
|
<web-resource-collection>
|
||||||
|
<web-resource-name>Users</web-resource-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</web-resource-collection>
|
||||||
|
<auth-constraint>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</auth-constraint>
|
||||||
|
</security-constraint>
|
||||||
|
|
||||||
|
<login-config>
|
||||||
|
<auth-method>BASIC</auth-method>
|
||||||
|
<realm-name>demo</realm-name>
|
||||||
|
<form-login-config>
|
||||||
|
<form-login-page>/error.html</form-login-page>
|
||||||
|
<form-error-page>/error.html</form-error-page>
|
||||||
|
</form-login-config>
|
||||||
|
</login-config>
|
||||||
|
|
||||||
|
<security-role>
|
||||||
|
<role-name>manager</role-name>
|
||||||
|
</security-role>
|
||||||
|
<security-role>
|
||||||
|
<role-name>el-jefe</role-name>
|
||||||
|
</security-role>
|
||||||
|
</web-app>
|
38
testsuite/tomcat6/src/test/resources/keycloak-saml/sp-metadata.xml
Executable file
38
testsuite/tomcat6/src/test/resources/keycloak-saml/sp-metadata.xml
Executable file
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<EntitiesDescriptor Name="urn:mace:shibboleth:testshib:two"
|
||||||
|
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||||
|
>
|
||||||
|
<EntityDescriptor entityID="http://localhost:8082/sales-metadata/">
|
||||||
|
<SPSSODescriptor AuthnRequestsSigned="true"
|
||||||
|
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext">
|
||||||
|
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient
|
||||||
|
</NameIDFormat>
|
||||||
|
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8082/sales-metadata/"/>
|
||||||
|
<AssertionConsumerService
|
||||||
|
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8082/sales-metadata/"
|
||||||
|
index="1" isDefault="true" />
|
||||||
|
<KeyDescriptor use="signing">
|
||||||
|
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
|
||||||
|
<dsig:X509Data>
|
||||||
|
<dsig:X509Certificate>
|
||||||
|
MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw==
|
||||||
|
</dsig:X509Certificate>
|
||||||
|
</dsig:X509Data>
|
||||||
|
</dsig:KeyInfo>
|
||||||
|
</KeyDescriptor>
|
||||||
|
</SPSSODescriptor>
|
||||||
|
<Organization>
|
||||||
|
<OrganizationName xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||||
|
xml:lang="en">JBoss</OrganizationName>
|
||||||
|
<OrganizationDisplayName xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||||
|
xml:lang="en">JBoss by Red Hat</OrganizationDisplayName>
|
||||||
|
<OrganizationURL xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
|
||||||
|
xml:lang="en">http://localhost:8080/sales-metadata/</OrganizationURL>
|
||||||
|
</Organization>
|
||||||
|
<ContactPerson contactType="technical">
|
||||||
|
<GivenName>The</GivenName>
|
||||||
|
<SurName>Admin</SurName>
|
||||||
|
<EmailAddress>admin@mycompany.com</EmailAddress>
|
||||||
|
</ContactPerson>
|
||||||
|
</EntityDescriptor>
|
||||||
|
</EntitiesDescriptor>
|
376
testsuite/tomcat6/src/test/resources/keycloak-saml/testsaml.json
Executable file
376
testsuite/tomcat6/src/test/resources/keycloak-saml/testsaml.json
Executable file
|
@ -0,0 +1,376 @@
|
||||||
|
{
|
||||||
|
"id": "demo",
|
||||||
|
"realm": "demo",
|
||||||
|
"enabled": true,
|
||||||
|
"sslRequired": "external",
|
||||||
|
"registrationAllowed": true,
|
||||||
|
"resetPasswordAllowed": true,
|
||||||
|
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||||
|
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||||
|
"requiredCredentials": [ "password" ],
|
||||||
|
"defaultRoles": [ "user" ],
|
||||||
|
"smtpServer": {
|
||||||
|
"from": "auto@keycloak.org",
|
||||||
|
"host": "localhost",
|
||||||
|
"port":"3025"
|
||||||
|
},
|
||||||
|
"users" : [
|
||||||
|
{
|
||||||
|
"username" : "bburke",
|
||||||
|
"enabled": true,
|
||||||
|
"email" : "bburke@redhat.com",
|
||||||
|
"credentials" : [
|
||||||
|
{ "type" : "password",
|
||||||
|
"value" : "password" }
|
||||||
|
],
|
||||||
|
"attributes" : {
|
||||||
|
"phone": "617"
|
||||||
|
},
|
||||||
|
"realmRoles": ["manager", "user"],
|
||||||
|
"applicationRoles": {
|
||||||
|
"http://localhost:8082/employee/": [ "employee" ],
|
||||||
|
"http://localhost:8082/employee2/": [ "employee" ]
|
||||||
|
}
|
||||||
|
} ,
|
||||||
|
{
|
||||||
|
"username" : "unauthorized",
|
||||||
|
"enabled": true,
|
||||||
|
"email" : "unauthorized@redhat.com",
|
||||||
|
"credentials" : [
|
||||||
|
{ "type" : "password",
|
||||||
|
"value" : "password" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"applications": [
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/sales-post/",
|
||||||
|
"enabled": true,
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"baseUrl": "http://localhost:8082/sales-post",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/sales-post/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8082/sales-post/",
|
||||||
|
"saml_assertion_consumer_url_redirect": "http://localhost:8082/sales-post/",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8082/sales-post/",
|
||||||
|
"saml_single_logout_service_url_redirect": "http://localhost:8082/sales-post/",
|
||||||
|
"saml_idp_initiated_sso_url_name": "sales-post"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/sales-post-sig/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/sales-post-sig",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/sales-post-sig/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8082/sales-post-sig/",
|
||||||
|
"saml_assertion_consumer_url_redirect": "http://localhost:8082/sales-post-sig/",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8082/sales-post-sig/",
|
||||||
|
"saml_single_logout_service_url_redirect": "http://localhost:8082/sales-post-sig/",
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.signature.algorithm": "RSA_SHA256",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/sales-post-sig-transient/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/sales-post-sig-transient",
|
||||||
|
"adminUrl": "http://localhost:8082/sales-post-sig-transient",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/sales-post-sig-transient/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8082/sales-post-sig-transient/",
|
||||||
|
"saml_assertion_consumer_url_redirect": "http://localhost:8082/sales-post-sig-transient/",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8082/sales-post-sig-transient/",
|
||||||
|
"saml_single_logout_service_url_redirect": "http://localhost:8082/sales-post-sig-transient/",
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.signature.algorithm": "RSA_SHA256",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/sales-post-sig-persistent/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/sales-post-sig-persistent",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/sales-post-sig-persistent/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8082/sales-post-sig-persistent/",
|
||||||
|
"saml_assertion_consumer_url_redirect": "http://localhost:8082/sales-post-sig-persistent/",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8082/sales-post-sig-persistent/",
|
||||||
|
"saml_single_logout_service_url_redirect": "http://localhost:8082/sales-post-sig-persistent/",
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.signature.algorithm": "RSA_SHA256",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/sales-post-sig-email/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/sales-post-sig-email",
|
||||||
|
"adminUrl": "http://localhost:8082/sales-post-sig-email",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/sales-post-sig-email/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml_force_name_id_format": "true",
|
||||||
|
"saml_name_id_format": "email",
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8082/sales-post-sig-email/",
|
||||||
|
"saml_assertion_consumer_url_redirect": "http://localhost:8082/sales-post-sig-email/",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8082/sales-post-sig-email/",
|
||||||
|
"saml_single_logout_service_url_redirect": "http://localhost:8082/sales-post-sig-email/",
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.signature.algorithm": "RSA_SHA256",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/bad-realm-sales-post-sig/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/bad-realm-sales-post-sig/",
|
||||||
|
"adminUrl": "http://localhost:8082/bad-realm-sales-post-sig/",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/bad-realm-sales-post-sig/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/bad-client-sales-post-sig/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/bad-client-sales-post-sig/",
|
||||||
|
"adminUrl": "http://localhost:8082/bad-client-sales-post-sig/",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/bad-client-sales-post-sig/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/sales-post-enc/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/sales-post-enc",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/sales-post-enc/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8082/sales-post-enc/",
|
||||||
|
"saml_assertion_consumer_url_redirect": "http://localhost:8082/sales-post-enc/",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8082/sales-post-enc/",
|
||||||
|
"saml_single_logout_service_url_redirect": "http://localhost:8082/sales-post-enc/",
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.signature.algorithm": "RSA_SHA512",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.encrypt": "true",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g==",
|
||||||
|
"saml.encryption.certificate": "MIIB1DCCAT0CBgFJGVacCDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1lbmMvMB4XDTE0MTAxNjE0MjA0NloXDTI0MTAxNjE0MjIyNlowMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3QtZW5jLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2+5MCT5BnVN+IYnKZcH6ev1pjXGi4feE0nOycq/VJ3aeaZMi4G9AxOxCBPupErOC7Kgm/Bw5AdJyw+Q12wSRXfJ9FhqCrLXpb7YOhbVSTJ8De5O8mW35DxAlh/cxe9FXjqPb286wKTUZ3LfGYR+X235UQeCTAPS/Ufi21EXaEikCAwEAATANBgkqhkiG9w0BAQsFAAOBgQBMrfGD9QFfx5v7ld/OAto5rjkTe3R1Qei8XRXfcs83vLaqEzjEtTuLGrJEi55kXuJgBpVmQpnwCCkkjSy0JxbqLDdVi9arfWUxEGmOr01ZHycELhDNaQcFqVMPr5kRHIHgktT8hK2IgCvd3Fy9/JCgUgCPxKfhwecyEOKxUc857g=="
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/employee-sig/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/employee-sig",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/employee-sig/*"
|
||||||
|
],
|
||||||
|
"adminUrl": "http://localhost:8082/employee-sig/",
|
||||||
|
"attributes": {
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.signature.algorithm": "RSA_SHA256",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/employee/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/employee/",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/employee/*"
|
||||||
|
],
|
||||||
|
"adminUrl": "http://localhost:8082/employee/",
|
||||||
|
"attributes": {
|
||||||
|
"saml.authnstatement": "true"
|
||||||
|
},
|
||||||
|
"protocolMappers": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-user-property-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"user.attribute": "email",
|
||||||
|
"friendly.name": "email",
|
||||||
|
"attribute.name": "urn:oid:1.2.840.113549.1.9.1",
|
||||||
|
"attribute.nameformat": "URI Reference"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "phone",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-user-attribute-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"user.attribute": "phone",
|
||||||
|
"attribute.name": "phone",
|
||||||
|
"attribute.nameformat": "Basic"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "role-list",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-role-list-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"attribute.name": "Role",
|
||||||
|
"attribute.nameformat": "Basic",
|
||||||
|
"single": "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/employee2/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"baseUrl": "http://localhost:8082/employee2/",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/employee2/*"
|
||||||
|
],
|
||||||
|
"adminUrl": "http://localhost:8082/employee2/",
|
||||||
|
"attributes": {
|
||||||
|
"saml.authnstatement": "true"
|
||||||
|
},
|
||||||
|
"protocolMappers": [
|
||||||
|
{
|
||||||
|
"name": "email",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-user-property-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"user.attribute": "email",
|
||||||
|
"friendly.name": "email",
|
||||||
|
"attribute.name": "urn:oid:1.2.840.113549.1.9.1",
|
||||||
|
"attribute.nameformat": "URI Reference"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "phone",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-user-attribute-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"user.attribute": "phone",
|
||||||
|
"attribute.name": "phone",
|
||||||
|
"attribute.nameformat": "Basic"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "role-list",
|
||||||
|
"protocol": "saml",
|
||||||
|
"protocolMapper": "saml-role-list-mapper",
|
||||||
|
"consentRequired": false,
|
||||||
|
"config": {
|
||||||
|
"attribute.name": "Role",
|
||||||
|
"attribute.nameformat": "Basic",
|
||||||
|
"single": "false"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http://localhost:8082/employee-sig-front/",
|
||||||
|
"enabled": true,
|
||||||
|
"protocol": "saml",
|
||||||
|
"fullScopeAllowed": true,
|
||||||
|
"frontchannelLogout": true,
|
||||||
|
"baseUrl": "http://localhost:8082/employee-sig-front/",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8082/employee-sig-front/*"
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"saml_assertion_consumer_url_post": "http://localhost:8082/employee-sig-front/",
|
||||||
|
"saml_assertion_consumer_url_redirect": "http://localhost:8082/employee-sig-front/",
|
||||||
|
"saml_single_logout_service_url_post": "http://localhost:8082/employee-sig-front/",
|
||||||
|
"saml_single_logout_service_url_redirect": "http://localhost:8082/employee-sig-front/",
|
||||||
|
"saml.server.signature": "true",
|
||||||
|
"saml.client.signature": "true",
|
||||||
|
"saml.signature.algorithm": "RSA_SHA1",
|
||||||
|
"saml.authnstatement": "true",
|
||||||
|
"saml.signing.certificate": "MIIB0DCCATkCBgFJH5u0EDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNodHRwOi8vbG9jYWxob3N0OjgwODAvZW1wbG95ZWUtc2lnLzAeFw0xNDEwMTcxOTMzNThaFw0yNDEwMTcxOTM1MzhaMC4xLDAqBgNVBAMTI2h0dHA6Ly9sb2NhbGhvc3Q6ODA4MC9lbXBsb3llZS1zaWcvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+9kVgPFpshjS2aT2g52lqTv2lqb1jgvXZVk7iFF4LAO6SdCXKXRZI4SuzIRkVNpE1a42V1kQRlaozoFklgvX5sje8tkpa9ylq+bxGXM9RRycqRu2B+oWUV7Aqq7Bs0Xud0WeHQYRcEoCjqsFKGy65qkLRDdT70FTJgpSHts+gDwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACKyPLGqMX8GsIrCfJU8eVnpaqzTXMglLVo/nTcfAnWe9UAdVe8N3a2PXpDBvuqNA/DEAhVcQgxdlOTWnB6s8/yLTRuH0bZgb3qGdySif+lU+E7zZ/SiDzavAvn+ABqemnzHcHyhYO+hNRGHvUbW5OAii9Vdjhm8BI32YF1NwhKp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"roles" : {
|
||||||
|
"realm" : [
|
||||||
|
{
|
||||||
|
"name": "manager",
|
||||||
|
"description": "Have Manager privileges"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "user",
|
||||||
|
"description": "Have User privileges"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"application" : {
|
||||||
|
"http://localhost:8082/employee/" : [
|
||||||
|
{
|
||||||
|
"name": "employee",
|
||||||
|
"description": "Have Employee privileges"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"http://localhost:8082/employee2/" : [
|
||||||
|
{
|
||||||
|
"name": "employee",
|
||||||
|
"description": "Have Employee privileges"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue