further
This commit is contained in:
parent
1548065b7f
commit
5ce263c2b5
17 changed files with 2959 additions and 16 deletions
85
integration/as7-eap6/adapter/pom.xml
Executable file
85
integration/as7-eap6/adapter/pom.xml
Executable file
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0"?>
|
||||
<project>
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-alpha-1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-as7-adapter</artifactId>
|
||||
<name>Keycloak AS7 Integration</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>3.1.2.GA</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>1.0.0.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-jaxrs</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>resteasy-client</artifactId>
|
||||
<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>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketbox</groupId>
|
||||
<artifactId>picketbox</artifactId>
|
||||
<scope>provided</scope>
|
||||
<version>4.0.7.Final</version>
|
||||
</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,14 @@
|
|||
package org.keycloak.adapters.as7;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface Actions
|
||||
{
|
||||
public static final String J_OAUTH_ADMIN_FORCED_LOGOUT = "j_oauth_admin_forced_logout";
|
||||
public static final String J_OAUTH_LOGOUT = "j_oauth_logout";
|
||||
public static final String J_OAUTH_RESOLVE_ACCESS_CODE = "j_oauth_resolve_access_code";
|
||||
public static final String J_OAUTH_REMOTE_LOGOUT = "j_oauth_remote_logout";
|
||||
public static final String J_OAUTH_TOKEN_GRANT = "j_oauth_token_grant";
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package org.keycloak.adapters.as7;
|
||||
|
||||
import org.apache.catalina.Lifecycle;
|
||||
import org.apache.catalina.LifecycleEvent;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.LifecycleListener;
|
||||
import org.apache.catalina.authenticator.AuthenticatorBase;
|
||||
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.jboss.logging.Logger;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.as7.config.ManagedResourceConfigLoader;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Uses a configured remote auth server to do Bearer token authentication only. SkeletonKeyTokens are used
|
||||
* to provide user data and role mappings.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements LifecycleListener
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(BearerTokenAuthenticatorValve.class);
|
||||
protected ManagedResourceConfig remoteSkeletonKeyConfig;
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
|
||||
@Override
|
||||
public void start() throws LifecycleException
|
||||
{
|
||||
super.start();
|
||||
StandardContext standardContext = (StandardContext)context;
|
||||
standardContext.addLifecycleListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lifecycleEvent(LifecycleEvent event)
|
||||
{
|
||||
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
ManagedResourceConfigLoader managedResourceConfigLoader = new ManagedResourceConfigLoader(context);
|
||||
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
|
||||
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(Request request, Response response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
super.invoke(request, response);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, !remoteSkeletonKeyConfig.isCancelPropagation(), true);
|
||||
if (bearer.login(request, response))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (LoginException e)
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
package org.keycloak.adapters.as7;
|
||||
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeyPrincipal;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CatalinaBearerTokenAuthenticator
|
||||
{
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
protected boolean challenge;
|
||||
protected Logger log = Logger.getLogger(CatalinaBearerTokenAuthenticator.class);
|
||||
protected String tokenString;
|
||||
protected SkeletonKeyToken token;
|
||||
private Principal principal;
|
||||
protected boolean propagateToken;
|
||||
|
||||
public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean propagateToken, boolean challenge)
|
||||
{
|
||||
this.resourceMetadata = resourceMetadata;
|
||||
this.challenge = challenge;
|
||||
this.propagateToken = propagateToken;
|
||||
}
|
||||
|
||||
public ResourceMetadata getResourceMetadata()
|
||||
{
|
||||
return resourceMetadata;
|
||||
}
|
||||
|
||||
public String getTokenString()
|
||||
{
|
||||
return tokenString;
|
||||
}
|
||||
|
||||
public SkeletonKeyToken getToken()
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
public Principal getPrincipal()
|
||||
{
|
||||
return principal;
|
||||
}
|
||||
|
||||
public boolean login(Request request, HttpServletResponse response) throws LoginException, IOException
|
||||
{
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
if (authHeader == null)
|
||||
{
|
||||
if (challenge)
|
||||
{
|
||||
challengeResponse(response, null, null);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String[] split = authHeader.trim().split("\\s+");
|
||||
if (split == null || split.length != 2) challengeResponse(response, null, null);
|
||||
if (!split[0].equalsIgnoreCase("Bearer")) challengeResponse(response, null, null);
|
||||
|
||||
|
||||
tokenString = split[1];
|
||||
|
||||
try
|
||||
{
|
||||
token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
|
||||
}
|
||||
catch (VerificationException e)
|
||||
{
|
||||
log.error("Failed to verify token", e);
|
||||
challengeResponse(response, "invalid_token", e.getMessage());
|
||||
}
|
||||
boolean verifyCaller = false;
|
||||
Set<String> roles = null;
|
||||
if (resourceMetadata.getResourceName() != null)
|
||||
{
|
||||
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
||||
if (access != null) roles = access.getRoles();
|
||||
verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName());
|
||||
}
|
||||
else
|
||||
{
|
||||
verifyCaller = token.isVerifyCaller();
|
||||
SkeletonKeyToken.Access access = token.getRealmAccess();
|
||||
if (access != null) roles = access.getRoles();
|
||||
}
|
||||
String surrogate = null;
|
||||
if (verifyCaller)
|
||||
{
|
||||
if (token.getTrustedCertificates() == null || token.getTrustedCertificates().size() == 0)
|
||||
{
|
||||
response.sendError(400);
|
||||
throw new LoginException("No trusted certificates in token");
|
||||
}
|
||||
// for now, we just make sure JBoss Web did two-way SSL
|
||||
// assume JBoss Web verifies the client cert
|
||||
X509Certificate[] chain = request.getCertificateChain();
|
||||
if (chain == null || chain.length == 0)
|
||||
{
|
||||
response.sendError(400);
|
||||
throw new LoginException("No certificates provided by jboss web to verify the caller");
|
||||
}
|
||||
surrogate = chain[0].getSubjectX500Principal().getName();
|
||||
}
|
||||
SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
|
||||
principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles);
|
||||
request.setUserPrincipal(principal);
|
||||
request.setAuthType("OAUTH_BEARER");
|
||||
if (propagateToken)
|
||||
{
|
||||
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata);
|
||||
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
|
||||
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected void challengeResponse(HttpServletResponse response, String error, String description) throws LoginException
|
||||
{
|
||||
StringBuilder header = new StringBuilder("Bearer realm=\"");
|
||||
header.append(resourceMetadata.getRealm()).append("\"");
|
||||
if (error != null)
|
||||
{
|
||||
header.append(", error=\"").append(error).append("\"");
|
||||
}
|
||||
if (description != null)
|
||||
{
|
||||
header.append(", error_description=\"").append(description).append("\"");
|
||||
}
|
||||
response.setHeader("WWW-Authenticate", header.toString());
|
||||
try
|
||||
{
|
||||
response.sendError(401);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
throw new LoginException("Challenged");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
package org.keycloak.adapters.as7;
|
||||
|
||||
import org.apache.catalina.Realm;
|
||||
import org.apache.catalina.realm.GenericPrincipal;
|
||||
import org.jboss.as.web.security.JBossGenericPrincipal;
|
||||
import org.jboss.security.NestableGroup;
|
||||
import org.jboss.security.SecurityConstants;
|
||||
import org.jboss.security.SecurityContext;
|
||||
import org.jboss.security.SecurityContextAssociation;
|
||||
import org.jboss.security.SimpleGroup;
|
||||
import org.jboss.security.SimplePrincipal;
|
||||
|
||||
import javax.security.auth.Subject;
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CatalinaSecurityContextHelper
|
||||
{
|
||||
public GenericPrincipal createPrincipal(Realm realm, Principal identity, Collection<String> roleSet)
|
||||
{
|
||||
Subject subject = new Subject();
|
||||
String credentials = "";
|
||||
Set<Principal> principals = subject.getPrincipals();
|
||||
principals.add(identity);
|
||||
Group[] roleSets = getRoleSets(roleSet);
|
||||
for(int g = 0; g < roleSets.length; g ++)
|
||||
{
|
||||
Group group = roleSets[g];
|
||||
String name = group.getName();
|
||||
Group subjectGroup = createGroup(name, principals);
|
||||
if( subjectGroup instanceof NestableGroup)
|
||||
{
|
||||
/* A NestableGroup only allows Groups to be added to it so we
|
||||
need to add a SimpleGroup to subjectRoles to contain the roles
|
||||
*/
|
||||
SimpleGroup tmp = new SimpleGroup("Roles");
|
||||
subjectGroup.addMember(tmp);
|
||||
subjectGroup = tmp;
|
||||
}
|
||||
// Copy the group members to the Subject group
|
||||
Enumeration<? extends Principal> members = group.members();
|
||||
while( members.hasMoreElements() )
|
||||
{
|
||||
Principal role = (Principal) members.nextElement();
|
||||
subjectGroup.addMember(role);
|
||||
}
|
||||
}
|
||||
// add the CallerPrincipal group if none has been added in getRoleSets
|
||||
Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
|
||||
callerGroup.addMember(identity);
|
||||
principals.add(callerGroup);
|
||||
SecurityContext sc = SecurityContextAssociation.getSecurityContext();
|
||||
Principal userPrincipal = getPrincipal(subject);
|
||||
sc.getUtil().createSubjectInfo(userPrincipal, credentials, subject);
|
||||
List<String> rolesAsStringList = new ArrayList<String>();
|
||||
rolesAsStringList.addAll(roleSet);
|
||||
return new JBossGenericPrincipal(realm, userPrincipal.getName(), null, rolesAsStringList,
|
||||
userPrincipal, null, credentials, null, subject);
|
||||
|
||||
}
|
||||
/**
|
||||
* Get the Principal given the authenticated Subject. Currently the first principal that is not of type {@code Group} is
|
||||
* considered or the single principal inside the CallerPrincipal group.
|
||||
*
|
||||
* @param subject
|
||||
* @return the authenticated principal
|
||||
*/
|
||||
protected Principal getPrincipal(Subject subject) {
|
||||
Principal principal = null;
|
||||
Principal callerPrincipal = null;
|
||||
if (subject != null) {
|
||||
Set<Principal> principals = subject.getPrincipals();
|
||||
if (principals != null && !principals.isEmpty()) {
|
||||
for (Principal p : principals) {
|
||||
if (!(p instanceof Group) && principal == null) {
|
||||
principal = p;
|
||||
}
|
||||
if (p instanceof Group) {
|
||||
Group g = Group.class.cast(p);
|
||||
if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
|
||||
Enumeration<? extends Principal> e = g.members();
|
||||
if (e.hasMoreElements())
|
||||
callerPrincipal = e.nextElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return callerPrincipal == null ? principal : callerPrincipal;
|
||||
}
|
||||
|
||||
protected Group createGroup(String name, Set<Principal> principals)
|
||||
{
|
||||
Group roles = null;
|
||||
Iterator<Principal> iter = principals.iterator();
|
||||
while( iter.hasNext() )
|
||||
{
|
||||
Object next = iter.next();
|
||||
if( (next instanceof Group) == false )
|
||||
continue;
|
||||
Group grp = (Group) next;
|
||||
if( grp.getName().equals(name) )
|
||||
{
|
||||
roles = grp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we did not find a group create one
|
||||
if( roles == null )
|
||||
{
|
||||
roles = new SimpleGroup(name);
|
||||
principals.add(roles);
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
protected Group[] getRoleSets(Collection<String> roleSet)
|
||||
{
|
||||
SimpleGroup roles = new SimpleGroup("Roles");
|
||||
Group[] roleSets = {roles};
|
||||
for (String role : roleSet)
|
||||
{
|
||||
roles.addMember(new SimplePrincipal(role));
|
||||
}
|
||||
return roleSets;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,303 @@
|
|||
package org.keycloak.adapters.as7;
|
||||
|
||||
import org.apache.catalina.Lifecycle;
|
||||
import org.apache.catalina.LifecycleEvent;
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.LifecycleListener;
|
||||
import org.apache.catalina.Session;
|
||||
import org.apache.catalina.authenticator.Constants;
|
||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||
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.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeyPrincipal;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.as7.config.ManagedResourceConfigLoader;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Web deployment whose security is managed by a remote OAuth Skeleton Key authentication server
|
||||
* <p/>
|
||||
* Redirects browser to remote authentication server if not logged in. Also allows OAuth Bearer Token requests
|
||||
* that contain a Skeleton Key bearer tokens.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OAuthManagedResourceValve extends FormAuthenticator implements LifecycleListener
|
||||
{
|
||||
protected RealmConfiguration realmConfiguration;
|
||||
private static final Logger log = Logger.getLogger(OAuthManagedResourceValve.class);
|
||||
protected UserSessionManagement userSessionManagement = new UserSessionManagement();
|
||||
protected ManagedResourceConfig remoteSkeletonKeyConfig;
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
|
||||
|
||||
@Override
|
||||
public void start() throws LifecycleException
|
||||
{
|
||||
super.start();
|
||||
StandardContext standardContext = (StandardContext) context;
|
||||
standardContext.addLifecycleListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lifecycleEvent(LifecycleEvent event)
|
||||
{
|
||||
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
|
||||
}
|
||||
|
||||
protected void init()
|
||||
{
|
||||
ManagedResourceConfigLoader managedResourceConfigLoader = new ManagedResourceConfigLoader(context);
|
||||
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
|
||||
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
|
||||
String client_id = remoteSkeletonKeyConfig.getClientId();
|
||||
if (client_id == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Must set client-id to use with auth server");
|
||||
}
|
||||
realmConfiguration = new RealmConfiguration();
|
||||
String authUrl = remoteSkeletonKeyConfig.getAuthUrl();
|
||||
if (authUrl == null)
|
||||
{
|
||||
throw new RuntimeException("You must specify auth-url");
|
||||
}
|
||||
String tokenUrl = remoteSkeletonKeyConfig.getCodeUrl();
|
||||
if (tokenUrl == null)
|
||||
{
|
||||
throw new RuntimeException("You mut specify code-url");
|
||||
}
|
||||
realmConfiguration.setMetadata(resourceMetadata);
|
||||
realmConfiguration.setClientId(client_id);
|
||||
|
||||
for (Map.Entry<String, String> entry : managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getClientCredentials().entrySet())
|
||||
{
|
||||
realmConfiguration.getCredentials().param(entry.getKey(), entry.getValue());
|
||||
}
|
||||
int size = 10;
|
||||
if (managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getConnectionPoolSize() > 0)
|
||||
size = managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getConnectionPoolSize();
|
||||
ResteasyClientBuilder.HostnameVerificationPolicy policy = ResteasyClientBuilder.HostnameVerificationPolicy.WILDCARD;
|
||||
if (managedResourceConfigLoader.getRemoteSkeletonKeyConfig().isAllowAnyHostname())
|
||||
policy = ResteasyClientBuilder.HostnameVerificationPolicy.ANY;
|
||||
ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
|
||||
ClassLoader old = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(OAuthManagedResourceValve.class.getClassLoader());
|
||||
try
|
||||
{
|
||||
ResteasyProviderFactory.getInstance(); // initialize builtins
|
||||
RegisterBuiltin.register(providerFactory);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(old);
|
||||
}
|
||||
ResteasyClient client = new ResteasyClientBuilder()
|
||||
.providerFactory(providerFactory)
|
||||
.connectionPoolSize(size)
|
||||
.hostnameVerification(policy)
|
||||
.trustStore(resourceMetadata.getTruststore())
|
||||
.keyStore(resourceMetadata.getClientKeystore(), resourceMetadata.getClientKeyPassword())
|
||||
.build();
|
||||
realmConfiguration.setClient(client);
|
||||
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", client_id));
|
||||
realmConfiguration.setCodeUrl(client.target(tokenUrl));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(Request request, Response response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
String requestURI = request.getDecodedRequestURI();
|
||||
if (requestURI.endsWith("j_oauth_remote_logout"))
|
||||
{
|
||||
remoteLogout(request, response);
|
||||
return;
|
||||
}
|
||||
super.invoke(request, response);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (bearer(false, request, response)) return true;
|
||||
else if (checkLoggedIn(request, response))
|
||||
{
|
||||
if (request.getSessionInternal().getNote(Constants.FORM_REQUEST_NOTE) != null)
|
||||
{
|
||||
if (restoreRequest(request, request.getSessionInternal()))
|
||||
{
|
||||
log.debug("restoreRequest");
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("Restore of original request failed");
|
||||
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// initiate or continue oauth2 protocol
|
||||
oauth(request, response);
|
||||
}
|
||||
catch (LoginException e)
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void remoteLogout(Request request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
log.debug("->> remoteLogout: ");
|
||||
if (!bearer(true, request, response))
|
||||
{
|
||||
log.debug("remoteLogout: bearer auth failed");
|
||||
return;
|
||||
}
|
||||
GenericPrincipal gp = (GenericPrincipal) request.getPrincipal();
|
||||
if (!gp.hasRole(remoteSkeletonKeyConfig.getAdminRole()))
|
||||
{
|
||||
log.debug("remoteLogout: role failure");
|
||||
response.sendError(403);
|
||||
return;
|
||||
}
|
||||
String user = request.getParameter("user");
|
||||
if (user != null)
|
||||
{
|
||||
userSessionManagement.logout(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
userSessionManagement.logoutAll();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("failed to logout", e);
|
||||
}
|
||||
response.setStatus(204);
|
||||
}
|
||||
|
||||
protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException
|
||||
{
|
||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), !remoteSkeletonKeyConfig.isCancelPropagation(), challenge);
|
||||
if (bearer.login(request, response))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean checkLoggedIn(Request request, HttpServletResponse response)
|
||||
{
|
||||
if (request.getSessionInternal() == null || request.getSessionInternal().getPrincipal() == null)
|
||||
return false;
|
||||
log.debug("remote logged in already");
|
||||
GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal();
|
||||
request.setUserPrincipal(principal);
|
||||
request.setAuthType("OAUTH");
|
||||
Session session = request.getSessionInternal();
|
||||
if (session != null && !remoteSkeletonKeyConfig.isCancelPropagation())
|
||||
{
|
||||
SkeletonKeySession skSession = (SkeletonKeySession) session.getNote(SkeletonKeySession.class.getName());
|
||||
if (skSession != null)
|
||||
{
|
||||
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
|
||||
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always set the HTTP response, so do not continue after invoking
|
||||
*/
|
||||
protected void oauth(Request request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
ServletOAuthLogin oauth = new ServletOAuthLogin(realmConfiguration, request, response, request.getConnector().getRedirectPort());
|
||||
String code = oauth.getCode();
|
||||
if (code == null)
|
||||
{
|
||||
String error = oauth.getError();
|
||||
if (error != null)
|
||||
{
|
||||
response.sendError(400, "OAuth " + error);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
saveRequest(request, request.getSessionInternal(true));
|
||||
oauth.loginRedirect();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!oauth.resolveCode(code)) return;
|
||||
|
||||
SkeletonKeyToken token = oauth.getToken();
|
||||
Set<String> roles = null;
|
||||
if (resourceMetadata.getResourceName() != null)
|
||||
{
|
||||
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
||||
if (access != null) roles = access.getRoles();
|
||||
}
|
||||
else
|
||||
{
|
||||
SkeletonKeyToken.Access access = token.getRealmAccess();
|
||||
if (access != null) roles = access.getRoles();
|
||||
}
|
||||
SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getPrincipal(), null);
|
||||
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(context.getRealm(), skp, roles);
|
||||
Session session = request.getSessionInternal(true);
|
||||
session.setPrincipal(principal);
|
||||
session.setAuthType("OAUTH");
|
||||
if (!remoteSkeletonKeyConfig.isCancelPropagation())
|
||||
{
|
||||
SkeletonKeySession skSession = new SkeletonKeySession(oauth.getTokenString(), realmConfiguration.getMetadata());
|
||||
session.setNote(SkeletonKeySession.class.getName(), skSession);
|
||||
}
|
||||
|
||||
String username = token.getPrincipal();
|
||||
log.debug("userSessionManage.login: " + username);
|
||||
userSessionManagement.login(session, username);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
package org.keycloak.adapters.as7;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.VerificationException;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.jboss.resteasy.util.BasicAuthHelper;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.client.Entity;
|
||||
import javax.ws.rs.core.Form;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ServletOAuthLogin
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(ServletOAuthLogin.class);
|
||||
protected HttpServletRequest request;
|
||||
protected HttpServletResponse response;
|
||||
protected boolean codePresent;
|
||||
protected RealmConfiguration realmInfo;
|
||||
protected int redirectPort;
|
||||
protected String tokenString;
|
||||
protected SkeletonKeyToken token;
|
||||
|
||||
public ServletOAuthLogin(RealmConfiguration realmInfo, HttpServletRequest request, HttpServletResponse response, int redirectPort)
|
||||
{
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.realmInfo = realmInfo;
|
||||
this.redirectPort = redirectPort;
|
||||
}
|
||||
|
||||
public String getTokenString()
|
||||
{
|
||||
return tokenString;
|
||||
}
|
||||
|
||||
public SkeletonKeyToken getToken()
|
||||
{
|
||||
return token;
|
||||
}
|
||||
|
||||
public RealmConfiguration getRealmInfo()
|
||||
{
|
||||
return realmInfo;
|
||||
}
|
||||
|
||||
protected String getDefaultCookiePath()
|
||||
{
|
||||
String path = request.getContextPath();
|
||||
if ("".equals(path) || path == null) path = "/";
|
||||
return path;
|
||||
}
|
||||
|
||||
protected String getRequestUrl()
|
||||
{
|
||||
return request.getRequestURL().toString();
|
||||
}
|
||||
|
||||
protected boolean isRequestSecure()
|
||||
{
|
||||
return request.isSecure();
|
||||
}
|
||||
|
||||
protected void sendError(int code)
|
||||
{
|
||||
try
|
||||
{
|
||||
response.sendError(code);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendRedirect(String url)
|
||||
{
|
||||
try
|
||||
{
|
||||
response.sendRedirect(url);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected Cookie getCookie(String cookieName)
|
||||
{
|
||||
if (request.getCookies() == null) return null;
|
||||
for (Cookie cookie : request.getCookies())
|
||||
{
|
||||
if (cookie.getName().equals(cookieName))
|
||||
{
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getCookieValue(String cookieName)
|
||||
{
|
||||
Cookie cookie = getCookie(cookieName);
|
||||
if (cookie == null) return null;
|
||||
return cookie.getValue();
|
||||
}
|
||||
|
||||
protected String getQueryParamValue(String paramName)
|
||||
{
|
||||
String query = request.getQueryString();
|
||||
if (query == null) return null;
|
||||
String[] params = query.split("&");
|
||||
for (String param : params)
|
||||
{
|
||||
int eq = param.indexOf('=');
|
||||
if (eq == -1) continue;
|
||||
String name = param.substring(0, eq);
|
||||
if (!name.equals(paramName)) continue;
|
||||
return param.substring(eq + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getError()
|
||||
{
|
||||
return getQueryParamValue("error");
|
||||
}
|
||||
|
||||
public String getCode()
|
||||
{
|
||||
return getQueryParamValue("code");
|
||||
}
|
||||
|
||||
protected void setCookie(String name, String value, String domain, String path, boolean secure)
|
||||
{
|
||||
Cookie cookie = new Cookie(name, value);
|
||||
if (domain != null) cookie.setDomain(domain);
|
||||
if (path != null) cookie.setPath(path);
|
||||
if (secure) cookie.setSecure(true);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
|
||||
protected String getRedirectUri(String state)
|
||||
{
|
||||
String url = getRequestUrl();
|
||||
if (!isRequestSecure() && realmInfo.isSslRequired())
|
||||
{
|
||||
int port = redirectPort;
|
||||
if (port < 0)
|
||||
{
|
||||
// disabled?
|
||||
return null;
|
||||
}
|
||||
UriBuilder secureUrl = UriBuilder.fromUri(url).scheme("https").port(-1);
|
||||
if (port != 443) secureUrl.port(port);
|
||||
url = secureUrl.build().toString();
|
||||
}
|
||||
return realmInfo.getAuthUrl().clone()
|
||||
.queryParam("client_id", realmInfo.getClientId())
|
||||
.queryParam("redirect_uri", url)
|
||||
.queryParam("state", state)
|
||||
.queryParam("login", "true")
|
||||
.build().toString();
|
||||
}
|
||||
|
||||
protected static final AtomicLong counter = new AtomicLong();
|
||||
|
||||
protected String getStateCode()
|
||||
{
|
||||
return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public void loginRedirect()
|
||||
{
|
||||
String state = getStateCode();
|
||||
String redirect = getRedirectUri(state);
|
||||
if (redirect == null)
|
||||
{
|
||||
sendError(Response.Status.FORBIDDEN.getStatusCode());
|
||||
return;
|
||||
}
|
||||
setCookie(realmInfo.getStateCookieName(), state, null, getDefaultCookiePath(), realmInfo.isSslRequired());
|
||||
sendRedirect(redirect);
|
||||
}
|
||||
|
||||
public boolean checkStateCookie()
|
||||
{
|
||||
Cookie stateCookie = getCookie(realmInfo.getStateCookieName());
|
||||
|
||||
if (stateCookie == null)
|
||||
{
|
||||
sendError(400);
|
||||
log.warn("No state cookie");
|
||||
return false;
|
||||
}
|
||||
// reset the cookie
|
||||
Cookie reset = new Cookie(stateCookie.getName(), stateCookie.getValue());
|
||||
reset.setPath(stateCookie.getPath());
|
||||
reset.setMaxAge(0);
|
||||
response.addCookie(reset);
|
||||
|
||||
String stateCookieValue = getCookieValue(realmInfo.getStateCookieName());
|
||||
// its ok to call request.getParameter() because this should be a redirect
|
||||
String state = request.getParameter("state");
|
||||
if (state == null)
|
||||
{
|
||||
sendError(400);
|
||||
log.warn("state parameter was null");
|
||||
return false;
|
||||
}
|
||||
if (!state.equals(stateCookieValue))
|
||||
{
|
||||
sendError(400);
|
||||
log.warn("state parameter invalid");
|
||||
log.warn("cookie: " + stateCookieValue);
|
||||
log.warn("queryParam: " + state);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Start or continue the oauth login process.
|
||||
*
|
||||
* if code query parameter is not present, then browser is redirected to authUrl. The redirect URL will be
|
||||
* the URL of the current request.
|
||||
*
|
||||
* If code query parameter is present, then an access token is obtained by invoking a secure request to the codeUrl.
|
||||
* If the access token is obtained, the browser is again redirected to the current request URL, but any OAuth
|
||||
* protocol specific query parameters are removed.
|
||||
*
|
||||
* @return true if an access token was obtained
|
||||
*/
|
||||
public boolean resolveCode(String code)
|
||||
{
|
||||
// abort if not HTTPS
|
||||
if (realmInfo.isSslRequired() && !isRequestSecure())
|
||||
{
|
||||
log.error("SSL is required");
|
||||
sendError(Response.Status.FORBIDDEN.getStatusCode());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!checkStateCookie()) return false;
|
||||
|
||||
String client_id = realmInfo.getClientId();
|
||||
String password = realmInfo.getCredentials().asMap().getFirst("password");
|
||||
String authHeader = BasicAuthHelper.createHeader(client_id, password);
|
||||
String redirectUri = stripOauthParametersFromRedirect();
|
||||
Form form = new Form();
|
||||
form.param("grant_type", "authorization_code")
|
||||
.param("code", code)
|
||||
.param("redirect_uri", redirectUri);
|
||||
|
||||
Response res = realmInfo.getCodeUrl().request().header(HttpHeaders.AUTHORIZATION, authHeader).post(Entity.form(form));
|
||||
AccessTokenResponse tokenResponse;
|
||||
try
|
||||
{
|
||||
if (res.getStatus() != 200)
|
||||
{
|
||||
log.error("failed to turn code into token");
|
||||
sendError(Response.Status.FORBIDDEN.getStatusCode());
|
||||
return false;
|
||||
}
|
||||
log.debug("media type: " + res.getMediaType());
|
||||
log.debug("Content-Type header: " + res.getHeaderString("Content-Type"));
|
||||
tokenResponse = res.readEntity(AccessTokenResponse.class);
|
||||
}
|
||||
finally
|
||||
{
|
||||
res.close();
|
||||
}
|
||||
|
||||
tokenString = tokenResponse.getToken();
|
||||
try
|
||||
{
|
||||
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata());
|
||||
log.debug("Verification succeeded!");
|
||||
}
|
||||
catch (VerificationException e)
|
||||
{
|
||||
log.error("failed verification of token");
|
||||
sendError(Response.Status.FORBIDDEN.getStatusCode());
|
||||
return false;
|
||||
}
|
||||
// redirect to URL without oauth query parameters
|
||||
sendRedirect(redirectUri);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* strip out unwanted query parameters and redirect so bookmarks don't retain oauth protocol bits
|
||||
*/
|
||||
protected String stripOauthParametersFromRedirect()
|
||||
{
|
||||
StringBuffer buf = request.getRequestURL().append("?").append(request.getQueryString());
|
||||
UriBuilder builder = UriBuilder.fromUri(buf.toString())
|
||||
.replaceQueryParam("code", null)
|
||||
.replaceQueryParam("state", null);
|
||||
return builder.build().toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package org.keycloak.adapters.as7;
|
||||
|
||||
import org.apache.catalina.Session;
|
||||
import org.apache.catalina.SessionEvent;
|
||||
import org.apache.catalina.SessionListener;
|
||||
import org.apache.catalina.realm.GenericPrincipal;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Manages relationship to users and sessions so that forced admin logout can be implemented
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserSessionManagement implements SessionListener
|
||||
{
|
||||
private static final Logger log = Logger.getLogger(UserSessionManagement.class);
|
||||
protected ConcurrentHashMap<String, Map<String, Session>> userSessionMap = new ConcurrentHashMap<String, Map<String, Session>>();
|
||||
|
||||
protected void login(Session session, String username)
|
||||
{
|
||||
Map<String, Session> map = userSessionMap.get(username);
|
||||
if (map == null)
|
||||
{
|
||||
final Map<String, Session> value = new HashMap<String, Session>();
|
||||
map = userSessionMap.putIfAbsent(username, value);
|
||||
if (map == null)
|
||||
{
|
||||
map = value;
|
||||
}
|
||||
}
|
||||
synchronized (map)
|
||||
{
|
||||
map.put(session.getId(), session);
|
||||
}
|
||||
session.addSessionListener(this);
|
||||
}
|
||||
|
||||
public void logoutAll()
|
||||
{
|
||||
List<String> users = new ArrayList<String>();
|
||||
users.addAll(userSessionMap.keySet());
|
||||
for (String user : users) logout(user);
|
||||
}
|
||||
|
||||
public void logoutAllBut(String but)
|
||||
{
|
||||
List<String> users = new ArrayList<String>();
|
||||
users.addAll(userSessionMap.keySet());
|
||||
for (String user : users)
|
||||
{
|
||||
if (!but.equals(user)) logout(user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void logout(String user)
|
||||
{
|
||||
log.debug("logoutUser: " + user);
|
||||
Map<String, Session> map = userSessionMap.remove(user);
|
||||
if (map == null)
|
||||
{
|
||||
log.debug("no session for user: " + user);
|
||||
return;
|
||||
}
|
||||
log.debug("found session for user");
|
||||
synchronized (map)
|
||||
{
|
||||
for (Session session : map.values())
|
||||
{
|
||||
log.debug("invalidating session for user: " + user);
|
||||
session.setPrincipal(null);
|
||||
session.setAuthType(null);
|
||||
session.getSession().invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void sessionEvent(SessionEvent event)
|
||||
{
|
||||
// We only care about session destroyed events
|
||||
if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType())
|
||||
&& (!Session.SESSION_PASSIVATED_EVENT.equals(event.getType())))
|
||||
return;
|
||||
|
||||
// Look up the single session id associated with this session (if any)
|
||||
Session session = event.getSession();
|
||||
GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
|
||||
if (principal == null) return;
|
||||
session.setPrincipal(null);
|
||||
session.setAuthType(null);
|
||||
|
||||
String username = principal.getUserPrincipal().getName();
|
||||
Map<String, Session> map = userSessionMap.get(username);
|
||||
if (map == null) return;
|
||||
synchronized (map)
|
||||
{
|
||||
map.remove(session.getId());
|
||||
if (map.isEmpty()) userSessionMap.remove(username);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
package org.keycloak.adapters.as7.config;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AuthServerConfig
|
||||
{
|
||||
@JsonProperty("realm")
|
||||
protected String realm;
|
||||
|
||||
@JsonProperty("realm-private-key")
|
||||
protected String realmPrivateKey;
|
||||
|
||||
@JsonProperty("realm-public-key")
|
||||
protected String realmPublicKey;
|
||||
|
||||
@JsonProperty("realm-keystore")
|
||||
protected String realmKeyStore;
|
||||
|
||||
@JsonProperty("realm-keystore-password")
|
||||
protected String realmKeystorePassword;
|
||||
|
||||
@JsonProperty("realm-key-alias")
|
||||
protected String realmKeyAlias;
|
||||
|
||||
@JsonProperty("realm-private-key-password")
|
||||
protected String realmPrivateKeyPassword;
|
||||
|
||||
@JsonProperty("access-code-lifetime")
|
||||
protected int accessCodeLifetime;
|
||||
|
||||
@JsonProperty("token-lifetime")
|
||||
protected int tokenLifetime;
|
||||
|
||||
@JsonProperty("admin-role")
|
||||
protected String adminRole;
|
||||
|
||||
@JsonProperty("login-role")
|
||||
protected String loginRole;
|
||||
|
||||
@JsonProperty("oauth-client-role")
|
||||
protected String clientRole;
|
||||
|
||||
@JsonProperty("wildcard-role")
|
||||
protected String wildcardRole;
|
||||
|
||||
@JsonProperty("cancel-propagation")
|
||||
protected boolean cancelPropagation;
|
||||
|
||||
@JsonProperty("sso-disabled")
|
||||
protected boolean ssoDisabled;
|
||||
|
||||
// these properties are optional and used to provide connection metadata when the server wants to make
|
||||
// remote SSL connections
|
||||
|
||||
protected String truststore;
|
||||
@JsonProperty("truststore-password")
|
||||
protected String truststorePassword;
|
||||
@JsonProperty("client-keystore")
|
||||
protected String clientKeystore;
|
||||
@JsonProperty("client-keystore-password")
|
||||
protected String clientKeystorePassword;
|
||||
@JsonProperty("client-key-password")
|
||||
protected String clientKeyPassword;
|
||||
|
||||
protected List<String> resources = new ArrayList<String>();
|
||||
|
||||
|
||||
public String getRealm()
|
||||
{
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm)
|
||||
{
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getRealmPrivateKey()
|
||||
{
|
||||
return realmPrivateKey;
|
||||
}
|
||||
|
||||
public void setRealmPrivateKey(String realmPrivateKey)
|
||||
{
|
||||
this.realmPrivateKey = realmPrivateKey;
|
||||
}
|
||||
|
||||
public String getRealmPublicKey()
|
||||
{
|
||||
return realmPublicKey;
|
||||
}
|
||||
|
||||
public void setRealmPublicKey(String realmPublicKey)
|
||||
{
|
||||
this.realmPublicKey = realmPublicKey;
|
||||
}
|
||||
|
||||
public int getAccessCodeLifetime()
|
||||
{
|
||||
return accessCodeLifetime;
|
||||
}
|
||||
|
||||
public void setAccessCodeLifetime(int accessCodeLifetime)
|
||||
{
|
||||
this.accessCodeLifetime = accessCodeLifetime;
|
||||
}
|
||||
|
||||
public String getTruststore()
|
||||
{
|
||||
return truststore;
|
||||
}
|
||||
|
||||
public void setTruststore(String truststore)
|
||||
{
|
||||
this.truststore = truststore;
|
||||
}
|
||||
|
||||
public String getTruststorePassword()
|
||||
{
|
||||
return truststorePassword;
|
||||
}
|
||||
|
||||
public void setTruststorePassword(String truststorePassword)
|
||||
{
|
||||
this.truststorePassword = truststorePassword;
|
||||
}
|
||||
|
||||
public String getClientKeystore()
|
||||
{
|
||||
return clientKeystore;
|
||||
}
|
||||
|
||||
public void setClientKeystore(String clientKeystore)
|
||||
{
|
||||
this.clientKeystore = clientKeystore;
|
||||
}
|
||||
|
||||
public String getClientKeystorePassword()
|
||||
{
|
||||
return clientKeystorePassword;
|
||||
}
|
||||
|
||||
public void setClientKeystorePassword(String clientKeystorePassword)
|
||||
{
|
||||
this.clientKeystorePassword = clientKeystorePassword;
|
||||
}
|
||||
|
||||
public String getClientKeyPassword()
|
||||
{
|
||||
return clientKeyPassword;
|
||||
}
|
||||
|
||||
public void setClientKeyPassword(String clientKeyPassword)
|
||||
{
|
||||
this.clientKeyPassword = clientKeyPassword;
|
||||
}
|
||||
|
||||
public boolean isCancelPropagation()
|
||||
{
|
||||
return cancelPropagation;
|
||||
}
|
||||
|
||||
public void setCancelPropagation(boolean cancelPropagation)
|
||||
{
|
||||
this.cancelPropagation = cancelPropagation;
|
||||
}
|
||||
|
||||
public boolean isSsoDisabled()
|
||||
{
|
||||
return ssoDisabled;
|
||||
}
|
||||
|
||||
public void setSsoDisabled(boolean ssoDisabled)
|
||||
{
|
||||
this.ssoDisabled = ssoDisabled;
|
||||
}
|
||||
|
||||
public List<String> getResources()
|
||||
{
|
||||
return resources;
|
||||
}
|
||||
|
||||
public String getAdminRole()
|
||||
{
|
||||
return adminRole;
|
||||
}
|
||||
|
||||
public void setAdminRole(String adminRole)
|
||||
{
|
||||
this.adminRole = adminRole;
|
||||
}
|
||||
|
||||
public String getLoginRole()
|
||||
{
|
||||
return loginRole;
|
||||
}
|
||||
|
||||
public void setLoginRole(String loginRole)
|
||||
{
|
||||
this.loginRole = loginRole;
|
||||
}
|
||||
|
||||
public String getClientRole()
|
||||
{
|
||||
return clientRole;
|
||||
}
|
||||
|
||||
public void setClientRole(String clientRole)
|
||||
{
|
||||
this.clientRole = clientRole;
|
||||
}
|
||||
|
||||
public String getWildcardRole()
|
||||
{
|
||||
return wildcardRole;
|
||||
}
|
||||
|
||||
public void setWildcardRole(String wildcardRole)
|
||||
{
|
||||
this.wildcardRole = wildcardRole;
|
||||
}
|
||||
|
||||
public String getRealmKeyStore()
|
||||
{
|
||||
return realmKeyStore;
|
||||
}
|
||||
|
||||
public void setRealmKeyStore(String realmKeyStore)
|
||||
{
|
||||
this.realmKeyStore = realmKeyStore;
|
||||
}
|
||||
|
||||
public String getRealmKeystorePassword()
|
||||
{
|
||||
return realmKeystorePassword;
|
||||
}
|
||||
|
||||
public void setRealmKeystorePassword(String realmKeystorePassword)
|
||||
{
|
||||
this.realmKeystorePassword = realmKeystorePassword;
|
||||
}
|
||||
|
||||
public String getRealmKeyAlias()
|
||||
{
|
||||
return realmKeyAlias;
|
||||
}
|
||||
|
||||
public void setRealmKeyAlias(String realmKeyAlias)
|
||||
{
|
||||
this.realmKeyAlias = realmKeyAlias;
|
||||
}
|
||||
|
||||
public String getRealmPrivateKeyPassword()
|
||||
{
|
||||
return realmPrivateKeyPassword;
|
||||
}
|
||||
|
||||
public void setRealmPrivateKeyPassword(String realmPrivateKeyPassword)
|
||||
{
|
||||
this.realmPrivateKeyPassword = realmPrivateKeyPassword;
|
||||
}
|
||||
|
||||
public int getTokenLifetime()
|
||||
{
|
||||
return tokenLifetime;
|
||||
}
|
||||
|
||||
public void setTokenLifetime(int tokenLifetime)
|
||||
{
|
||||
this.tokenLifetime = tokenLifetime;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
package org.keycloak.adapters.as7.config;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonProperty;
|
||||
import org.codehaus.jackson.annotate.JsonPropertyOrder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@JsonPropertyOrder({"realm", "resource", "realm-public-key", "admin-role", "auth-url", "code-url", "truststore", "truststore-password", "client-id", "client-credentials"})
|
||||
public class ManagedResourceConfig
|
||||
{
|
||||
@JsonProperty("realm")
|
||||
protected String realm;
|
||||
@JsonProperty("resource")
|
||||
protected String resource;
|
||||
|
||||
@JsonProperty("realm-public-key")
|
||||
protected String realmKey;
|
||||
|
||||
@JsonProperty("admin-role")
|
||||
protected String adminRole;
|
||||
|
||||
@JsonProperty("auth-url")
|
||||
protected String authUrl;
|
||||
@JsonProperty("code-url")
|
||||
protected String codeUrl;
|
||||
|
||||
@JsonProperty("allow-any-hostname")
|
||||
protected boolean allowAnyHostname;
|
||||
|
||||
@JsonProperty("truststore")
|
||||
protected String truststore;
|
||||
|
||||
@JsonProperty("truststore-password")
|
||||
protected String truststorePassword;
|
||||
@JsonProperty("client-id")
|
||||
protected String clientId;
|
||||
@JsonProperty("client-keystore")
|
||||
protected String clientKeystore;
|
||||
@JsonProperty("client-keystore-password")
|
||||
protected String clientKeystorePassword;
|
||||
@JsonProperty("client-key-password")
|
||||
protected String clientKeyPassword;
|
||||
|
||||
@JsonProperty("client-credentials")
|
||||
protected Map<String, String> clientCredentials = new HashMap<String, String>();
|
||||
|
||||
@JsonProperty("connection-pool-size")
|
||||
protected int connectionPoolSize;
|
||||
|
||||
@JsonProperty("cancel-propagation")
|
||||
protected boolean cancelPropagation;
|
||||
|
||||
|
||||
public String getRealm()
|
||||
{
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm)
|
||||
{
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getResource()
|
||||
{
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource)
|
||||
{
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public String getRealmKey()
|
||||
{
|
||||
return realmKey;
|
||||
}
|
||||
|
||||
public void setRealmKey(String realmKey)
|
||||
{
|
||||
this.realmKey = realmKey;
|
||||
}
|
||||
|
||||
public String getAuthUrl()
|
||||
{
|
||||
return authUrl;
|
||||
}
|
||||
|
||||
public void setAuthUrl(String authUrl)
|
||||
{
|
||||
this.authUrl = authUrl;
|
||||
}
|
||||
|
||||
public String getCodeUrl()
|
||||
{
|
||||
return codeUrl;
|
||||
}
|
||||
|
||||
public void setCodeUrl(String codeUrl)
|
||||
{
|
||||
this.codeUrl = codeUrl;
|
||||
}
|
||||
|
||||
public boolean isAllowAnyHostname()
|
||||
{
|
||||
return allowAnyHostname;
|
||||
}
|
||||
|
||||
public void setAllowAnyHostname(boolean allowAnyHostname)
|
||||
{
|
||||
this.allowAnyHostname = allowAnyHostname;
|
||||
}
|
||||
|
||||
public String getTruststore()
|
||||
{
|
||||
return truststore;
|
||||
}
|
||||
|
||||
public void setTruststore(String truststore)
|
||||
{
|
||||
this.truststore = truststore;
|
||||
}
|
||||
|
||||
public String getTruststorePassword()
|
||||
{
|
||||
return truststorePassword;
|
||||
}
|
||||
|
||||
public void setTruststorePassword(String truststorePassword)
|
||||
{
|
||||
this.truststorePassword = truststorePassword;
|
||||
}
|
||||
|
||||
public String getClientId()
|
||||
{
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId)
|
||||
{
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public Map<String, String> getClientCredentials()
|
||||
{
|
||||
return clientCredentials;
|
||||
}
|
||||
|
||||
public String getClientKeystore()
|
||||
{
|
||||
return clientKeystore;
|
||||
}
|
||||
|
||||
public void setClientKeystore(String clientKeystore)
|
||||
{
|
||||
this.clientKeystore = clientKeystore;
|
||||
}
|
||||
|
||||
public String getClientKeystorePassword()
|
||||
{
|
||||
return clientKeystorePassword;
|
||||
}
|
||||
|
||||
public void setClientKeystorePassword(String clientKeystorePassword)
|
||||
{
|
||||
this.clientKeystorePassword = clientKeystorePassword;
|
||||
}
|
||||
|
||||
public String getClientKeyPassword()
|
||||
{
|
||||
return clientKeyPassword;
|
||||
}
|
||||
|
||||
public void setClientKeyPassword(String clientKeyPassword)
|
||||
{
|
||||
this.clientKeyPassword = clientKeyPassword;
|
||||
}
|
||||
|
||||
public int getConnectionPoolSize()
|
||||
{
|
||||
return connectionPoolSize;
|
||||
}
|
||||
|
||||
public void setConnectionPoolSize(int connectionPoolSize)
|
||||
{
|
||||
this.connectionPoolSize = connectionPoolSize;
|
||||
}
|
||||
|
||||
public boolean isCancelPropagation()
|
||||
{
|
||||
return cancelPropagation;
|
||||
}
|
||||
|
||||
public void setCancelPropagation(boolean cancelPropagation)
|
||||
{
|
||||
this.cancelPropagation = cancelPropagation;
|
||||
}
|
||||
|
||||
public String getAdminRole()
|
||||
{
|
||||
return adminRole;
|
||||
}
|
||||
|
||||
public void setAdminRole(String adminRole)
|
||||
{
|
||||
this.adminRole = adminRole;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package org.keycloak.adapters.as7.config;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.EnvUtil;
|
||||
import org.keycloak.PemUtils;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class ManagedResourceConfigLoader
|
||||
{
|
||||
static final Logger log = Logger.getLogger(ManagedResourceConfigLoader.class);
|
||||
protected ManagedResourceConfig remoteSkeletonKeyConfig;
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
|
||||
public ManagedResourceConfigLoader(Context context)
|
||||
{
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
||||
InputStream is = null;
|
||||
String path = context.getServletContext().getInitParameter("skeleton.key.config.file");
|
||||
if (path == null)
|
||||
{
|
||||
is = context.getServletContext().getResourceAsStream("/WEB-INF/resteasy-oauth.json");
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
is = new FileInputStream(path);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
remoteSkeletonKeyConfig = null;
|
||||
try
|
||||
{
|
||||
remoteSkeletonKeyConfig = mapper.readValue(is, ManagedResourceConfig.class);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String name = remoteSkeletonKeyConfig.getResource();
|
||||
String realm = remoteSkeletonKeyConfig.getRealm();
|
||||
if (realm == null) throw new RuntimeException("Must set 'realm' in config");
|
||||
|
||||
String realmKeyPem = remoteSkeletonKeyConfig.getRealmKey();
|
||||
if (realmKeyPem == null)
|
||||
{
|
||||
throw new IllegalArgumentException("You must set the realm-public-key");
|
||||
}
|
||||
|
||||
PublicKey realmKey = null;
|
||||
try
|
||||
{
|
||||
realmKey = PemUtils.decodePublicKey(realmKeyPem);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
resourceMetadata = new ResourceMetadata();
|
||||
resourceMetadata.setRealm(realm);
|
||||
resourceMetadata.setResourceName(name);
|
||||
resourceMetadata.setRealmKey(realmKey);
|
||||
|
||||
|
||||
String truststore = remoteSkeletonKeyConfig.getTruststore();
|
||||
if (truststore != null)
|
||||
{
|
||||
truststore = EnvUtil.replace(truststore);
|
||||
String truststorePassword = remoteSkeletonKeyConfig.getTruststorePassword();
|
||||
KeyStore trust = null;
|
||||
try
|
||||
{
|
||||
trust = loadKeyStore(truststore, truststorePassword);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException("Failed to load truststore", e);
|
||||
}
|
||||
resourceMetadata.setTruststore(trust);
|
||||
}
|
||||
String clientKeystore = remoteSkeletonKeyConfig.getClientKeystore();
|
||||
String clientKeyPassword = null;
|
||||
if (clientKeystore != null)
|
||||
{
|
||||
clientKeystore = EnvUtil.replace(clientKeystore);
|
||||
String clientKeystorePassword = remoteSkeletonKeyConfig.getClientKeystorePassword();
|
||||
KeyStore serverKS = null;
|
||||
try
|
||||
{
|
||||
serverKS = loadKeyStore(clientKeystore, clientKeystorePassword);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException("Failed to load keystore", e);
|
||||
}
|
||||
resourceMetadata.setClientKeystore(serverKS);
|
||||
clientKeyPassword = remoteSkeletonKeyConfig.getClientKeyPassword();
|
||||
resourceMetadata.setClientKeyPassword(clientKeyPassword);
|
||||
}
|
||||
|
||||
}
|
||||
public static KeyStore loadKeyStore(String filename, String password) throws Exception
|
||||
{
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore
|
||||
.getDefaultType());
|
||||
File truststoreFile = new File(filename);
|
||||
FileInputStream trustStream = new FileInputStream(truststoreFile);
|
||||
trustStore.load(trustStream, password.toCharArray());
|
||||
trustStream.close();
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public ManagedResourceConfig getRemoteSkeletonKeyConfig()
|
||||
{
|
||||
return remoteSkeletonKeyConfig;
|
||||
}
|
||||
|
||||
public ResourceMetadata getResourceMetadata()
|
||||
{
|
||||
return resourceMetadata;
|
||||
}
|
||||
|
||||
}
|
21
integration/pom.xml
Executable file
21
integration/pom.xml
Executable file
|
@ -0,0 +1,21 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-alpha-1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Integration</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>integration-pom</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>as7-eap6/adapter</module>
|
||||
<!-- <module>as7-eap6/jboss-modules</module> -->
|
||||
</modules>
|
||||
</project>
|
1
pom.xml
1
pom.xml
|
@ -54,6 +54,7 @@
|
|||
<modules>
|
||||
<module>core</module>
|
||||
<module>services</module>
|
||||
<module>integration</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
|
@ -20,10 +20,14 @@ public class InstallationManager {
|
|||
defaultRealm.setAccessCodeLifespan(60);
|
||||
defaultRealm.setSslNotRequired(false);
|
||||
defaultRealm.setCookieLoginAllowed(true);
|
||||
defaultRealm.setRegistrationAllowed(true);
|
||||
manager.generateRealmKeys(defaultRealm);
|
||||
defaultRealm.updateRealm();
|
||||
defaultRealm.addRequiredCredential(RequiredCredentialModel.PASSWORD);
|
||||
defaultRealm.getIdm().add(new SimpleRole(RegistrationService.REALM_CREATOR_ROLE));
|
||||
}
|
||||
|
||||
public boolean isInstalled(RealmManager manager) {
|
||||
return manager.defaultRealm() != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.picketlink.idm.model.Attribute;
|
|||
import org.picketlink.idm.model.Grant;
|
||||
import org.picketlink.idm.model.Realm;
|
||||
import org.picketlink.idm.model.Role;
|
||||
import org.picketlink.idm.model.SimpleAgent;
|
||||
import org.picketlink.idm.model.Tier;
|
||||
import org.picketlink.idm.model.User;
|
||||
import org.picketlink.idm.query.IdentityQuery;
|
||||
|
@ -48,21 +47,22 @@ public class RealmModel {
|
|||
public static final String REALM_PUBLIC_KEY = "publicKey";
|
||||
public static final String REALM_IS_SSL_NOT_REQUIRED = "isSSLNotRequired";
|
||||
public static final String REALM_IS_COOKIE_LOGIN_ALLOWED = "isCookieLoginAllowed";
|
||||
public static final String REALM_IS_REGISTRATION_ALLOWED = "isRegistrationAllowed";
|
||||
|
||||
protected Realm realm;
|
||||
protected Agent realmAgent;
|
||||
protected IdentitySession IdentitySession;
|
||||
protected IdentitySession identitySession;
|
||||
protected volatile transient PublicKey publicKey;
|
||||
protected volatile transient PrivateKey privateKey;
|
||||
|
||||
public RealmModel(Realm realm, IdentitySession factory) {
|
||||
public RealmModel(Realm realm, IdentitySession session) {
|
||||
this.realm = realm;
|
||||
this.IdentitySession = factory;
|
||||
this.identitySession = session;
|
||||
realmAgent = getIdm().getAgent(REALM_AGENT_ID);
|
||||
}
|
||||
|
||||
public IdentityManager getIdm() {
|
||||
return IdentitySession.createIdentityManager(realm);
|
||||
return identitySession.createIdentityManager(realm);
|
||||
}
|
||||
|
||||
public void updateRealm() {
|
||||
|
@ -105,6 +105,14 @@ public class RealmModel {
|
|||
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_COOKIE_LOGIN_ALLOWED, cookieLoginAllowed));
|
||||
}
|
||||
|
||||
public boolean isRegistrationAllowed() {
|
||||
return (Boolean) realmAgent.getAttribute(REALM_IS_REGISTRATION_ALLOWED).getValue();
|
||||
}
|
||||
|
||||
public void setRegistrationAllowed(boolean registrationAllowed) {
|
||||
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_REGISTRATION_ALLOWED, registrationAllowed));
|
||||
}
|
||||
|
||||
public long getTokenLifespan() {
|
||||
return (Long) realmAgent.getAttribute(REALM_TOKEN_LIFESPAN).getValue();
|
||||
}
|
||||
|
@ -269,8 +277,8 @@ public class RealmModel {
|
|||
List<ResourceRelationship> results = query.getResultList();
|
||||
List<ResourceModel> resources = new ArrayList<ResourceModel>();
|
||||
for (ResourceRelationship relationship : results) {
|
||||
Tier resourceTier = IdentitySession.findTier(relationship.getResourceId());
|
||||
ResourceModel model = new ResourceModel(resourceTier,relationship, this, IdentitySession);
|
||||
Tier resourceTier = identitySession.findTier(relationship.getResourceId());
|
||||
ResourceModel model = new ResourceModel(resourceTier,relationship, this, identitySession);
|
||||
resources.add(model);
|
||||
}
|
||||
|
||||
|
@ -278,14 +286,14 @@ public class RealmModel {
|
|||
}
|
||||
|
||||
public ResourceModel addResource(String name) {
|
||||
Tier newTier = IdentitySession.createTier(RealmManager.generateId());
|
||||
Tier newTier = identitySession.createTier(RealmManager.generateId());
|
||||
IdentityManager idm = getIdm();
|
||||
ResourceRelationship relationship = new ResourceRelationship();
|
||||
relationship.setResourceName(name);
|
||||
relationship.setRealmAgent(realmAgent);
|
||||
relationship.setResourceId(newTier.getId());
|
||||
idm.add(relationship);
|
||||
return new ResourceModel(newTier, relationship, this, IdentitySession);
|
||||
return new ResourceModel(newTier, relationship, this, identitySession);
|
||||
}
|
||||
|
||||
public Set<String> getRoleMappings(User user) {
|
||||
|
@ -322,7 +330,7 @@ public class RealmModel {
|
|||
}
|
||||
|
||||
public boolean isRealmAdmin(Agent agent) {
|
||||
IdentityManager idm = new RealmManager(IdentitySession).defaultRealm().getIdm();
|
||||
IdentityManager idm = new RealmManager(identitySession).defaultRealm().getIdm();
|
||||
RelationshipQuery<RealmAdminRelationship> query = idm.createRelationshipQuery(RealmAdminRelationship.class);
|
||||
query.setParameter(RealmAdminRelationship.REALM, realm.getId());
|
||||
query.setParameter(RealmAdminRelationship.ADMIN, agent);
|
||||
|
@ -331,7 +339,7 @@ public class RealmModel {
|
|||
}
|
||||
|
||||
public void addRealmAdmin(Agent agent) {
|
||||
IdentityManager idm = new RealmManager(IdentitySession).defaultRealm().getIdm();
|
||||
IdentityManager idm = new RealmManager(identitySession).defaultRealm().getIdm();
|
||||
RealmAdminRelationship relationship = new RealmAdminRelationship();
|
||||
relationship.setAdmin(agent);
|
||||
relationship.setRealm(realm.getId());
|
||||
|
|
|
@ -11,6 +11,7 @@ import org.picketlink.idm.model.SimpleUser;
|
|||
import org.picketlink.idm.model.User;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.ForbiddenException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Context;
|
||||
|
@ -32,15 +33,21 @@ public class RegistrationService {
|
|||
protected UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
protected IdentitySession IdentitySession;
|
||||
protected IdentitySession identitySession;
|
||||
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response register(UserRepresentation newUser) {
|
||||
IdentitySession.getTransaction().begin();
|
||||
identitySession.getTransaction().begin();
|
||||
try {
|
||||
RealmManager realmManager = new RealmManager(IdentitySession);
|
||||
RealmManager realmManager = new RealmManager(identitySession);
|
||||
RealmModel defaultRealm = realmManager.defaultRealm();
|
||||
if (!defaultRealm.isEnabled()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
if (!defaultRealm.isRegistrationAllowed()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
User user = defaultRealm.getIdm().getUser(newUser.getUsername());
|
||||
if (user != null) {
|
||||
return Response.status(400).type("text/plain").entity("user exists").build();
|
||||
|
@ -56,12 +63,12 @@ public class RegistrationService {
|
|||
}
|
||||
Role realmCreator = defaultRealm.getIdm().getRole(REALM_CREATOR_ROLE);
|
||||
defaultRealm.getIdm().grantRole(user, realmCreator);
|
||||
IdentitySession.getTransaction().commit();
|
||||
identitySession.getTransaction().commit();
|
||||
URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
|
||||
return Response.created(uri).build();
|
||||
} catch (RuntimeException e) {
|
||||
logger.error("Failed to register", e);
|
||||
IdentitySession.getTransaction().rollback();
|
||||
identitySession.getTransaction().rollback();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue