commit
bdfb480279
43 changed files with 5062 additions and 2124 deletions
|
@ -36,7 +36,7 @@ public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper>
|
||||||
@Override
|
@Override
|
||||||
public ObjectMapper getContext(Class<?> type)
|
public ObjectMapper getContext(Class<?> type)
|
||||||
{
|
{
|
||||||
if (type.getPackage().getName().startsWith("org.jboss.resteasy.skeleton.key")) return mapper;
|
if (type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
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>
|
12
pom.xml
12
pom.xml
|
@ -54,6 +54,7 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>services</module>
|
<module>services</module>
|
||||||
|
<module>integration</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -108,6 +109,12 @@
|
||||||
<artifactId>jose-jwt</artifactId>
|
<artifactId>jose-jwt</artifactId>
|
||||||
<version>${resteasy.version}</version>
|
<version>${resteasy.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
|
<artifactId>tjws</artifactId>
|
||||||
|
<version>${resteasy.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.codehaus.jackson</groupId>
|
<groupId>org.codehaus.jackson</groupId>
|
||||||
<artifactId>jackson-core-asl</artifactId>
|
<artifactId>jackson-core-asl</artifactId>
|
||||||
|
@ -163,6 +170,11 @@
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.11</version>
|
<version>4.11</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate.javax.persistence</groupId>
|
||||||
|
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||||
|
<version>1.0.1.Final</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,25 @@
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>resteasy-jaxrs</artifactId>
|
<artifactId>resteasy-jaxrs</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>log4j</groupId>
|
||||||
|
<artifactId>log4j</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
|
<artifactId>tjws</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
|
@ -94,6 +113,23 @@
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate.javax.persistence</groupId>
|
||||||
|
<artifactId>hibernate-jpa-2.0-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<version>1.3.161</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-entitymanager</artifactId>
|
||||||
|
<version>3.6.6.Final</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.keycloak.services.filters;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
|
import org.picketlink.idm.IdentitySessionFactory;
|
||||||
|
|
||||||
|
import javax.ws.rs.container.ContainerRequestContext;
|
||||||
|
import javax.ws.rs.container.ContainerRequestFilter;
|
||||||
|
import javax.ws.rs.container.ContainerResponseContext;
|
||||||
|
import javax.ws.rs.container.ContainerResponseFilter;
|
||||||
|
import javax.ws.rs.container.PreMatching;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@PreMatching
|
||||||
|
public class IdentitySessionFilter implements ContainerRequestFilter, ContainerResponseFilter {
|
||||||
|
protected IdentitySessionFactory factory;
|
||||||
|
|
||||||
|
public IdentitySessionFilter(IdentitySessionFactory factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void filter(ContainerRequestContext requestContext) throws IOException {
|
||||||
|
IdentitySession ctx = factory.createIdentitySession();
|
||||||
|
requestContext.setProperty(IdentitySession.class.getName(), ctx);
|
||||||
|
ResteasyProviderFactory.pushContext(IdentitySession.class, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
|
||||||
|
IdentitySession ctx = (IdentitySession)requestContext.getProperty(IdentitySession.class.getName());
|
||||||
|
if (ctx != null) ctx.close();
|
||||||
|
}
|
||||||
|
}
|
49
services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java
Executable file
49
services/src/main/java/org/keycloak/services/managers/AccessCodeEntry.java
Executable file
|
@ -0,0 +1,49 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AccessCodeEntry {
|
||||||
|
protected String id = UUID.randomUUID().toString() + System.currentTimeMillis();
|
||||||
|
protected long expiration;
|
||||||
|
protected SkeletonKeyToken token;
|
||||||
|
protected User client;
|
||||||
|
|
||||||
|
public boolean isExpired() {
|
||||||
|
return expiration != 0 && (System.currentTimeMillis() / 1000) > expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getExpiration() {
|
||||||
|
return expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpiration(long expiration) {
|
||||||
|
this.expiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkeletonKeyToken getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(SkeletonKeyToken token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getClient() {
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClient(User client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,27 +24,28 @@ 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 AuthenticationManager
|
public class AuthenticationManager {
|
||||||
{
|
|
||||||
protected Logger logger = Logger.getLogger(AuthenticationManager.class);
|
protected Logger logger = Logger.getLogger(AuthenticationManager.class);
|
||||||
public static final String FORM_USERNAME = "username";
|
public static final String FORM_USERNAME = "username";
|
||||||
protected RealmManager adapter;
|
|
||||||
|
|
||||||
public AuthenticationManager(RealmManager adapter)
|
/**
|
||||||
{
|
* Grabs token from headers, authenticates, authorizes
|
||||||
this.adapter = adapter;
|
*
|
||||||
|
* @param realm
|
||||||
|
* @param headers
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isRealmAdmin(RealmModel realm, HttpHeaders headers) {
|
||||||
|
User user = authenticateToken(realm, headers);
|
||||||
|
return realm.isRealmAdmin(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public User authenticateToken(RealmModel realm, HttpHeaders headers)
|
public User authenticateToken(RealmModel realm, HttpHeaders headers) {
|
||||||
{
|
|
||||||
String tokenString = null;
|
String tokenString = null;
|
||||||
String authHeader = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
|
String authHeader = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
|
||||||
if (authHeader == null)
|
if (authHeader == null) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Bearer");
|
throw new NotAuthorizedException("Bearer");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
String[] split = authHeader.trim().split("\\s+");
|
String[] split = authHeader.trim().split("\\s+");
|
||||||
if (split == null || split.length != 2) throw new NotAuthorizedException("Bearer");
|
if (split == null || split.length != 2) throw new NotAuthorizedException("Bearer");
|
||||||
if (!split[0].equalsIgnoreCase("Bearer")) throw new NotAuthorizedException("Bearer");
|
if (!split[0].equalsIgnoreCase("Bearer")) throw new NotAuthorizedException("Bearer");
|
||||||
|
@ -52,51 +53,40 @@ public class AuthenticationManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getId());
|
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getId());
|
||||||
if (!token.isActive())
|
if (!token.isActive()) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("token_expired");
|
throw new NotAuthorizedException("token_expired");
|
||||||
}
|
}
|
||||||
User user = realm.getIdm().getUser(token.getPrincipal());
|
User user = realm.getIdm().getUser(token.getPrincipal());
|
||||||
if (user == null || !user.isEnabled())
|
if (user == null || !user.isEnabled()) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("invalid_user");
|
throw new NotAuthorizedException("invalid_user");
|
||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
} catch (VerificationException e) {
|
||||||
catch (VerificationException e)
|
|
||||||
{
|
|
||||||
logger.error("Failed to verify token", e);
|
logger.error("Failed to verify token", e);
|
||||||
throw new NotAuthorizedException("invalid_token");
|
throw new NotAuthorizedException("invalid_token");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean authenticateForm(RealmModel realm, User user, MultivaluedMap<String, String> formData)
|
public boolean authenticateForm(RealmModel realm, User user, MultivaluedMap<String, String> formData) {
|
||||||
{
|
|
||||||
String username = user.getLoginName();
|
String username = user.getLoginName();
|
||||||
Set<String> types = new HashSet<String>();
|
Set<String> types = new HashSet<String>();
|
||||||
|
|
||||||
for (RequiredCredentialModel credential : realm.getRequiredCredentials())
|
for (RequiredCredentialModel credential : realm.getRequiredCredentials()) {
|
||||||
{
|
|
||||||
types.add(credential.getType());
|
types.add(credential.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (types.contains(RequiredCredentialRepresentation.PASSWORD))
|
if (types.contains(RequiredCredentialRepresentation.PASSWORD)) {
|
||||||
{
|
|
||||||
String password = formData.getFirst(RequiredCredentialRepresentation.PASSWORD);
|
String password = formData.getFirst(RequiredCredentialRepresentation.PASSWORD);
|
||||||
if (password == null)
|
if (password == null) {
|
||||||
{
|
|
||||||
logger.warn("Password not provided");
|
logger.warn("Password not provided");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (types.contains(RequiredCredentialRepresentation.TOTP))
|
if (types.contains(RequiredCredentialRepresentation.TOTP)) {
|
||||||
{
|
|
||||||
String token = formData.getFirst(RequiredCredentialRepresentation.TOTP);
|
String token = formData.getFirst(RequiredCredentialRepresentation.TOTP);
|
||||||
if (token == null)
|
if (token == null) {
|
||||||
{
|
|
||||||
logger.warn("TOTP token not provided");
|
logger.warn("TOTP token not provided");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -105,23 +95,17 @@ public class AuthenticationManager
|
||||||
creds.setUsername(username);
|
creds.setUsername(username);
|
||||||
creds.setPassword(new Password(password));
|
creds.setPassword(new Password(password));
|
||||||
realm.getIdm().validateCredentials(creds);
|
realm.getIdm().validateCredentials(creds);
|
||||||
if (creds.getStatus() != Credentials.Status.VALID)
|
if (creds.getStatus() != Credentials.Status.VALID) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, new Password(password));
|
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, new Password(password));
|
||||||
realm.getIdm().validateCredentials(creds);
|
realm.getIdm().validateCredentials(creds);
|
||||||
if (creds.getStatus() != Credentials.Status.VALID)
|
if (creds.getStatus() != Credentials.Status.VALID) {
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.warn("Do not know how to authenticate user");
|
logger.warn("Do not know how to authenticate user");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.services.models.RealmManager;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
import org.keycloak.services.models.RequiredCredentialModel;
|
||||||
|
import org.keycloak.services.resources.RegistrationService;
|
||||||
|
import org.picketlink.idm.model.Realm;
|
||||||
|
import org.picketlink.idm.model.SimpleRole;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class InstallationManager {
|
||||||
|
public void install(RealmManager manager) {
|
||||||
|
RealmModel defaultRealm = manager.createRealm(Realm.DEFAULT_REALM, Realm.DEFAULT_REALM);
|
||||||
|
defaultRealm.setName(Realm.DEFAULT_REALM);
|
||||||
|
defaultRealm.setEnabled(true);
|
||||||
|
defaultRealm.setTokenLifespan(300);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,43 +21,30 @@ 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 TokenManager
|
public class TokenManager {
|
||||||
{
|
|
||||||
protected RealmManager adapter;
|
|
||||||
|
|
||||||
public TokenManager(RealmManager adapter)
|
public SkeletonKeyToken createScopedToken(SkeletonKeyScope scope, RealmModel realm, User client, User user) {
|
||||||
{
|
|
||||||
this.adapter = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SkeletonKeyToken createScopedToken(SkeletonKeyScope scope, RealmModel realm, User client, User user)
|
|
||||||
{
|
|
||||||
SkeletonKeyToken token = new SkeletonKeyToken();
|
SkeletonKeyToken token = new SkeletonKeyToken();
|
||||||
token.id(adapter.generateId());
|
token.id(RealmManager.generateId());
|
||||||
token.principal(user.getLoginName());
|
token.principal(user.getLoginName());
|
||||||
token.audience(realm.getName());
|
token.audience(realm.getName());
|
||||||
token.issuedNow();
|
token.issuedNow();
|
||||||
token.issuedFor(client.getLoginName());
|
token.issuedFor(client.getLoginName());
|
||||||
if (realm.getTokenLifespan() > 0)
|
if (realm.getTokenLifespan() > 0) {
|
||||||
{
|
|
||||||
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
||||||
}
|
}
|
||||||
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
|
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
|
||||||
|
|
||||||
for (String res : scope.keySet())
|
for (String res : scope.keySet()) {
|
||||||
{
|
|
||||||
ResourceModel resource = resourceMap.get(res);
|
ResourceModel resource = resourceMap.get(res);
|
||||||
Set<String> scopeMapping = resource.getScope(client);
|
Set<String> scopeMapping = resource.getScope(client);
|
||||||
Set<String> roleMapping = resource.getRoleMappings(user);
|
Set<String> roleMapping = resource.getRoleMappings(user);
|
||||||
SkeletonKeyToken.Access access = token.addAccess(resource.getName());
|
SkeletonKeyToken.Access access = token.addAccess(resource.getName());
|
||||||
for (String role : scope.get(res))
|
for (String role : scope.get(res)) {
|
||||||
{
|
if (!scopeMapping.contains("*") && !scopeMapping.contains(role)) {
|
||||||
if (!scopeMapping.contains("*") && !scopeMapping.contains(role))
|
|
||||||
{
|
|
||||||
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized for the requested scope.</p>").type("text/html").build());
|
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized for the requested scope.</p>").type("text/html").build());
|
||||||
}
|
}
|
||||||
if (!roleMapping.contains(role))
|
if (!roleMapping.contains(role)) {
|
||||||
{
|
|
||||||
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized for the requested scope.</p>").type("text/html").build());
|
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized for the requested scope.</p>").type("text/html").build());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,17 +54,14 @@ public class TokenManager
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkeletonKeyToken createScopedToken(String scopeParam, RealmModel realm, User client, User user)
|
public SkeletonKeyToken createScopedToken(String scopeParam, RealmModel realm, User client, User user) {
|
||||||
{
|
|
||||||
SkeletonKeyScope scope = decodeScope(scopeParam);
|
SkeletonKeyScope scope = decodeScope(scopeParam);
|
||||||
return createScopedToken(scope, realm, client, user);
|
return createScopedToken(scope, realm, client, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkeletonKeyToken createLoginToken(RealmModel realm, User client, User user)
|
public SkeletonKeyToken createLoginToken(RealmModel realm, User client, User user) {
|
||||||
{
|
|
||||||
Set<String> mapping = realm.getScope(client);
|
Set<String> mapping = realm.getScope(client);
|
||||||
if (!mapping.contains("*"))
|
if (!mapping.contains("*")) {
|
||||||
{
|
|
||||||
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized to request a user login.</p>").type("text/html").build());
|
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized to request a user login.</p>").type("text/html").build());
|
||||||
}
|
}
|
||||||
SkeletonKeyToken token = createAccessToken(realm, user);
|
SkeletonKeyToken token = createAccessToken(realm, user);
|
||||||
|
@ -86,56 +70,45 @@ public class TokenManager
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkeletonKeyScope decodeScope(String scopeParam)
|
public SkeletonKeyScope decodeScope(String scopeParam) {
|
||||||
{
|
|
||||||
SkeletonKeyScope scope = null;
|
SkeletonKeyScope scope = null;
|
||||||
byte[] bytes = Base64Url.decode(scopeParam);
|
byte[] bytes = Base64Url.decode(scopeParam);
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
scope = JsonSerialization.fromBytes(SkeletonKeyScope.class, bytes);
|
scope = JsonSerialization.fromBytes(SkeletonKeyScope.class, bytes);
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SkeletonKeyToken createAccessToken(RealmModel realm, User user)
|
public SkeletonKeyToken createAccessToken(RealmModel realm, User user) {
|
||||||
{
|
|
||||||
List<ResourceModel> resources = realm.getResources();
|
List<ResourceModel> resources = realm.getResources();
|
||||||
SkeletonKeyToken token = new SkeletonKeyToken();
|
SkeletonKeyToken token = new SkeletonKeyToken();
|
||||||
token.id(adapter.generateId());
|
token.id(RealmManager.generateId());
|
||||||
token.issuedNow();
|
token.issuedNow();
|
||||||
token.principal(user.getLoginName());
|
token.principal(user.getLoginName());
|
||||||
token.audience(realm.getId());
|
token.audience(realm.getId());
|
||||||
if (realm.getTokenLifespan() > 0)
|
if (realm.getTokenLifespan() > 0) {
|
||||||
{
|
|
||||||
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> realmMapping = realm.getRoleMappings(user);
|
Set<String> realmMapping = realm.getRoleMappings(user);
|
||||||
|
|
||||||
if (realmMapping != null && realmMapping.size() > 0)
|
if (realmMapping != null && realmMapping.size() > 0) {
|
||||||
{
|
|
||||||
SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
|
SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
|
||||||
for (String role : realmMapping)
|
for (String role : realmMapping) {
|
||||||
{
|
|
||||||
access.addRole(role);
|
access.addRole(role);
|
||||||
}
|
}
|
||||||
token.setRealmAccess(access);
|
token.setRealmAccess(access);
|
||||||
}
|
}
|
||||||
if (resources != null)
|
if (resources != null) {
|
||||||
{
|
for (ResourceModel resource : resources) {
|
||||||
for (ResourceModel resource : resources)
|
|
||||||
{
|
|
||||||
Set<String> mapping = resource.getRoleMappings(user);
|
Set<String> mapping = resource.getRoleMappings(user);
|
||||||
if (mapping == null) continue;
|
if (mapping == null) continue;
|
||||||
SkeletonKeyToken.Access access = token.addAccess(resource.getName())
|
SkeletonKeyToken.Access access = token.addAccess(resource.getName())
|
||||||
.verifyCaller(resource.isSurrogateAuthRequired());
|
.verifyCaller(resource.isSurrogateAuthRequired());
|
||||||
for (String role : mapping)
|
for (String role : mapping) {
|
||||||
{
|
|
||||||
access.addRole(role);
|
access.addRole(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,29 +116,23 @@ public class TokenManager
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkeletonKeyToken createIdentityToken(RealmModel realm, String username)
|
public SkeletonKeyToken createIdentityToken(RealmModel realm, String username) {
|
||||||
{
|
|
||||||
SkeletonKeyToken token = new SkeletonKeyToken();
|
SkeletonKeyToken token = new SkeletonKeyToken();
|
||||||
token.id(adapter.generateId());
|
token.id(RealmManager.generateId());
|
||||||
token.issuedNow();
|
token.issuedNow();
|
||||||
token.principal(username);
|
token.principal(username);
|
||||||
token.audience(realm.getId());
|
token.audience(realm.getId());
|
||||||
if (realm.getTokenLifespan() > 0)
|
if (realm.getTokenLifespan() > 0) {
|
||||||
{
|
|
||||||
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String encodeToken(RealmModel realm, SkeletonKeyToken token)
|
public String encodeToken(RealmModel realm, SkeletonKeyToken token) {
|
||||||
{
|
|
||||||
byte[] tokenBytes = null;
|
byte[] tokenBytes = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
tokenBytes = JsonSerialization.toByteArray(token, false);
|
tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
String encodedToken = new JWSBuilder()
|
String encodedToken = new JWSBuilder()
|
||||||
|
|
|
@ -1,49 +1,71 @@
|
||||||
package org.keycloak.services.models;
|
package org.keycloak.services.models;
|
||||||
|
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
import org.picketlink.idm.IdentityManager;
|
import org.picketlink.idm.IdentityManager;
|
||||||
import org.picketlink.idm.internal.IdentityManagerFactory;
|
|
||||||
import org.picketlink.idm.model.Realm;
|
import org.picketlink.idm.model.Realm;
|
||||||
|
import org.picketlink.idm.model.Role;
|
||||||
import org.picketlink.idm.model.SimpleAgent;
|
import org.picketlink.idm.model.SimpleAgent;
|
||||||
|
import org.picketlink.idm.model.SimpleUser;
|
||||||
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.KeyPairGenerator;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 RealmManager
|
public class RealmManager {
|
||||||
{
|
|
||||||
private static AtomicLong counter = new AtomicLong(1);
|
private static AtomicLong counter = new AtomicLong(1);
|
||||||
|
|
||||||
public static String generateId()
|
public static String generateId() {
|
||||||
{
|
|
||||||
return counter.getAndIncrement() + "-" + System.currentTimeMillis();
|
return counter.getAndIncrement() + "-" + System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IdentityManagerFactory factory;
|
protected IdentitySession IdentitySession;
|
||||||
|
|
||||||
public RealmManager(IdentityManagerFactory factory)
|
public RealmManager(IdentitySession IdentitySession) {
|
||||||
{
|
this.IdentitySession = IdentitySession;
|
||||||
this.factory = factory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RealmModel getRealm(String id)
|
public RealmModel defaultRealm() {
|
||||||
{
|
return getRealm(Realm.DEFAULT_REALM);
|
||||||
Realm existing = factory.findRealm(id);
|
}
|
||||||
if (existing == null)
|
|
||||||
{
|
public RealmModel getRealm(String id) {
|
||||||
|
Realm existing = IdentitySession.findRealm(id);
|
||||||
|
if (existing == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new RealmModel(existing, factory);
|
return new RealmModel(existing, IdentitySession);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RealmModel create(String name)
|
public RealmModel createRealm(String name) {
|
||||||
{
|
return createRealm(generateId(), name);
|
||||||
Realm newRealm = factory.createRealm(generateId());
|
}
|
||||||
IdentityManager idm = factory.createIdentityManager(newRealm);
|
|
||||||
|
public RealmModel createRealm(String id, String name) {
|
||||||
|
Realm newRealm = IdentitySession.createRealm(id);
|
||||||
|
IdentityManager idm = IdentitySession.createIdentityManager(newRealm);
|
||||||
SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID);
|
SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID);
|
||||||
idm.add(agent);
|
idm.add(agent);
|
||||||
return new RealmModel(newRealm, factory);
|
RealmModel realm = new RealmModel(newRealm, IdentitySession);
|
||||||
|
return realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void generateRealmKeys(RealmModel realm) {
|
||||||
|
KeyPair keyPair = null;
|
||||||
|
try {
|
||||||
|
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
realm.setPrivateKey(keyPair.getPrivate());
|
||||||
|
realm.setPublicKey(keyPair.getPublic());
|
||||||
|
realm.updateRealm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,20 +4,19 @@ import org.bouncycastle.openssl.PEMWriter;
|
||||||
import org.jboss.resteasy.security.PemUtils;
|
import org.jboss.resteasy.security.PemUtils;
|
||||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||||
import org.keycloak.services.models.relationships.RealmAdminRelationship;
|
import org.keycloak.services.models.relationships.RealmAdminRelationship;
|
||||||
import org.keycloak.services.models.relationships.RealmResourceRelationship;
|
import org.keycloak.services.models.relationships.ResourceRelationship;
|
||||||
import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
|
import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
|
||||||
import org.keycloak.services.models.relationships.ScopeRelationship;
|
import org.keycloak.services.models.relationships.ScopeRelationship;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
import org.picketlink.idm.IdentityManager;
|
import org.picketlink.idm.IdentityManager;
|
||||||
import org.picketlink.idm.credential.Password;
|
import org.picketlink.idm.credential.Password;
|
||||||
import org.picketlink.idm.credential.TOTPCredential;
|
import org.picketlink.idm.credential.TOTPCredential;
|
||||||
import org.picketlink.idm.credential.X509CertificateCredentials;
|
import org.picketlink.idm.credential.X509CertificateCredentials;
|
||||||
import org.picketlink.idm.internal.IdentityManagerFactory;
|
|
||||||
import org.picketlink.idm.model.Agent;
|
import org.picketlink.idm.model.Agent;
|
||||||
import org.picketlink.idm.model.Attribute;
|
import org.picketlink.idm.model.Attribute;
|
||||||
import org.picketlink.idm.model.Grant;
|
import org.picketlink.idm.model.Grant;
|
||||||
import org.picketlink.idm.model.Realm;
|
import org.picketlink.idm.model.Realm;
|
||||||
import org.picketlink.idm.model.Role;
|
import org.picketlink.idm.model.Role;
|
||||||
import org.picketlink.idm.model.SimpleAgent;
|
|
||||||
import org.picketlink.idm.model.Tier;
|
import org.picketlink.idm.model.Tier;
|
||||||
import org.picketlink.idm.model.User;
|
import org.picketlink.idm.model.User;
|
||||||
import org.picketlink.idm.query.IdentityQuery;
|
import org.picketlink.idm.query.IdentityQuery;
|
||||||
|
@ -39,8 +38,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 RealmModel
|
public class RealmModel {
|
||||||
{
|
|
||||||
public static final String REALM_AGENT_ID = "_realm_";
|
public static final String REALM_AGENT_ID = "_realm_";
|
||||||
public static final String REALM_NAME = "name";
|
public static final String REALM_NAME = "name";
|
||||||
public static final String REALM_ACCESS_CODE_LIFESPAN = "accessCodeLifespan";
|
public static final String REALM_ACCESS_CODE_LIFESPAN = "accessCodeLifespan";
|
||||||
|
@ -49,199 +47,168 @@ public class RealmModel
|
||||||
public static final String REALM_PUBLIC_KEY = "publicKey";
|
public static final String REALM_PUBLIC_KEY = "publicKey";
|
||||||
public static final String REALM_IS_SSL_NOT_REQUIRED = "isSSLNotRequired";
|
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_COOKIE_LOGIN_ALLOWED = "isCookieLoginAllowed";
|
||||||
|
public static final String REALM_IS_REGISTRATION_ALLOWED = "isRegistrationAllowed";
|
||||||
|
|
||||||
protected Realm realm;
|
protected Realm realm;
|
||||||
protected Agent realmAgent;
|
protected Agent realmAgent;
|
||||||
protected IdentityManagerFactory factory;
|
protected IdentitySession identitySession;
|
||||||
protected volatile transient PublicKey publicKey;
|
protected volatile transient PublicKey publicKey;
|
||||||
protected volatile transient PrivateKey privateKey;
|
protected volatile transient PrivateKey privateKey;
|
||||||
|
|
||||||
public RealmModel(Realm realm, IdentityManagerFactory factory)
|
public RealmModel(Realm realm, IdentitySession session) {
|
||||||
{
|
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.factory = factory;
|
this.identitySession = session;
|
||||||
realmAgent = getIdm().getAgent(REALM_AGENT_ID);
|
realmAgent = getIdm().getAgent(REALM_AGENT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityManager getIdm()
|
public IdentityManager getIdm() {
|
||||||
{
|
return identitySession.createIdentityManager(realm);
|
||||||
return factory.createIdentityManager(realm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRealm()
|
public void updateRealm() {
|
||||||
{
|
|
||||||
getIdm().update(realmAgent);
|
getIdm().update(realmAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId()
|
public String getId() {
|
||||||
{
|
|
||||||
return realm.getId();
|
return realm.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName()
|
public String getName() {
|
||||||
{
|
|
||||||
return (String) realmAgent.getAttribute(REALM_NAME).getValue();
|
return (String) realmAgent.getAttribute(REALM_NAME).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name)
|
public void setName(String name) {
|
||||||
{
|
|
||||||
realmAgent.setAttribute(new Attribute<String>(REALM_NAME, name));
|
realmAgent.setAttribute(new Attribute<String>(REALM_NAME, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled()
|
public boolean isEnabled() {
|
||||||
{
|
|
||||||
return realmAgent.isEnabled();
|
return realmAgent.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled)
|
public void setEnabled(boolean enabled) {
|
||||||
{
|
|
||||||
realmAgent.setEnabled(enabled);
|
realmAgent.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSslNotRequired()
|
public boolean isSslNotRequired() {
|
||||||
{
|
|
||||||
return (Boolean) realmAgent.getAttribute(REALM_IS_SSL_NOT_REQUIRED).getValue();
|
return (Boolean) realmAgent.getAttribute(REALM_IS_SSL_NOT_REQUIRED).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSslNotRequired(boolean sslNotRequired)
|
public void setSslNotRequired(boolean sslNotRequired) {
|
||||||
{
|
|
||||||
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_SSL_NOT_REQUIRED, sslNotRequired));
|
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_SSL_NOT_REQUIRED, sslNotRequired));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCookieLoginAllowed()
|
public boolean isCookieLoginAllowed() {
|
||||||
{
|
|
||||||
return (Boolean) realmAgent.getAttribute(REALM_IS_COOKIE_LOGIN_ALLOWED).getValue();
|
return (Boolean) realmAgent.getAttribute(REALM_IS_COOKIE_LOGIN_ALLOWED).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCookieLoginAllowed(boolean cookieLoginAllowed)
|
public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
|
||||||
{
|
|
||||||
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_COOKIE_LOGIN_ALLOWED, cookieLoginAllowed));
|
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_COOKIE_LOGIN_ALLOWED, cookieLoginAllowed));
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTokenLifespan()
|
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();
|
return (Long) realmAgent.getAttribute(REALM_TOKEN_LIFESPAN).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTokenLifespan(long tokenLifespan)
|
public void setTokenLifespan(long tokenLifespan) {
|
||||||
{
|
|
||||||
realmAgent.setAttribute(new Attribute<Long>(REALM_TOKEN_LIFESPAN, tokenLifespan));
|
realmAgent.setAttribute(new Attribute<Long>(REALM_TOKEN_LIFESPAN, tokenLifespan));
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getAccessCodeLifespan()
|
public long getAccessCodeLifespan() {
|
||||||
{
|
|
||||||
return (Long) realmAgent.getAttribute(REALM_ACCESS_CODE_LIFESPAN).getValue();
|
return (Long) realmAgent.getAttribute(REALM_ACCESS_CODE_LIFESPAN).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAccessCodeLifespan(long accessCodeLifespan)
|
public void setAccessCodeLifespan(long accessCodeLifespan) {
|
||||||
{
|
|
||||||
realmAgent.setAttribute(new Attribute<Long>(REALM_ACCESS_CODE_LIFESPAN, accessCodeLifespan));
|
realmAgent.setAttribute(new Attribute<Long>(REALM_ACCESS_CODE_LIFESPAN, accessCodeLifespan));
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPublicKeyPem()
|
public String getPublicKeyPem() {
|
||||||
{
|
|
||||||
return (String) realmAgent.getAttribute(REALM_PUBLIC_KEY).getValue();
|
return (String) realmAgent.getAttribute(REALM_PUBLIC_KEY).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPublicKeyPem(String publicKeyPem)
|
public void setPublicKeyPem(String publicKeyPem) {
|
||||||
{
|
|
||||||
realmAgent.setAttribute(new Attribute<String>(REALM_PUBLIC_KEY, publicKeyPem));
|
realmAgent.setAttribute(new Attribute<String>(REALM_PUBLIC_KEY, publicKeyPem));
|
||||||
this.publicKey = null;
|
this.publicKey = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrivateKeyPem()
|
public String getPrivateKeyPem() {
|
||||||
{
|
|
||||||
return (String) realmAgent.getAttribute(REALM_PRIVATE_KEY).getValue();
|
return (String) realmAgent.getAttribute(REALM_PRIVATE_KEY).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrivateKeyPem(String privateKeyPem)
|
public void setPrivateKeyPem(String privateKeyPem) {
|
||||||
{
|
|
||||||
realmAgent.setAttribute(new Attribute<String>(REALM_PRIVATE_KEY, privateKeyPem));
|
realmAgent.setAttribute(new Attribute<String>(REALM_PRIVATE_KEY, privateKeyPem));
|
||||||
this.privateKey = null;
|
this.privateKey = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PublicKey getPublicKey()
|
public PublicKey getPublicKey() {
|
||||||
{
|
|
||||||
if (publicKey != null) return publicKey;
|
if (publicKey != null) return publicKey;
|
||||||
String pem = getPublicKeyPem();
|
String pem = getPublicKeyPem();
|
||||||
if (pem != null)
|
if (pem != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
publicKey = PemUtils.decodePublicKey(pem);
|
publicKey = PemUtils.decodePublicKey(pem);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPublicKey(PublicKey publicKey)
|
public void setPublicKey(PublicKey publicKey) {
|
||||||
{
|
|
||||||
this.publicKey = publicKey;
|
this.publicKey = publicKey;
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
PEMWriter pemWriter = new PEMWriter(writer);
|
PEMWriter pemWriter = new PEMWriter(writer);
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
pemWriter.writeObject(publicKey);
|
pemWriter.writeObject(publicKey);
|
||||||
pemWriter.flush();
|
pemWriter.flush();
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
String s = writer.toString();
|
String s = writer.toString();
|
||||||
setPublicKeyPem(PemUtils.removeBeginEnd(s));
|
setPublicKeyPem(PemUtils.removeBeginEnd(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PrivateKey getPrivateKey()
|
public PrivateKey getPrivateKey() {
|
||||||
{
|
|
||||||
if (privateKey != null) return privateKey;
|
if (privateKey != null) return privateKey;
|
||||||
String pem = getPrivateKeyPem();
|
String pem = getPrivateKeyPem();
|
||||||
if (pem != null)
|
if (pem != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
privateKey = PemUtils.decodePrivateKey(pem);
|
privateKey = PemUtils.decodePrivateKey(pem);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return privateKey;
|
return privateKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrivateKey(PrivateKey privateKey)
|
public void setPrivateKey(PrivateKey privateKey) {
|
||||||
{
|
|
||||||
this.privateKey = privateKey;
|
this.privateKey = privateKey;
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
PEMWriter pemWriter = new PEMWriter(writer);
|
PEMWriter pemWriter = new PEMWriter(writer);
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
pemWriter.writeObject(privateKey);
|
pemWriter.writeObject(privateKey);
|
||||||
pemWriter.flush();
|
pemWriter.flush();
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
String s = writer.toString();
|
String s = writer.toString();
|
||||||
setPrivateKeyPem(PemUtils.removeBeginEnd(s));
|
setPrivateKeyPem(PemUtils.removeBeginEnd(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<RequiredCredentialModel> getRequiredCredentials()
|
public List<RequiredCredentialModel> getRequiredCredentials() {
|
||||||
{
|
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
Agent realmAgent = idm.getAgent(REALM_AGENT_ID);
|
Agent realmAgent = idm.getAgent(REALM_AGENT_ID);
|
||||||
RelationshipQuery<RequiredCredentialRelationship> query = idm.createRelationshipQuery(RequiredCredentialRelationship.class);
|
RelationshipQuery<RequiredCredentialRelationship> query = idm.createRelationshipQuery(RequiredCredentialRelationship.class);
|
||||||
query.setParameter(RequiredCredentialRelationship.REALM_AGENT, realmAgent);
|
query.setParameter(RequiredCredentialRelationship.REALM_AGENT, realmAgent);
|
||||||
List<RequiredCredentialRelationship> results = query.getResultList();
|
List<RequiredCredentialRelationship> results = query.getResultList();
|
||||||
List<RequiredCredentialModel> rtn = new ArrayList<RequiredCredentialModel>();
|
List<RequiredCredentialModel> rtn = new ArrayList<RequiredCredentialModel>();
|
||||||
for (RequiredCredentialRelationship relationship : results)
|
for (RequiredCredentialRelationship relationship : results) {
|
||||||
{
|
|
||||||
RequiredCredentialModel model = new RequiredCredentialModel();
|
RequiredCredentialModel model = new RequiredCredentialModel();
|
||||||
model.setInput(relationship.isInput());
|
model.setInput(relationship.isInput());
|
||||||
model.setSecret(relationship.isSecret());
|
model.setSecret(relationship.isSecret());
|
||||||
|
@ -251,8 +218,7 @@ public class RealmModel
|
||||||
return rtn;
|
return rtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRequiredCredential(RequiredCredentialModel cred)
|
public void addRequiredCredential(RequiredCredentialModel cred) {
|
||||||
{
|
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
Agent realmAgent = idm.getAgent(REALM_AGENT_ID);
|
Agent realmAgent = idm.getAgent(REALM_AGENT_ID);
|
||||||
RequiredCredentialRelationship relationship = new RequiredCredentialRelationship();
|
RequiredCredentialRelationship relationship = new RequiredCredentialRelationship();
|
||||||
|
@ -263,28 +229,19 @@ public class RealmModel
|
||||||
idm.add(relationship);
|
idm.add(relationship);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCredential(User user, UserCredentialModel cred)
|
public void updateCredential(User user, UserCredentialModel cred) {
|
||||||
{
|
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD))
|
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) {
|
||||||
{
|
|
||||||
Password password = new Password(cred.getValue());
|
Password password = new Password(cred.getValue());
|
||||||
idm.updateCredential(user, password);
|
idm.updateCredential(user, password);
|
||||||
}
|
} else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) {
|
||||||
else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP))
|
|
||||||
{
|
|
||||||
TOTPCredential totp = new TOTPCredential(cred.getValue());
|
TOTPCredential totp = new TOTPCredential(cred.getValue());
|
||||||
idm.updateCredential(user, totp);
|
idm.updateCredential(user, totp);
|
||||||
}
|
} else if (cred.getType().equals(RequiredCredentialRepresentation.CLIENT_CERT)) {
|
||||||
else if (cred.getType().equals(RequiredCredentialRepresentation.CLIENT_CERT))
|
|
||||||
{
|
|
||||||
X509Certificate cert = null;
|
X509Certificate cert = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
cert = org.keycloak.PemUtils.decodeCertificate(cred.getValue());
|
cert = org.keycloak.PemUtils.decodeCertificate(cred.getValue());
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
X509CertificateCredentials creds = new X509CertificateCredentials(cert);
|
X509CertificateCredentials creds = new X509CertificateCredentials(cert);
|
||||||
|
@ -292,8 +249,7 @@ public class RealmModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Role> getRoles()
|
public List<Role> getRoles() {
|
||||||
{
|
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
IdentityQuery<Role> query = idm.createIdentityQuery(Role.class);
|
IdentityQuery<Role> query = idm.createIdentityQuery(Role.class);
|
||||||
query.setParameter(Role.PARTITION, realm);
|
query.setParameter(Role.PARTITION, realm);
|
||||||
|
@ -301,73 +257,57 @@ public class RealmModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected ResourceModel loadResource(Agent resource)
|
|
||||||
{
|
|
||||||
Tier tier = factory.findTier(resource.getPartition().getId());
|
|
||||||
return new ResourceModel(tier, resource, this, factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key name, value resource
|
* Key name, value resource
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Map<String, ResourceModel> getResourceMap()
|
public Map<String, ResourceModel> getResourceMap() {
|
||||||
{
|
|
||||||
Map<String, ResourceModel> resourceMap = new HashMap<String, ResourceModel>();
|
Map<String, ResourceModel> resourceMap = new HashMap<String, ResourceModel>();
|
||||||
for (ResourceModel resource : getResources())
|
for (ResourceModel resource : getResources()) {
|
||||||
{
|
|
||||||
resourceMap.put(resource.getName(), resource);
|
resourceMap.put(resource.getName(), resource);
|
||||||
}
|
}
|
||||||
return resourceMap;
|
return resourceMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ResourceModel> getResources()
|
public List<ResourceModel> getResources() {
|
||||||
{
|
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
RelationshipQuery<RealmResourceRelationship> query = idm.createRelationshipQuery(RealmResourceRelationship.class);
|
RelationshipQuery<ResourceRelationship> query = idm.createRelationshipQuery(ResourceRelationship.class);
|
||||||
query.setParameter(RealmResourceRelationship.REALM_AGENT, realmAgent);
|
query.setParameter(ResourceRelationship.REALM_AGENT, realmAgent);
|
||||||
List<RealmResourceRelationship> results = query.getResultList();
|
List<ResourceRelationship> results = query.getResultList();
|
||||||
List<ResourceModel> resources = new ArrayList<ResourceModel>();
|
List<ResourceModel> resources = new ArrayList<ResourceModel>();
|
||||||
for (RealmResourceRelationship relationship : results)
|
for (ResourceRelationship relationship : results) {
|
||||||
{
|
Tier resourceTier = identitySession.findTier(relationship.getResourceId());
|
||||||
ResourceModel model = loadResource(relationship.getResourceAgent());
|
ResourceModel model = new ResourceModel(resourceTier,relationship, this, identitySession);
|
||||||
resources.add(model);
|
resources.add(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resources;
|
return resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceModel addResource(String name)
|
public ResourceModel addResource(String name) {
|
||||||
{
|
Tier newTier = identitySession.createTier(RealmManager.generateId());
|
||||||
Tier newTier = factory.createTier(RealmManager.generateId());
|
IdentityManager idm = getIdm();
|
||||||
IdentityManager idm = factory.createIdentityManager(newTier);
|
ResourceRelationship relationship = new ResourceRelationship();
|
||||||
SimpleAgent resourceAgent = new SimpleAgent(ResourceModel.RESOURCE_AGENT_ID);
|
relationship.setResourceName(name);
|
||||||
resourceAgent.setAttribute(new Attribute<String>(ResourceModel.RESOURCE_NAME, name));
|
|
||||||
idm.add(resourceAgent);
|
|
||||||
idm = getIdm();
|
|
||||||
RealmResourceRelationship relationship = new RealmResourceRelationship();
|
|
||||||
relationship.setRealmAgent(realmAgent);
|
relationship.setRealmAgent(realmAgent);
|
||||||
relationship.setResourceAgent(resourceAgent);
|
relationship.setResourceId(newTier.getId());
|
||||||
idm.add(relationship);
|
idm.add(relationship);
|
||||||
return new ResourceModel(newTier, resourceAgent, this, factory);
|
return new ResourceModel(newTier, relationship, this, identitySession);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getRoleMappings(User user)
|
public Set<String> getRoleMappings(User user) {
|
||||||
{
|
|
||||||
RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class);
|
RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class);
|
||||||
query.setParameter(Grant.ASSIGNEE, user);
|
query.setParameter(Grant.ASSIGNEE, user);
|
||||||
List<Grant> grants = query.getResultList();
|
List<Grant> grants = query.getResultList();
|
||||||
HashSet<String> set = new HashSet<String>();
|
HashSet<String> set = new HashSet<String>();
|
||||||
for (Grant grant : grants)
|
for (Grant grant : grants) {
|
||||||
{
|
|
||||||
if (grant.getRole().getPartition().getId().equals(realm.getId())) set.add(grant.getRole().getName());
|
if (grant.getRole().getPartition().getId().equals(realm.getId())) set.add(grant.getRole().getName());
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addScope(Agent agent, String roleName)
|
public void addScope(Agent agent, String roleName) {
|
||||||
{
|
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
Role role = idm.getRole(roleName);
|
Role role = idm.getRole(roleName);
|
||||||
if (role == null) throw new RuntimeException("role not found");
|
if (role == null) throw new RuntimeException("role not found");
|
||||||
|
@ -378,35 +318,31 @@ public class RealmModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Set<String> getScope(Agent agent)
|
public Set<String> getScope(Agent agent) {
|
||||||
{
|
|
||||||
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class);
|
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class);
|
||||||
query.setParameter(ScopeRelationship.CLIENT, agent);
|
query.setParameter(ScopeRelationship.CLIENT, agent);
|
||||||
List<ScopeRelationship> scope = query.getResultList();
|
List<ScopeRelationship> scope = query.getResultList();
|
||||||
HashSet<String> set = new HashSet<String>();
|
HashSet<String> set = new HashSet<String>();
|
||||||
for (ScopeRelationship rel : scope)
|
for (ScopeRelationship rel : scope) {
|
||||||
{
|
|
||||||
if (rel.getScope().getPartition().getId().equals(realm.getId())) set.add(rel.getScope().getName());
|
if (rel.getScope().getPartition().getId().equals(realm.getId())) set.add(rel.getScope().getName());
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRealmAdmin(Agent agent)
|
public boolean isRealmAdmin(Agent agent) {
|
||||||
{
|
IdentityManager idm = new RealmManager(identitySession).defaultRealm().getIdm();
|
||||||
IdentityManager idm = getIdm();
|
|
||||||
RelationshipQuery<RealmAdminRelationship> query = idm.createRelationshipQuery(RealmAdminRelationship.class);
|
RelationshipQuery<RealmAdminRelationship> query = idm.createRelationshipQuery(RealmAdminRelationship.class);
|
||||||
query.setParameter(RealmAdminRelationship.REALM, realm);
|
query.setParameter(RealmAdminRelationship.REALM, realm.getId());
|
||||||
query.setParameter(RealmAdminRelationship.ADMIN, agent);
|
query.setParameter(RealmAdminRelationship.ADMIN, agent);
|
||||||
List<RealmAdminRelationship> results = query.getResultList();
|
List<RealmAdminRelationship> results = query.getResultList();
|
||||||
return results.size() > 0;
|
return results.size() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRealmAdmin(Agent agent)
|
public void addRealmAdmin(Agent agent) {
|
||||||
{
|
IdentityManager idm = new RealmManager(identitySession).defaultRealm().getIdm();
|
||||||
IdentityManager idm = getIdm();
|
|
||||||
RealmAdminRelationship relationship = new RealmAdminRelationship();
|
RealmAdminRelationship relationship = new RealmAdminRelationship();
|
||||||
relationship.setAdmin(agent);
|
relationship.setAdmin(agent);
|
||||||
relationship.setRealm(realm);
|
relationship.setRealm(realm.getId());
|
||||||
idm.add(relationship);
|
idm.add(relationship);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,48 @@
|
||||||
package org.keycloak.services.models;
|
package org.keycloak.services.models;
|
||||||
|
|
||||||
|
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 RequiredCredentialModel
|
public class RequiredCredentialModel {
|
||||||
{
|
|
||||||
protected String type;
|
protected String type;
|
||||||
protected boolean input;
|
protected boolean input;
|
||||||
protected boolean secret;
|
protected boolean secret;
|
||||||
|
|
||||||
public String getType()
|
public RequiredCredentialModel() {
|
||||||
{
|
}
|
||||||
|
|
||||||
|
public RequiredCredentialModel(String type, boolean input, boolean secret) {
|
||||||
|
this.type = type;
|
||||||
|
this.input = input;
|
||||||
|
this.secret = secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(String type)
|
public void setType(String type) {
|
||||||
{
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInput()
|
public boolean isInput() {
|
||||||
{
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInput(boolean input)
|
public void setInput(boolean input) {
|
||||||
{
|
|
||||||
this.input = input;
|
this.input = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSecret()
|
public boolean isSecret() {
|
||||||
{
|
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecret(boolean secret)
|
public void setSecret(boolean secret) {
|
||||||
{
|
|
||||||
this.secret = secret;
|
this.secret = secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final RequiredCredentialModel PASSWORD = new RequiredCredentialModel(RequiredCredentialRepresentation.PASSWORD, true, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package org.keycloak.services.models;
|
package org.keycloak.services.models;
|
||||||
|
|
||||||
|
import org.keycloak.services.models.relationships.ResourceRelationship;
|
||||||
import org.keycloak.services.models.relationships.ScopeRelationship;
|
import org.keycloak.services.models.relationships.ScopeRelationship;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
import org.picketlink.idm.IdentityManager;
|
import org.picketlink.idm.IdentityManager;
|
||||||
import org.picketlink.idm.internal.IdentityManagerFactory;
|
|
||||||
import org.picketlink.idm.model.Agent;
|
import org.picketlink.idm.model.Agent;
|
||||||
import org.picketlink.idm.model.Attribute;
|
import org.picketlink.idm.model.Attribute;
|
||||||
import org.picketlink.idm.model.Grant;
|
import org.picketlink.idm.model.Grant;
|
||||||
|
@ -20,93 +21,77 @@ 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 ResourceModel
|
public class ResourceModel {
|
||||||
{
|
|
||||||
public static final String RESOURCE_AGENT_ID = "_resource_";
|
public static final String RESOURCE_AGENT_ID = "_resource_";
|
||||||
public static final String RESOURCE_NAME = "name";
|
public static final String RESOURCE_NAME = "name";
|
||||||
public static final String RESOURCE_SURROGATE_AUTH = "surrogate_auth";
|
public static final String RESOURCE_SURROGATE_AUTH = "surrogate_auth";
|
||||||
|
|
||||||
protected Tier tier;
|
protected Tier tier;
|
||||||
protected Agent agent;
|
protected ResourceRelationship agent;
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
protected IdentityManagerFactory factory;
|
protected IdentitySession IdentitySession;
|
||||||
|
|
||||||
public ResourceModel(Tier tier, Agent agent, RealmModel realm, IdentityManagerFactory factory)
|
public ResourceModel(Tier tier, ResourceRelationship agent, RealmModel realm, IdentitySession factory) {
|
||||||
{
|
|
||||||
this.tier = tier;
|
this.tier = tier;
|
||||||
this.agent = agent;
|
this.agent = agent;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.factory = factory;
|
this.IdentitySession = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IdentityManager getIdm()
|
public IdentityManager getIdm() {
|
||||||
{
|
return IdentitySession.createIdentityManager(tier);
|
||||||
return factory.createIdentityManager(tier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateResource()
|
public void updateResource() {
|
||||||
{
|
|
||||||
getIdm().update(agent);
|
getIdm().update(agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId()
|
public String getId() {
|
||||||
{
|
|
||||||
return tier.getId();
|
return tier.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName()
|
public String getName() {
|
||||||
{
|
return agent.getResourceName();
|
||||||
return (String)agent.getAttribute(RESOURCE_NAME).getValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name)
|
public void setName(String name) {
|
||||||
{
|
agent.setResourceName(name);
|
||||||
agent.setAttribute(new Attribute<String>(RESOURCE_NAME, name));
|
|
||||||
getIdm().update(agent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled()
|
public boolean isEnabled() {
|
||||||
{
|
return agent.getEnabled();
|
||||||
return agent.isEnabled();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled)
|
public void setEnabled(boolean enabled) {
|
||||||
{
|
|
||||||
agent.setEnabled(enabled);
|
agent.setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSurrogateAuthRequired()
|
public boolean isSurrogateAuthRequired() {
|
||||||
{
|
return agent.getSurrogateAuthRequired();
|
||||||
return (Boolean)agent.getAttribute(RESOURCE_SURROGATE_AUTH).getValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSurrogateAuthRequired(boolean surrogateAuthRequired)
|
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
|
||||||
{
|
agent.setSurrogateAuthRequired(surrogateAuthRequired);
|
||||||
agent.setAttribute(new Attribute<Boolean>(RESOURCE_SURROGATE_AUTH, surrogateAuthRequired));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Role> getRoles()
|
public List<Role> getRoles() {
|
||||||
{
|
|
||||||
IdentityQuery<Role> query = getIdm().createIdentityQuery(Role.class);
|
IdentityQuery<Role> query = getIdm().createIdentityQuery(Role.class);
|
||||||
query.setParameter(Role.PARTITION, tier);
|
query.setParameter(Role.PARTITION, tier);
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getRoleMappings(User user)
|
public Set<String> getRoleMappings(User user) {
|
||||||
{
|
|
||||||
RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class);
|
RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class);
|
||||||
query.setParameter(Grant.ASSIGNEE, user);
|
query.setParameter(Grant.ASSIGNEE, user);
|
||||||
List<Grant> grants = query.getResultList();
|
List<Grant> grants = query.getResultList();
|
||||||
HashSet<String> set = new HashSet<String>();
|
HashSet<String> set = new HashSet<String>();
|
||||||
for (Grant grant : grants)
|
for (Grant grant : grants) {
|
||||||
{
|
|
||||||
if (grant.getRole().getPartition().getId().equals(tier.getId())) set.add(grant.getRole().getName());
|
if (grant.getRole().getPartition().getId().equals(tier.getId())) set.add(grant.getRole().getName());
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addScope(Agent agent, String roleName)
|
public void addScope(Agent agent, String roleName) {
|
||||||
{
|
|
||||||
IdentityManager idm = getIdm();
|
IdentityManager idm = getIdm();
|
||||||
Role role = idm.getRole(roleName);
|
Role role = idm.getRole(roleName);
|
||||||
if (role == null) throw new RuntimeException("role not found");
|
if (role == null) throw new RuntimeException("role not found");
|
||||||
|
@ -116,14 +101,12 @@ public class ResourceModel
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getScope(Agent agent)
|
public Set<String> getScope(Agent agent) {
|
||||||
{
|
|
||||||
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class);
|
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class);
|
||||||
query.setParameter(ScopeRelationship.CLIENT, agent);
|
query.setParameter(ScopeRelationship.CLIENT, agent);
|
||||||
List<ScopeRelationship> scope = query.getResultList();
|
List<ScopeRelationship> scope = query.getResultList();
|
||||||
HashSet<String> set = new HashSet<String>();
|
HashSet<String> set = new HashSet<String>();
|
||||||
for (ScopeRelationship rel : scope)
|
for (ScopeRelationship rel : scope) {
|
||||||
{
|
|
||||||
if (rel.getScope().getPartition().getId().equals(tier.getId())) set.add(rel.getScope().getName());
|
if (rel.getScope().getPartition().getId().equals(tier.getId())) set.add(rel.getScope().getName());
|
||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
|
|
|
@ -4,29 +4,24 @@ package org.keycloak.services.models;
|
||||||
* @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 UserCredentialModel
|
public class UserCredentialModel {
|
||||||
{
|
|
||||||
|
|
||||||
protected String type;
|
protected String type;
|
||||||
protected String value;
|
protected String value;
|
||||||
|
|
||||||
public String getType()
|
public String getType() {
|
||||||
{
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(String type)
|
public void setType(String type) {
|
||||||
{
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValue()
|
public String getValue() {
|
||||||
{
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValue(String value)
|
public void setValue(String value) {
|
||||||
{
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.picketlink.idm.model.AbstractAttributedType;
|
||||||
import org.picketlink.idm.model.Agent;
|
import org.picketlink.idm.model.Agent;
|
||||||
import org.picketlink.idm.model.Realm;
|
import org.picketlink.idm.model.Realm;
|
||||||
import org.picketlink.idm.model.Relationship;
|
import org.picketlink.idm.model.Relationship;
|
||||||
|
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||||
import org.picketlink.idm.model.annotation.IdentityProperty;
|
import org.picketlink.idm.model.annotation.IdentityProperty;
|
||||||
import org.picketlink.idm.query.RelationshipQueryParameter;
|
import org.picketlink.idm.query.RelationshipQueryParameter;
|
||||||
|
|
||||||
|
@ -11,8 +12,7 @@ import org.picketlink.idm.query.RelationshipQueryParameter;
|
||||||
* @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 RealmAdminRelationship extends AbstractAttributedType implements Relationship
|
public class RealmAdminRelationship extends AbstractAttributedType implements Relationship {
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public static final RelationshipQueryParameter REALM = new RelationshipQueryParameter() {
|
public static final RelationshipQueryParameter REALM = new RelationshipQueryParameter() {
|
||||||
|
@ -31,28 +31,24 @@ public class RealmAdminRelationship extends AbstractAttributedType implements Re
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected Realm realm;
|
protected String realm;
|
||||||
protected Agent admin;
|
protected Agent admin;
|
||||||
|
|
||||||
@IdentityProperty
|
@AttributeProperty
|
||||||
public Realm getRealm()
|
public String getRealm() {
|
||||||
{
|
|
||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRealm(Realm realm)
|
public void setRealm(String realm) {
|
||||||
{
|
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@IdentityProperty
|
@IdentityProperty
|
||||||
public Agent getAdmin()
|
public Agent getAdmin() {
|
||||||
{
|
|
||||||
return admin;
|
return admin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAdmin(Agent admin)
|
public void setAdmin(Agent admin) {
|
||||||
{
|
|
||||||
this.admin = admin;
|
this.admin = admin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
package org.keycloak.services.models.relationships;
|
|
||||||
|
|
||||||
import org.picketlink.idm.model.AbstractAttributedType;
|
|
||||||
import org.picketlink.idm.model.Agent;
|
|
||||||
import org.picketlink.idm.model.Relationship;
|
|
||||||
import org.picketlink.idm.model.annotation.IdentityProperty;
|
|
||||||
import org.picketlink.idm.query.RelationshipQueryParameter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class RealmResourceRelationship extends AbstractAttributedType implements Relationship
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public static final RelationshipQueryParameter REALM_AGENT = new RelationshipQueryParameter() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "realmAgent";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final RelationshipQueryParameter RESOURCE_AGENT = new RelationshipQueryParameter() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "resourceAgent";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected Agent realmAgent;
|
|
||||||
protected Agent resourceAgent;
|
|
||||||
|
|
||||||
@IdentityProperty
|
|
||||||
public Agent getRealmAgent()
|
|
||||||
{
|
|
||||||
return realmAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRealmAgent(Agent realmAgent)
|
|
||||||
{
|
|
||||||
this.realmAgent = realmAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@IdentityProperty
|
|
||||||
public Agent getResourceAgent()
|
|
||||||
{
|
|
||||||
return resourceAgent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setResourceAgent(Agent resourceAgent)
|
|
||||||
{
|
|
||||||
this.resourceAgent = resourceAgent;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,8 +11,7 @@ import org.picketlink.idm.query.RelationshipQueryParameter;
|
||||||
* @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 RequiredCredentialRelationship extends AbstractAttributedType implements Relationship
|
public class RequiredCredentialRelationship extends AbstractAttributedType implements Relationship {
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public static final RelationshipQueryParameter REALM_AGENT = new RelationshipQueryParameter() {
|
public static final RelationshipQueryParameter REALM_AGENT = new RelationshipQueryParameter() {
|
||||||
|
@ -29,51 +28,42 @@ public class RequiredCredentialRelationship extends AbstractAttributedType imple
|
||||||
protected boolean input;
|
protected boolean input;
|
||||||
protected boolean secret;
|
protected boolean secret;
|
||||||
|
|
||||||
public RequiredCredentialRelationship()
|
public RequiredCredentialRelationship() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@IdentityProperty
|
@IdentityProperty
|
||||||
public Agent getRealmAgent()
|
public Agent getRealmAgent() {
|
||||||
{
|
|
||||||
return realmAgent;
|
return realmAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRealmAgent(Agent realmAgent)
|
public void setRealmAgent(Agent realmAgent) {
|
||||||
{
|
|
||||||
this.realmAgent = realmAgent;
|
this.realmAgent = realmAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AttributeProperty
|
@AttributeProperty
|
||||||
public String getCredentialType()
|
public String getCredentialType() {
|
||||||
{
|
|
||||||
return credentialType;
|
return credentialType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCredentialType(String credentialType)
|
public void setCredentialType(String credentialType) {
|
||||||
{
|
|
||||||
this.credentialType = credentialType;
|
this.credentialType = credentialType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AttributeProperty
|
@AttributeProperty
|
||||||
public boolean isInput()
|
public boolean isInput() {
|
||||||
{
|
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInput(boolean input)
|
public void setInput(boolean input) {
|
||||||
{
|
|
||||||
this.input = input;
|
this.input = input;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AttributeProperty
|
@AttributeProperty
|
||||||
public boolean isSecret()
|
public boolean isSecret() {
|
||||||
{
|
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecret(boolean secret)
|
public void setSecret(boolean secret) {
|
||||||
{
|
|
||||||
this.secret = secret;
|
this.secret = secret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
package org.keycloak.services.models.relationships;
|
||||||
|
|
||||||
|
import org.picketlink.idm.model.AbstractAttributedType;
|
||||||
|
import org.picketlink.idm.model.Agent;
|
||||||
|
import org.picketlink.idm.model.Relationship;
|
||||||
|
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||||
|
import org.picketlink.idm.model.annotation.IdentityProperty;
|
||||||
|
import org.picketlink.idm.query.RelationshipQueryParameter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ResourceRelationship extends AbstractAttributedType implements Relationship {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public static final RelationshipQueryParameter REALM_AGENT = new RelationshipQueryParameter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "realmAgent";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected Agent realmAgent;
|
||||||
|
protected String resourceId;
|
||||||
|
protected String resourceName;
|
||||||
|
protected boolean surrogateAuthRequired;
|
||||||
|
protected boolean enabled;
|
||||||
|
|
||||||
|
@IdentityProperty
|
||||||
|
public Agent getRealmAgent() {
|
||||||
|
return realmAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealmAgent(Agent realmAgent) {
|
||||||
|
this.realmAgent = realmAgent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AttributeProperty
|
||||||
|
public String getResourceId() {
|
||||||
|
return resourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceId(String resourceId) {
|
||||||
|
this.resourceId = resourceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AttributeProperty
|
||||||
|
public String getResourceName() {
|
||||||
|
return resourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResourceName(String resourceName) {
|
||||||
|
this.resourceName = resourceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AttributeProperty
|
||||||
|
public boolean getSurrogateAuthRequired() {
|
||||||
|
return surrogateAuthRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
|
||||||
|
this.surrogateAuthRequired = surrogateAuthRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AttributeProperty
|
||||||
|
public boolean getEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,8 +11,7 @@ import org.picketlink.idm.query.RelationshipQueryParameter;
|
||||||
* @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 ScopeRelationship extends AbstractAttributedType implements Relationship
|
public class ScopeRelationship extends AbstractAttributedType implements Relationship {
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public static final RelationshipQueryParameter CLIENT = new RelationshipQueryParameter() {
|
public static final RelationshipQueryParameter CLIENT = new RelationshipQueryParameter() {
|
||||||
|
@ -27,24 +26,20 @@ public class ScopeRelationship extends AbstractAttributedType implements Relatio
|
||||||
protected Role scope;
|
protected Role scope;
|
||||||
|
|
||||||
@IdentityProperty
|
@IdentityProperty
|
||||||
public Agent getClient()
|
public Agent getClient() {
|
||||||
{
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClient(Agent client)
|
public void setClient(Agent client) {
|
||||||
{
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@IdentityProperty
|
@IdentityProperty
|
||||||
public Role getScope()
|
public Role getScope() {
|
||||||
{
|
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setScope(Role scope)
|
public void setScope(Role scope) {
|
||||||
{
|
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
|
import org.keycloak.SkeletonKeyContextResolver;
|
||||||
|
import org.keycloak.services.filters.IdentitySessionFilter;
|
||||||
|
import org.keycloak.services.models.relationships.RealmAdminRelationship;
|
||||||
|
import org.keycloak.services.models.relationships.ResourceRelationship;
|
||||||
|
import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
|
||||||
|
import org.keycloak.services.models.relationships.ScopeRelationship;
|
||||||
|
import org.picketlink.idm.IdentitySessionFactory;
|
||||||
|
import org.picketlink.idm.config.IdentityConfiguration;
|
||||||
|
import org.picketlink.idm.config.IdentityConfigurationBuilder;
|
||||||
|
import org.picketlink.idm.internal.DefaultIdentitySessionFactory;
|
||||||
|
import org.picketlink.idm.jpa.internal.ResourceLocalJpaIdentitySessionHandler;
|
||||||
|
import org.picketlink.idm.jpa.schema.CredentialObject;
|
||||||
|
import org.picketlink.idm.jpa.schema.CredentialObjectAttribute;
|
||||||
|
import org.picketlink.idm.jpa.schema.IdentityObject;
|
||||||
|
import org.picketlink.idm.jpa.schema.IdentityObjectAttribute;
|
||||||
|
import org.picketlink.idm.jpa.schema.PartitionObject;
|
||||||
|
import org.picketlink.idm.jpa.schema.RelationshipIdentityObject;
|
||||||
|
import org.picketlink.idm.jpa.schema.RelationshipObject;
|
||||||
|
import org.picketlink.idm.jpa.schema.RelationshipObjectAttribute;
|
||||||
|
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
import javax.ws.rs.core.Application;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class KeycloakApplication extends Application {
|
||||||
|
protected Set<Object> singletons = new HashSet<Object>();
|
||||||
|
protected Set<Class<?>> classes = new HashSet<Class<?>>();
|
||||||
|
|
||||||
|
protected IdentitySessionFactory factory;
|
||||||
|
|
||||||
|
public KeycloakApplication() {
|
||||||
|
this.factory = createFactory();
|
||||||
|
IdentitySessionFilter filter = new IdentitySessionFilter(factory);
|
||||||
|
singletons.add(new RealmsResource());
|
||||||
|
singletons.add(filter);
|
||||||
|
classes.add(SkeletonKeyContextResolver.class);
|
||||||
|
classes.add(RegistrationService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentitySessionFactory getFactory() {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
public void destroy() {
|
||||||
|
factory.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IdentitySessionFactory createFactory() {
|
||||||
|
ResourceLocalJpaIdentitySessionHandler handler = new ResourceLocalJpaIdentitySessionHandler("keycloak-identity-store");
|
||||||
|
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.stores()
|
||||||
|
.jpa()
|
||||||
|
.identityClass(IdentityObject.class)
|
||||||
|
.attributeClass(IdentityObjectAttribute.class)
|
||||||
|
.relationshipClass(RelationshipObject.class)
|
||||||
|
.relationshipIdentityClass(RelationshipIdentityObject.class)
|
||||||
|
.relationshipAttributeClass(RelationshipObjectAttribute.class)
|
||||||
|
.credentialClass(CredentialObject.class)
|
||||||
|
.credentialAttributeClass(CredentialObjectAttribute.class)
|
||||||
|
.partitionClass(PartitionObject.class)
|
||||||
|
.supportAllFeatures()
|
||||||
|
.supportRelationshipType(RealmAdminRelationship.class, ResourceRelationship.class, RequiredCredentialRelationship.class, ScopeRelationship.class)
|
||||||
|
.setIdentitySessionHandler(handler);
|
||||||
|
|
||||||
|
IdentityConfiguration build = builder.build();
|
||||||
|
return new DefaultIdentitySessionFactory(build);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Class<?>> getClasses() {
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Object> getSingletons() {
|
||||||
|
return singletons;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,343 +0,0 @@
|
||||||
package org.keycloak.services.resources;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.logging.Logger;
|
|
||||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
|
||||||
import org.keycloak.representations.idm.ResourceRepresentation;
|
|
||||||
import org.keycloak.representations.idm.RoleMappingRepresentation;
|
|
||||||
import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
|
||||||
import org.keycloak.services.models.RealmManager;
|
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
|
||||||
import org.keycloak.services.models.RealmModel;
|
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
|
||||||
import org.keycloak.services.models.ResourceModel;
|
|
||||||
import org.keycloak.services.models.UserCredentialModel;
|
|
||||||
import org.picketlink.idm.model.Attribute;
|
|
||||||
import org.picketlink.idm.model.Realm;
|
|
||||||
import org.picketlink.idm.model.Role;
|
|
||||||
import org.picketlink.idm.model.SimpleRole;
|
|
||||||
import org.picketlink.idm.model.SimpleUser;
|
|
||||||
import org.picketlink.idm.model.User;
|
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.WebApplicationException;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
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 javax.ws.rs.core.UriInfo;
|
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.security.KeyPairGenerator;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
@Path("/realmfactory")
|
|
||||||
public class RealmFactory
|
|
||||||
{
|
|
||||||
protected Logger logger = Logger.getLogger(RealmFactory.class);
|
|
||||||
|
|
||||||
protected RealmManager adapter;
|
|
||||||
protected AuthenticationManager authenticationManager;
|
|
||||||
protected RealmModel defaultRealm;
|
|
||||||
|
|
||||||
|
|
||||||
@Context
|
|
||||||
protected UriInfo uriInfo;
|
|
||||||
|
|
||||||
@Context
|
|
||||||
protected HttpHeaders headers;
|
|
||||||
|
|
||||||
|
|
||||||
public RealmFactory(RealmManager adapter)
|
|
||||||
{
|
|
||||||
this.adapter = adapter;
|
|
||||||
defaultRealm = adapter.getRealm(Realm.DEFAULT_REALM);
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Consumes("application/json")
|
|
||||||
public Response importDomain(RealmRepresentation rep)
|
|
||||||
{
|
|
||||||
RealmModel realm = createRealm(rep);
|
|
||||||
UriBuilder builder = uriInfo.getRequestUriBuilder().path(realm.getId());
|
|
||||||
return Response.created(builder.build())
|
|
||||||
.entity(RealmResource.realmRep(realm, uriInfo))
|
|
||||||
.type(MediaType.APPLICATION_JSON_TYPE).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RealmModel createRealm(RealmRepresentation rep)
|
|
||||||
{
|
|
||||||
User realmCreator = authenticationManager.authenticateToken(defaultRealm, headers);
|
|
||||||
Role creatorRole = defaultRealm.getIdm().getRole(RegistrationService.REALM_CREATOR_ROLE);
|
|
||||||
if (!defaultRealm.getIdm().hasRole(realmCreator, creatorRole))
|
|
||||||
{
|
|
||||||
logger.warn("not a realm creator");
|
|
||||||
throw new NotAuthorizedException("Bearer");
|
|
||||||
}
|
|
||||||
verifyRealmRepresentation(rep);
|
|
||||||
|
|
||||||
RealmModel realm = adapter.create(rep.getRealm());
|
|
||||||
realm.addRealmAdmin(realmCreator);
|
|
||||||
KeyPair keyPair = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
|
||||||
}
|
|
||||||
catch (NoSuchAlgorithmException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
realm.setPrivateKey(keyPair.getPrivate());
|
|
||||||
realm.setPublicKey(keyPair.getPublic());
|
|
||||||
realm.setName(rep.getRealm());
|
|
||||||
realm.setEnabled(rep.isEnabled());
|
|
||||||
realm.setTokenLifespan(rep.getTokenLifespan());
|
|
||||||
realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
|
|
||||||
realm.setSslNotRequired(rep.isSslNotRequired());
|
|
||||||
realm.setCookieLoginAllowed(rep.isCookieLoginAllowed());
|
|
||||||
realm.updateRealm();
|
|
||||||
|
|
||||||
|
|
||||||
Map<String, User> userMap = new HashMap<String, User>();
|
|
||||||
|
|
||||||
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials())
|
|
||||||
{
|
|
||||||
RequiredCredentialModel credential = new RequiredCredentialModel();
|
|
||||||
credential.setType(requiredCred.getType());
|
|
||||||
credential.setInput(requiredCred.isInput());
|
|
||||||
credential.setSecret(requiredCred.isSecret());
|
|
||||||
realm.addRequiredCredential(credential);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (UserRepresentation userRep : rep.getUsers())
|
|
||||||
{
|
|
||||||
User user = new SimpleUser(userRep.getUsername());
|
|
||||||
user.setEnabled(userRep.isEnabled());
|
|
||||||
if (userRep.getAttributes() != null)
|
|
||||||
{
|
|
||||||
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet())
|
|
||||||
{
|
|
||||||
user.setAttribute(new Attribute<String>(entry.getKey(), entry.getValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
realm.getIdm().add(user);
|
|
||||||
if (userRep.getCredentials() != null)
|
|
||||||
{
|
|
||||||
for (UserRepresentation.Credential cred : userRep.getCredentials())
|
|
||||||
{
|
|
||||||
UserCredentialModel credential = new UserCredentialModel();
|
|
||||||
credential.setType(cred.getType());
|
|
||||||
credential.setValue(cred.getValue());
|
|
||||||
realm.updateCredential(user, credential);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
userMap.put(user.getLoginName(), user);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, Role> roles = new HashMap<String, Role>();
|
|
||||||
|
|
||||||
if (rep.getRoles() != null)
|
|
||||||
{
|
|
||||||
for (String roleString : rep.getRoles())
|
|
||||||
{
|
|
||||||
SimpleRole role = new SimpleRole(roleString.trim());
|
|
||||||
realm.getIdm().add(role);
|
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rep.getRoleMappings() != null)
|
|
||||||
{
|
|
||||||
for (RoleMappingRepresentation mapping : rep.getRoleMappings())
|
|
||||||
{
|
|
||||||
User user = userMap.get(mapping.getUsername());
|
|
||||||
for (String roleString : mapping.getRoles())
|
|
||||||
{
|
|
||||||
Role role = roles.get(roleString.trim());
|
|
||||||
if (role == null)
|
|
||||||
{
|
|
||||||
role = new SimpleRole(roleString.trim());
|
|
||||||
realm.getIdm().add(role);
|
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
|
||||||
realm.getIdm().grantRole(user, role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rep.getScopeMappings() != null)
|
|
||||||
{
|
|
||||||
for (ScopeMappingRepresentation scope : rep.getScopeMappings())
|
|
||||||
{
|
|
||||||
for (String roleString : scope.getRoles())
|
|
||||||
{
|
|
||||||
Role role = roles.get(roleString.trim());
|
|
||||||
if (role == null)
|
|
||||||
{
|
|
||||||
role = new SimpleRole(roleString.trim());
|
|
||||||
realm.getIdm().add(role);
|
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
|
||||||
User user = userMap.get(scope.getUsername());
|
|
||||||
realm.addScope(user, role.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!roles.containsKey("*"))
|
|
||||||
{
|
|
||||||
SimpleRole wildcard = new SimpleRole("*");
|
|
||||||
realm.getIdm().add(wildcard);
|
|
||||||
roles.put("*", wildcard);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rep.getResources() != null)
|
|
||||||
{
|
|
||||||
createResources(rep, realm, userMap);
|
|
||||||
}
|
|
||||||
return realm;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void createResources(RealmRepresentation rep, RealmModel realm, Map<String, User> userMap)
|
|
||||||
{
|
|
||||||
for (ResourceRepresentation resourceRep : rep.getResources())
|
|
||||||
{
|
|
||||||
ResourceModel resource = realm.addResource(resourceRep.getName());
|
|
||||||
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
|
|
||||||
resource.updateResource();
|
|
||||||
Map<String, Role> roles = new HashMap<String, Role>();
|
|
||||||
if (resourceRep.getRoles() != null)
|
|
||||||
{
|
|
||||||
for (String roleString : rep.getRoles())
|
|
||||||
{
|
|
||||||
SimpleRole role = new SimpleRole(roleString.trim());
|
|
||||||
resource.getIdm().add(role);
|
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (resourceRep.getRoleMappings() != null)
|
|
||||||
{
|
|
||||||
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings())
|
|
||||||
{
|
|
||||||
User user = userMap.get(mapping.getUsername());
|
|
||||||
for (String roleString : mapping.getRoles())
|
|
||||||
{
|
|
||||||
Role role = roles.get(roleString.trim());
|
|
||||||
if (role == null)
|
|
||||||
{
|
|
||||||
role = new SimpleRole(roleString.trim());
|
|
||||||
resource.getIdm().add(role);
|
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
|
||||||
resource.getIdm().grantRole(user, role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (resourceRep.getScopeMappings() != null)
|
|
||||||
{
|
|
||||||
for (ScopeMappingRepresentation mapping : resourceRep.getScopeMappings())
|
|
||||||
{
|
|
||||||
User user = userMap.get(mapping.getUsername());
|
|
||||||
for (String roleString : mapping.getRoles())
|
|
||||||
{
|
|
||||||
Role role = roles.get(roleString.trim());
|
|
||||||
if (role == null)
|
|
||||||
{
|
|
||||||
role = new SimpleRole(roleString.trim());
|
|
||||||
resource.getIdm().add(role);
|
|
||||||
roles.put(role.getName(), role);
|
|
||||||
}
|
|
||||||
resource.addScope(user, role.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!roles.containsKey("*"))
|
|
||||||
{
|
|
||||||
SimpleRole wildcard = new SimpleRole("*");
|
|
||||||
resource.getIdm().add(wildcard);
|
|
||||||
roles.put("*", wildcard);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void verifyRealmRepresentation(RealmRepresentation rep)
|
|
||||||
{
|
|
||||||
if (rep.getRequiredCredentials() == null)
|
|
||||||
{
|
|
||||||
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
|
|
||||||
.entity("Realm credential requirements not defined").type("text/plain").build());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap<String, UserRepresentation> userReps = new HashMap<String, UserRepresentation>();
|
|
||||||
for (UserRepresentation userRep : rep.getUsers()) userReps.put(userRep.getUsername(), userRep);
|
|
||||||
|
|
||||||
// override enabled to false if user does not have at least all of browser or client credentials
|
|
||||||
for (UserRepresentation userRep : rep.getUsers())
|
|
||||||
{
|
|
||||||
if (userRep.getCredentials() == null)
|
|
||||||
{
|
|
||||||
userRep.setEnabled(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
boolean hasBrowserCredentials = true;
|
|
||||||
for (RequiredCredentialRepresentation credential : rep.getRequiredCredentials())
|
|
||||||
{
|
|
||||||
boolean hasCredential = false;
|
|
||||||
for (UserRepresentation.Credential cred : userRep.getCredentials())
|
|
||||||
{
|
|
||||||
if (cred.getType().equals(credential.getType()))
|
|
||||||
{
|
|
||||||
hasCredential = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasCredential)
|
|
||||||
{
|
|
||||||
hasBrowserCredentials = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasBrowserCredentials)
|
|
||||||
{
|
|
||||||
userRep.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rep.getResources() != null)
|
|
||||||
{
|
|
||||||
// check mappings
|
|
||||||
for (ResourceRepresentation resourceRep : rep.getResources())
|
|
||||||
{
|
|
||||||
if (resourceRep.getRoleMappings() != null)
|
|
||||||
{
|
|
||||||
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings())
|
|
||||||
{
|
|
||||||
if (!userReps.containsKey(mapping.getUsername()))
|
|
||||||
{
|
|
||||||
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
|
|
||||||
.entity("No users declared for role mapping").type("text/plain").build());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
package org.keycloak.services.resources;
|
|
||||||
|
|
||||||
import org.keycloak.services.models.RealmManager;
|
|
||||||
import org.jboss.resteasy.logging.Logger;
|
|
||||||
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
|
||||||
import org.keycloak.services.models.RealmModel;
|
|
||||||
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.NotFoundException;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
@Path("/realms")
|
|
||||||
public class RealmResource
|
|
||||||
{
|
|
||||||
protected Logger logger = Logger.getLogger(RealmResource.class);
|
|
||||||
protected RealmManager adapter;
|
|
||||||
@Context
|
|
||||||
protected UriInfo uriInfo;
|
|
||||||
|
|
||||||
public RealmResource(RealmManager adapter)
|
|
||||||
{
|
|
||||||
this.adapter = adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{realm}")
|
|
||||||
@Produces("application/json")
|
|
||||||
public PublishedRealmRepresentation getRealm(@PathParam("realm") String id)
|
|
||||||
{
|
|
||||||
RealmModel realm = adapter.getRealm(id);
|
|
||||||
if (realm == null)
|
|
||||||
{
|
|
||||||
logger.debug("realm not found");
|
|
||||||
throw new NotFoundException();
|
|
||||||
}
|
|
||||||
return realmRep(realm, uriInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("{realm}.html")
|
|
||||||
@Produces("text/html")
|
|
||||||
public String getRealmHtml(@PathParam("realm") String id)
|
|
||||||
{
|
|
||||||
RealmModel realm = adapter.getRealm(id);
|
|
||||||
if (realm == null)
|
|
||||||
{
|
|
||||||
logger.debug("realm not found");
|
|
||||||
throw new NotFoundException();
|
|
||||||
}
|
|
||||||
return realmHtml(realm);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String realmHtml(RealmModel realm)
|
|
||||||
{
|
|
||||||
StringBuffer html = new StringBuffer();
|
|
||||||
|
|
||||||
UriBuilder auth = uriInfo.getBaseUriBuilder();
|
|
||||||
auth.path(TokenService.class)
|
|
||||||
.path(TokenService.class, "requestAccessCode");
|
|
||||||
String authUri = auth.build(realm.getId()).toString();
|
|
||||||
|
|
||||||
UriBuilder code = uriInfo.getBaseUriBuilder();
|
|
||||||
code.path(TokenService.class).path(TokenService.class, "accessRequest");
|
|
||||||
String codeUri = code.build(realm.getId()).toString();
|
|
||||||
|
|
||||||
UriBuilder grant = uriInfo.getBaseUriBuilder();
|
|
||||||
grant.path(TokenService.class).path(TokenService.class, "accessTokenGrant");
|
|
||||||
String grantUrl = grant.build(realm.getId()).toString();
|
|
||||||
|
|
||||||
UriBuilder idGrant = uriInfo.getBaseUriBuilder();
|
|
||||||
grant.path(TokenService.class).path(TokenService.class, "identityTokenGrant");
|
|
||||||
String idGrantUrl = idGrant.build(realm.getId()).toString();
|
|
||||||
|
|
||||||
html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
|
|
||||||
html.append("<p>auth: ").append(authUri).append("</p>");
|
|
||||||
html.append("<p>code: ").append(codeUri).append("</p>");
|
|
||||||
html.append("<p>grant: ").append(grantUrl).append("</p>");
|
|
||||||
html.append("<p>identity grant: ").append(idGrantUrl).append("</p>");
|
|
||||||
html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>");
|
|
||||||
html.append("</body></html>");
|
|
||||||
|
|
||||||
return html.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo)
|
|
||||||
{
|
|
||||||
PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
|
|
||||||
rep.setRealm(realm.getName());
|
|
||||||
rep.setSelf(uriInfo.getRequestUri().toString());
|
|
||||||
rep.setPublicKeyPem(realm.getPublicKeyPem());
|
|
||||||
|
|
||||||
UriBuilder auth = uriInfo.getBaseUriBuilder();
|
|
||||||
auth.path(TokenService.class)
|
|
||||||
.path(TokenService.class, "requestAccessCode");
|
|
||||||
rep.setAuthorizationUrl(auth.build(realm.getId()).toString());
|
|
||||||
|
|
||||||
UriBuilder code = uriInfo.getBaseUriBuilder();
|
|
||||||
code.path(TokenService.class).path(TokenService.class, "accessRequest");
|
|
||||||
rep.setCodeUrl(code.build(realm.getId()).toString());
|
|
||||||
|
|
||||||
UriBuilder grant = uriInfo.getBaseUriBuilder();
|
|
||||||
grant.path(TokenService.class).path(TokenService.class, "accessTokenGrant");
|
|
||||||
String grantUrl = grant.build(realm.getId()).toString();
|
|
||||||
rep.setGrantUrl(grantUrl);
|
|
||||||
|
|
||||||
UriBuilder idGrant = uriInfo.getBaseUriBuilder();
|
|
||||||
grant.path(TokenService.class).path(TokenService.class, "identityTokenGrant");
|
|
||||||
String idGrantUrl = idGrant.build(realm.getId()).toString();
|
|
||||||
rep.setIdentityGrantUrl(idGrantUrl);
|
|
||||||
return rep;
|
|
||||||
}
|
|
||||||
}
|
|
105
services/src/main/java/org/keycloak/services/resources/RealmSubResource.java
Executable file
105
services/src/main/java/org/keycloak/services/resources/RealmSubResource.java
Executable file
|
@ -0,0 +1,105 @@
|
||||||
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.logging.Logger;
|
||||||
|
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
|
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class RealmSubResource {
|
||||||
|
protected static final Logger logger = Logger.getLogger(RealmSubResource.class);
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected UriInfo uriInfo;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected IdentitySession IdentitySession;
|
||||||
|
|
||||||
|
protected RealmModel realm;
|
||||||
|
|
||||||
|
public RealmSubResource(RealmModel realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("json")
|
||||||
|
@Produces("application/json")
|
||||||
|
public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) {
|
||||||
|
return realmRep(realm, uriInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("html")
|
||||||
|
@Produces("text/html")
|
||||||
|
public String getRealmHtml(@PathParam("realm") String id) {
|
||||||
|
StringBuffer html = new StringBuffer();
|
||||||
|
|
||||||
|
UriBuilder auth = uriInfo.getBaseUriBuilder();
|
||||||
|
auth.path(TokenService.class)
|
||||||
|
.path(TokenService.class, "requestAccessCode");
|
||||||
|
String authUri = auth.build(realm.getId()).toString();
|
||||||
|
|
||||||
|
UriBuilder code = uriInfo.getBaseUriBuilder();
|
||||||
|
code.path(TokenService.class).path(TokenService.class, "accessRequest");
|
||||||
|
String codeUri = code.build(realm.getId()).toString();
|
||||||
|
|
||||||
|
UriBuilder grant = uriInfo.getBaseUriBuilder();
|
||||||
|
grant.path(TokenService.class).path(TokenService.class, "accessTokenGrant");
|
||||||
|
String grantUrl = grant.build(realm.getId()).toString();
|
||||||
|
|
||||||
|
UriBuilder idGrant = uriInfo.getBaseUriBuilder();
|
||||||
|
grant.path(TokenService.class).path(TokenService.class, "identityTokenGrant");
|
||||||
|
String idGrantUrl = idGrant.build(realm.getId()).toString();
|
||||||
|
|
||||||
|
html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
|
||||||
|
html.append("<p>auth: ").append(authUri).append("</p>");
|
||||||
|
html.append("<p>code: ").append(codeUri).append("</p>");
|
||||||
|
html.append("<p>grant: ").append(grantUrl).append("</p>");
|
||||||
|
html.append("<p>identity grant: ").append(idGrantUrl).append("</p>");
|
||||||
|
html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>");
|
||||||
|
html.append("</body></html>");
|
||||||
|
|
||||||
|
return html.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {
|
||||||
|
PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
|
||||||
|
rep.setRealm(realm.getName());
|
||||||
|
rep.setSelf(uriInfo.getRequestUri().toString());
|
||||||
|
rep.setPublicKeyPem(realm.getPublicKeyPem());
|
||||||
|
|
||||||
|
UriBuilder auth = uriInfo.getBaseUriBuilder();
|
||||||
|
auth.path(RealmsResource.class).path(RealmsResource.class, "getTokenService")
|
||||||
|
.path(TokenService.class, "requestAccessCode");
|
||||||
|
rep.setAuthorizationUrl(auth.build(realm.getId()).toString());
|
||||||
|
|
||||||
|
UriBuilder code = uriInfo.getBaseUriBuilder();
|
||||||
|
code.path(RealmsResource.class).path(RealmsResource.class, "getTokenService").path(TokenService.class, "accessRequest");
|
||||||
|
rep.setCodeUrl(code.build(realm.getId()).toString());
|
||||||
|
|
||||||
|
UriBuilder grant = uriInfo.getBaseUriBuilder();
|
||||||
|
grant.path(RealmsResource.class).path(RealmsResource.class, "getTokenService").path(TokenService.class, "accessTokenGrant");
|
||||||
|
String grantUrl = grant.build(realm.getId()).toString();
|
||||||
|
rep.setGrantUrl(grantUrl);
|
||||||
|
|
||||||
|
UriBuilder idGrant = uriInfo.getBaseUriBuilder();
|
||||||
|
grant.path(RealmsResource.class).path(RealmsResource.class, "getTokenService").path(TokenService.class, "identityTokenGrant");
|
||||||
|
String idGrantUrl = idGrant.build(realm.getId()).toString();
|
||||||
|
rep.setIdentityGrantUrl(idGrantUrl);
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
323
services/src/main/java/org/keycloak/services/resources/RealmsResource.java
Executable file
323
services/src/main/java/org/keycloak/services/resources/RealmsResource.java
Executable file
|
@ -0,0 +1,323 @@
|
||||||
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.logging.Logger;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ResourceRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RoleMappingRepresentation;
|
||||||
|
import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.keycloak.services.managers.AccessCodeEntry;
|
||||||
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
|
import org.keycloak.services.models.RealmManager;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
import org.keycloak.services.models.RequiredCredentialModel;
|
||||||
|
import org.keycloak.services.models.ResourceModel;
|
||||||
|
import org.keycloak.services.models.UserCredentialModel;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
|
import org.picketlink.idm.model.Attribute;
|
||||||
|
import org.picketlink.idm.model.Realm;
|
||||||
|
import org.picketlink.idm.model.Role;
|
||||||
|
import org.picketlink.idm.model.SimpleRole;
|
||||||
|
import org.picketlink.idm.model.SimpleUser;
|
||||||
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
|
import javax.ws.rs.NotFoundException;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.container.ResourceContext;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
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 javax.ws.rs.core.UriInfo;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@Path("/realms")
|
||||||
|
public class RealmsResource {
|
||||||
|
protected static Logger logger = Logger.getLogger(RealmsResource.class);
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected UriInfo uriInfo;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected HttpHeaders headers;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected
|
||||||
|
IdentitySession IdentitySession;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
ResourceContext resourceContext;
|
||||||
|
|
||||||
|
protected Map<String, AccessCodeEntry> accessCodes = new ConcurrentHashMap<String, AccessCodeEntry>();
|
||||||
|
|
||||||
|
@Path("{realm}/tokens")
|
||||||
|
public TokenService getTokenService(@PathParam("realm") String id) {
|
||||||
|
RealmManager realmManager = new RealmManager(IdentitySession);
|
||||||
|
RealmModel realm = realmManager.getRealm(id);
|
||||||
|
if (realm == null) {
|
||||||
|
logger.debug("realm not found");
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
TokenService tokenService = new TokenService(realm, accessCodes);
|
||||||
|
resourceContext.initResource(tokenService);
|
||||||
|
return tokenService;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Path("{realm}")
|
||||||
|
public RealmSubResource getRealmResource(@PathParam("realm") String id) {
|
||||||
|
RealmManager realmManager = new RealmManager(IdentitySession);
|
||||||
|
RealmModel realm = realmManager.getRealm(id);
|
||||||
|
if (realm == null) {
|
||||||
|
logger.debug("realm not found");
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
RealmSubResource realmResource = new RealmSubResource(realm);
|
||||||
|
resourceContext.initResource(realmResource);
|
||||||
|
return realmResource;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Consumes("application/json")
|
||||||
|
public Response importRealm(RealmRepresentation rep) {
|
||||||
|
IdentitySession.getTransaction().begin();
|
||||||
|
RealmModel realm;
|
||||||
|
try {
|
||||||
|
realm = createRealm(rep);
|
||||||
|
IdentitySession.getTransaction().commit();
|
||||||
|
} catch (RuntimeException re) {
|
||||||
|
IdentitySession.getTransaction().rollback();
|
||||||
|
throw re;
|
||||||
|
}
|
||||||
|
UriBuilder builder = uriInfo.getRequestUriBuilder().path(realm.getId());
|
||||||
|
return Response.created(builder.build())
|
||||||
|
.entity(RealmSubResource.realmRep(realm, uriInfo))
|
||||||
|
.type(MediaType.APPLICATION_JSON_TYPE).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RealmModel createRealm(RealmRepresentation rep) {
|
||||||
|
RealmManager realmManager = new RealmManager(IdentitySession);
|
||||||
|
RealmModel defaultRealm = realmManager.getRealm(Realm.DEFAULT_REALM);
|
||||||
|
User realmCreator = new AuthenticationManager().authenticateToken(defaultRealm, headers);
|
||||||
|
Role creatorRole = defaultRealm.getIdm().getRole(RegistrationService.REALM_CREATOR_ROLE);
|
||||||
|
if (!defaultRealm.getIdm().hasRole(realmCreator, creatorRole)) {
|
||||||
|
logger.warn("not a realm creator");
|
||||||
|
throw new NotAuthorizedException("Bearer");
|
||||||
|
}
|
||||||
|
verifyRealmRepresentation(rep);
|
||||||
|
|
||||||
|
RealmModel realm = realmManager.createRealm(rep.getRealm());
|
||||||
|
realmManager.generateRealmKeys(realm);
|
||||||
|
realm.addRealmAdmin(realmCreator);
|
||||||
|
realm.setName(rep.getRealm());
|
||||||
|
realm.setEnabled(rep.isEnabled());
|
||||||
|
realm.setTokenLifespan(rep.getTokenLifespan());
|
||||||
|
realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
|
||||||
|
realm.setSslNotRequired(rep.isSslNotRequired());
|
||||||
|
realm.setCookieLoginAllowed(rep.isCookieLoginAllowed());
|
||||||
|
realm.updateRealm();
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, User> userMap = new HashMap<String, User>();
|
||||||
|
|
||||||
|
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials()) {
|
||||||
|
RequiredCredentialModel credential = new RequiredCredentialModel();
|
||||||
|
credential.setType(requiredCred.getType());
|
||||||
|
credential.setInput(requiredCred.isInput());
|
||||||
|
credential.setSecret(requiredCred.isSecret());
|
||||||
|
realm.addRequiredCredential(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UserRepresentation userRep : rep.getUsers()) {
|
||||||
|
User user = new SimpleUser(userRep.getUsername());
|
||||||
|
user.setEnabled(userRep.isEnabled());
|
||||||
|
if (userRep.getAttributes() != null) {
|
||||||
|
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
|
||||||
|
user.setAttribute(new Attribute<String>(entry.getKey(), entry.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.getIdm().add(user);
|
||||||
|
if (userRep.getCredentials() != null) {
|
||||||
|
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
|
||||||
|
UserCredentialModel credential = new UserCredentialModel();
|
||||||
|
credential.setType(cred.getType());
|
||||||
|
credential.setValue(cred.getValue());
|
||||||
|
realm.updateCredential(user, credential);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userMap.put(user.getLoginName(), user);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Role> roles = new HashMap<String, Role>();
|
||||||
|
|
||||||
|
if (rep.getRoles() != null) {
|
||||||
|
for (String roleString : rep.getRoles()) {
|
||||||
|
SimpleRole role = new SimpleRole(roleString.trim());
|
||||||
|
realm.getIdm().add(role);
|
||||||
|
roles.put(role.getName(), role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rep.getRoleMappings() != null) {
|
||||||
|
for (RoleMappingRepresentation mapping : rep.getRoleMappings()) {
|
||||||
|
User user = userMap.get(mapping.getUsername());
|
||||||
|
for (String roleString : mapping.getRoles()) {
|
||||||
|
Role role = roles.get(roleString.trim());
|
||||||
|
if (role == null) {
|
||||||
|
role = new SimpleRole(roleString.trim());
|
||||||
|
realm.getIdm().add(role);
|
||||||
|
roles.put(role.getName(), role);
|
||||||
|
}
|
||||||
|
realm.getIdm().grantRole(user, role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rep.getScopeMappings() != null) {
|
||||||
|
for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
|
||||||
|
for (String roleString : scope.getRoles()) {
|
||||||
|
Role role = roles.get(roleString.trim());
|
||||||
|
if (role == null) {
|
||||||
|
role = new SimpleRole(roleString.trim());
|
||||||
|
realm.getIdm().add(role);
|
||||||
|
roles.put(role.getName(), role);
|
||||||
|
}
|
||||||
|
User user = userMap.get(scope.getUsername());
|
||||||
|
realm.addScope(user, role.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!roles.containsKey("*")) {
|
||||||
|
SimpleRole wildcard = new SimpleRole("*");
|
||||||
|
realm.getIdm().add(wildcard);
|
||||||
|
roles.put("*", wildcard);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rep.getResources() != null) {
|
||||||
|
createResources(rep, realm, userMap);
|
||||||
|
}
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createResources(RealmRepresentation rep, RealmModel realm, Map<String, User> userMap) {
|
||||||
|
for (ResourceRepresentation resourceRep : rep.getResources()) {
|
||||||
|
ResourceModel resource = realm.addResource(resourceRep.getName());
|
||||||
|
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
|
||||||
|
resource.updateResource();
|
||||||
|
Map<String, Role> roles = new HashMap<String, Role>();
|
||||||
|
if (resourceRep.getRoles() != null) {
|
||||||
|
for (String roleString : resourceRep.getRoles()) {
|
||||||
|
SimpleRole role = new SimpleRole(roleString.trim());
|
||||||
|
resource.getIdm().add(role);
|
||||||
|
roles.put(role.getName(), role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resourceRep.getRoleMappings() != null) {
|
||||||
|
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
|
||||||
|
User user = userMap.get(mapping.getUsername());
|
||||||
|
for (String roleString : mapping.getRoles()) {
|
||||||
|
Role role = roles.get(roleString.trim());
|
||||||
|
if (role == null) {
|
||||||
|
role = new SimpleRole(roleString.trim());
|
||||||
|
resource.getIdm().add(role);
|
||||||
|
roles.put(role.getName(), role);
|
||||||
|
}
|
||||||
|
Role role1 = resource.getIdm().getRole(role.getName());
|
||||||
|
realm.getIdm().grantRole(user, role1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resourceRep.getScopeMappings() != null) {
|
||||||
|
for (ScopeMappingRepresentation mapping : resourceRep.getScopeMappings()) {
|
||||||
|
User user = userMap.get(mapping.getUsername());
|
||||||
|
for (String roleString : mapping.getRoles()) {
|
||||||
|
Role role = roles.get(roleString.trim());
|
||||||
|
if (role == null) {
|
||||||
|
role = new SimpleRole(roleString.trim());
|
||||||
|
resource.getIdm().add(role);
|
||||||
|
roles.put(role.getName(), role);
|
||||||
|
}
|
||||||
|
resource.addScope(user, role.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!roles.containsKey("*")) {
|
||||||
|
SimpleRole wildcard = new SimpleRole("*");
|
||||||
|
resource.getIdm().add(wildcard);
|
||||||
|
roles.put("*", wildcard);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void verifyRealmRepresentation(RealmRepresentation rep) {
|
||||||
|
if (rep.getRequiredCredentials() == null) {
|
||||||
|
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("Realm credential requirements not defined").type("text/plain").build());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<String, UserRepresentation> userReps = new HashMap<String, UserRepresentation>();
|
||||||
|
for (UserRepresentation userRep : rep.getUsers()) userReps.put(userRep.getUsername(), userRep);
|
||||||
|
|
||||||
|
// override enabled to false if user does not have at least all of browser or client credentials
|
||||||
|
for (UserRepresentation userRep : rep.getUsers()) {
|
||||||
|
if (userRep.getCredentials() == null) {
|
||||||
|
userRep.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
boolean hasBrowserCredentials = true;
|
||||||
|
for (RequiredCredentialRepresentation credential : rep.getRequiredCredentials()) {
|
||||||
|
boolean hasCredential = false;
|
||||||
|
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
|
||||||
|
if (cred.getType().equals(credential.getType())) {
|
||||||
|
hasCredential = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasCredential) {
|
||||||
|
hasBrowserCredentials = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasBrowserCredentials) {
|
||||||
|
userRep.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rep.getResources() != null) {
|
||||||
|
// check mappings
|
||||||
|
for (ResourceRepresentation resourceRep : rep.getResources()) {
|
||||||
|
if (resourceRep.getRoleMappings() != null) {
|
||||||
|
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
|
||||||
|
if (!userReps.containsKey(mapping.getUsername())) {
|
||||||
|
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity("No users declared for role mapping").type("text/plain").build());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,15 +1,17 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.services.models.RealmManager;
|
import org.keycloak.services.models.RealmManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.UserCredentialModel;
|
import org.keycloak.services.models.UserCredentialModel;
|
||||||
import org.picketlink.idm.model.Realm;
|
import org.picketlink.idm.IdentitySession;
|
||||||
import org.picketlink.idm.model.Role;
|
import org.picketlink.idm.model.Role;
|
||||||
import org.picketlink.idm.model.SimpleUser;
|
import org.picketlink.idm.model.SimpleUser;
|
||||||
import org.picketlink.idm.model.User;
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.ForbiddenException;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
|
@ -23,37 +25,37 @@ import java.net.URI;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
@Path("/registrations")
|
@Path("/registrations")
|
||||||
public class RegistrationService
|
public class RegistrationService {
|
||||||
{
|
protected static final Logger logger = Logger.getLogger(RegistrationService.class);
|
||||||
public static final String REALM_CREATOR_ROLE = "realm-creator";
|
public static final String REALM_CREATOR_ROLE = "realm-creator";
|
||||||
protected RealmManager adapter;
|
|
||||||
protected RealmModel defaultRealm;
|
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
protected UriInfo uriInfo;
|
protected UriInfo uriInfo;
|
||||||
|
|
||||||
public RegistrationService(RealmManager adapter)
|
@Context
|
||||||
{
|
protected IdentitySession identitySession;
|
||||||
this.adapter = adapter;
|
|
||||||
defaultRealm = adapter.getRealm(Realm.DEFAULT_REALM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Response register(UserRepresentation newUser)
|
public Response register(UserRepresentation newUser) {
|
||||||
{
|
identitySession.getTransaction().begin();
|
||||||
|
try {
|
||||||
|
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());
|
User user = defaultRealm.getIdm().getUser(newUser.getUsername());
|
||||||
if (user != null)
|
if (user != null) {
|
||||||
{
|
|
||||||
return Response.status(400).type("text/plain").entity("user exists").build();
|
return Response.status(400).type("text/plain").entity("user exists").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
user = new SimpleUser(newUser.getUsername());
|
user = new SimpleUser(newUser.getUsername());
|
||||||
defaultRealm.getIdm().add(user);
|
defaultRealm.getIdm().add(user);
|
||||||
for (UserRepresentation.Credential cred : newUser.getCredentials())
|
for (UserRepresentation.Credential cred : newUser.getCredentials()) {
|
||||||
{
|
|
||||||
UserCredentialModel credModel = new UserCredentialModel();
|
UserCredentialModel credModel = new UserCredentialModel();
|
||||||
credModel.setType(cred.getType());
|
credModel.setType(cred.getType());
|
||||||
credModel.setValue(cred.getValue());
|
credModel.setValue(cred.getValue());
|
||||||
|
@ -61,8 +63,14 @@ public class RegistrationService
|
||||||
}
|
}
|
||||||
Role realmCreator = defaultRealm.getIdm().getRole(REALM_CREATOR_ROLE);
|
Role realmCreator = defaultRealm.getIdm().getRole(REALM_CREATOR_ROLE);
|
||||||
defaultRealm.getIdm().grantRole(user, realmCreator);
|
defaultRealm.getIdm().grantRole(user, realmCreator);
|
||||||
URI uri = uriInfo.getBaseUriBuilder().path(RealmFactory.class).path(user.getLoginName()).build();
|
identitySession.getTransaction().commit();
|
||||||
|
URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
|
||||||
return Response.created(uri).build();
|
return Response.created(uri).build();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
logger.error("Failed to register", e);
|
||||||
|
identitySession.getTransaction().rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
package org.keycloak.services.resources;
|
|
||||||
|
|
||||||
import org.infinispan.Cache;
|
|
||||||
import org.infinispan.manager.DefaultCacheManager;
|
|
||||||
import org.keycloak.SkeletonKeyContextResolver;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.Application;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class SkeletonKeyApplication extends Application
|
|
||||||
{
|
|
||||||
protected Set<Object> singletons = new HashSet<Object>();
|
|
||||||
protected Set<Class<?>> classes = new HashSet<Class<?>>();
|
|
||||||
|
|
||||||
public SkeletonKeyApplication()
|
|
||||||
{
|
|
||||||
Cache cache = getCache();
|
|
||||||
singletons.add(new TokenService(null));
|
|
||||||
singletons.add(new RealmFactory(null));
|
|
||||||
singletons.add(new RealmResource(null));
|
|
||||||
classes.add(SkeletonKeyContextResolver.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Class<?>> getClasses()
|
|
||||||
{
|
|
||||||
return classes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<Object> getSingletons()
|
|
||||||
{
|
|
||||||
return singletons;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Cache getCache()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("skeleton-key.xml");
|
|
||||||
return new DefaultCacheManager(is).getCache("skeleton-key");
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,21 +9,21 @@ import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.representations.AccessTokenResponse;
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
import org.keycloak.representations.SkeletonKeyScope;
|
import org.keycloak.representations.SkeletonKeyScope;
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
|
import org.keycloak.services.managers.AccessCodeEntry;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
import org.keycloak.services.models.RealmManager;
|
import org.keycloak.services.models.RealmManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
import org.keycloak.services.models.RequiredCredentialModel;
|
||||||
import org.keycloak.services.models.ResourceModel;
|
import org.keycloak.services.models.ResourceModel;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
import org.picketlink.idm.model.User;
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
import javax.ws.rs.NotFoundException;
|
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
|
@ -41,69 +41,17 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@Path("/realms")
|
public class TokenService {
|
||||||
public class TokenService
|
|
||||||
{
|
|
||||||
public static class AccessCode
|
|
||||||
{
|
|
||||||
protected String id = UUID.randomUUID().toString() + System.currentTimeMillis();
|
|
||||||
protected long expiration;
|
|
||||||
protected SkeletonKeyToken token;
|
|
||||||
protected User client;
|
|
||||||
|
|
||||||
public boolean isExpired()
|
|
||||||
{
|
|
||||||
return expiration != 0 && (System.currentTimeMillis() / 1000) > expiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId()
|
protected static final Logger logger = Logger.getLogger(TokenService.class);
|
||||||
{
|
protected Map<String, AccessCodeEntry> accessCodeMap;
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getExpiration()
|
|
||||||
{
|
|
||||||
return expiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpiration(long expiration)
|
|
||||||
{
|
|
||||||
this.expiration = expiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SkeletonKeyToken getToken()
|
|
||||||
{
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(SkeletonKeyToken token)
|
|
||||||
{
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public User getClient()
|
|
||||||
{
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClient(User client)
|
|
||||||
{
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected RealmManager adapter;
|
|
||||||
protected TokenManager tokenManager;
|
|
||||||
protected AuthenticationManager authManager;
|
|
||||||
protected Logger logger = Logger.getLogger(TokenService.class);
|
|
||||||
protected Map<String, AccessCode> accessCodeMap = new HashMap<String, AccessCode>();
|
|
||||||
@Context
|
@Context
|
||||||
protected UriInfo uriInfo;
|
protected UriInfo uriInfo;
|
||||||
@Context
|
@Context
|
||||||
|
@ -112,86 +60,68 @@ public class TokenService
|
||||||
protected SecurityContext securityContext;
|
protected SecurityContext securityContext;
|
||||||
@Context
|
@Context
|
||||||
protected HttpHeaders headers;
|
protected HttpHeaders headers;
|
||||||
|
@Context
|
||||||
|
protected
|
||||||
|
IdentitySession IdentitySession;
|
||||||
|
|
||||||
private static AtomicLong counter = new AtomicLong(1);
|
protected RealmModel realm;
|
||||||
private static String generateId()
|
protected TokenManager tokenManager = new TokenManager();
|
||||||
{
|
protected AuthenticationManager authManager = new AuthenticationManager();
|
||||||
return counter.getAndIncrement() + "." + UUID.randomUUID().toString();
|
|
||||||
|
public TokenService(RealmModel realm, Map<String, AccessCodeEntry> accessCodeMap) {
|
||||||
|
this.realm = realm;
|
||||||
|
this.accessCodeMap = accessCodeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TokenService(RealmManager adapter)
|
@Path("grants/identity-token")
|
||||||
{
|
|
||||||
this.adapter = adapter;
|
|
||||||
this.tokenManager = new TokenManager(adapter);
|
|
||||||
this.authManager = new AuthenticationManager(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Path("{realm}/grants/identity-token")
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response identityTokenGrant(@PathParam("realm") String realmId, MultivaluedMap<String, String> form)
|
public Response identityTokenGrant(MultivaluedMap<String, String> form) {
|
||||||
{
|
|
||||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
if (username == null)
|
if (username == null) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("No user");
|
throw new NotAuthorizedException("No user");
|
||||||
}
|
}
|
||||||
RealmModel realm = adapter.getRealm(realmId);
|
if (!realm.isEnabled()) {
|
||||||
if (realm == null)
|
|
||||||
{
|
|
||||||
throw new NotFoundException("Realm not found");
|
|
||||||
}
|
|
||||||
if (!realm.isEnabled())
|
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Disabled realm");
|
throw new NotAuthorizedException("Disabled realm");
|
||||||
}
|
}
|
||||||
User user = realm.getIdm().getUser(username);
|
User user = realm.getIdm().getUser(username);
|
||||||
if (user == null)
|
if (user == null) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("No user");
|
throw new NotAuthorizedException("No user");
|
||||||
}
|
}
|
||||||
if (!user.isEnabled())
|
if (!user.isEnabled()) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Disabled user.");
|
throw new NotAuthorizedException("Disabled user.");
|
||||||
}
|
}
|
||||||
|
if (!authManager.authenticateForm(realm, user, form)) {
|
||||||
|
throw new NotAuthorizedException("FORM");
|
||||||
|
}
|
||||||
|
tokenManager = new TokenManager();
|
||||||
SkeletonKeyToken token = tokenManager.createIdentityToken(realm, username);
|
SkeletonKeyToken token = tokenManager.createIdentityToken(realm, username);
|
||||||
String encoded = tokenManager.encodeToken(realm, token);
|
String encoded = tokenManager.encodeToken(realm, token);
|
||||||
AccessTokenResponse res = accessTokenResponse(token, encoded);
|
AccessTokenResponse res = accessTokenResponse(token, encoded);
|
||||||
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{realm}/grants/access")
|
@Path("grants/access")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response accessTokenGrant(@PathParam("realm") String realmId, MultivaluedMap<String, String> form)
|
public Response accessTokenGrant(MultivaluedMap<String, String> form) {
|
||||||
{
|
|
||||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
if (username == null)
|
if (username == null) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("No user");
|
throw new NotAuthorizedException("No user");
|
||||||
}
|
}
|
||||||
RealmModel realm = adapter.getRealm(realmId);
|
if (!realm.isEnabled()) {
|
||||||
if (realm == null)
|
|
||||||
{
|
|
||||||
throw new NotFoundException("Realm not found");
|
|
||||||
}
|
|
||||||
if (!realm.isEnabled())
|
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Disabled realm");
|
throw new NotAuthorizedException("Disabled realm");
|
||||||
}
|
}
|
||||||
User user = realm.getIdm().getUser(username);
|
User user = realm.getIdm().getUser(username);
|
||||||
if (user == null)
|
if (user == null) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("No user");
|
throw new NotAuthorizedException("No user");
|
||||||
}
|
}
|
||||||
if (!user.isEnabled())
|
if (!user.isEnabled()) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Disabled user.");
|
throw new NotAuthorizedException("Disabled user.");
|
||||||
}
|
}
|
||||||
if (authManager.authenticateForm(realm, user, form))
|
if (authManager.authenticateForm(realm, user, form)) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Auth failed");
|
throw new NotAuthorizedException("Auth failed");
|
||||||
}
|
}
|
||||||
SkeletonKeyToken token = tokenManager.createAccessToken(realm, user);
|
SkeletonKeyToken token = tokenManager.createAccessToken(realm, user);
|
||||||
|
@ -200,69 +130,54 @@ public class TokenService
|
||||||
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{realm}/auth/request/login")
|
@Path("auth/request/login")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response login(@PathParam("realm") String realmId,
|
public Response login(MultivaluedMap<String, String> formData) {
|
||||||
MultivaluedMap<String, String> formData)
|
|
||||||
{
|
|
||||||
String clientId = formData.getFirst("client_id");
|
String clientId = formData.getFirst("client_id");
|
||||||
String scopeParam = formData.getFirst("scope");
|
String scopeParam = formData.getFirst("scope");
|
||||||
String state = formData.getFirst("state");
|
String state = formData.getFirst("state");
|
||||||
String redirect = formData.getFirst("redirect_uri");
|
String redirect = formData.getFirst("redirect_uri");
|
||||||
|
|
||||||
RealmModel realm = adapter.getRealm(realmId);
|
if (!realm.isEnabled()) {
|
||||||
if (realm == null)
|
|
||||||
{
|
|
||||||
throw new NotFoundException("Realm not found");
|
|
||||||
}
|
|
||||||
if (!realm.isEnabled())
|
|
||||||
{
|
|
||||||
return Response.ok("Realm not enabled").type("text/html").build();
|
return Response.ok("Realm not enabled").type("text/html").build();
|
||||||
}
|
}
|
||||||
User client = realm.getIdm().getUser(clientId);
|
User client = realm.getIdm().getUser(clientId);
|
||||||
if (client == null)
|
if (client == null) {
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("No client");
|
throw new NotAuthorizedException("No client");
|
||||||
}
|
}
|
||||||
if (!client.isEnabled())
|
if (!client.isEnabled()) {
|
||||||
{
|
|
||||||
return Response.ok("Requester not enabled").type("text/html").build();
|
return Response.ok("Requester not enabled").type("text/html").build();
|
||||||
}
|
}
|
||||||
String username = formData.getFirst("username");
|
String username = formData.getFirst("username");
|
||||||
User user = realm.getIdm().getUser(username);
|
User user = realm.getIdm().getUser(username);
|
||||||
if (user == null)
|
if (user == null) {
|
||||||
{
|
|
||||||
logger.debug("user not found");
|
logger.debug("user not found");
|
||||||
return loginForm("Not valid user", redirect, clientId, scopeParam, state, realm, client);
|
return loginForm("Not valid user", redirect, clientId, scopeParam, state, realm, client);
|
||||||
}
|
}
|
||||||
if (!user.isEnabled())
|
if (!user.isEnabled()) {
|
||||||
{
|
|
||||||
return Response.ok("Your account is not enabled").type("text/html").build();
|
return Response.ok("Your account is not enabled").type("text/html").build();
|
||||||
|
|
||||||
}
|
}
|
||||||
boolean authenticated = authManager.authenticateForm(realm, user, formData);
|
boolean authenticated = authManager.authenticateForm(realm, user, formData);
|
||||||
if (!authenticated) return loginForm("Unable to authenticate, try again", redirect, clientId, scopeParam, state, realm, client);
|
if (!authenticated)
|
||||||
|
return loginForm("Unable to authenticate, try again", redirect, clientId, scopeParam, state, realm, client);
|
||||||
|
|
||||||
SkeletonKeyToken token = null;
|
SkeletonKeyToken token = null;
|
||||||
if (scopeParam != null) token = tokenManager.createScopedToken(scopeParam, realm, client, user);
|
if (scopeParam != null) token = tokenManager.createScopedToken(scopeParam, realm, client, user);
|
||||||
else token = tokenManager.createLoginToken(realm, client, user);
|
else token = tokenManager.createLoginToken(realm, client, user);
|
||||||
|
|
||||||
AccessCode code = new AccessCode();
|
AccessCodeEntry code = new AccessCodeEntry();
|
||||||
code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
|
code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
|
||||||
code.setToken(token);
|
code.setToken(token);
|
||||||
code.setClient(client);
|
code.setClient(client);
|
||||||
synchronized (accessCodeMap)
|
synchronized (accessCodeMap) {
|
||||||
{
|
|
||||||
accessCodeMap.put(code.getId(), code);
|
accessCodeMap.put(code.getId(), code);
|
||||||
}
|
}
|
||||||
String accessCode = null;
|
String accessCode = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realm.getPrivateKey());
|
accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realm.getPrivateKey());
|
||||||
}
|
} catch (UnsupportedEncodingException e) {
|
||||||
catch (UnsupportedEncodingException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam("code", accessCode);
|
UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam("code", accessCode);
|
||||||
|
@ -270,25 +185,16 @@ public class TokenService
|
||||||
return Response.status(302).location(redirectUri.build()).build();
|
return Response.status(302).location(redirectUri.build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{realm}/access/codes")
|
@Path("access/codes")
|
||||||
@POST
|
@POST
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public Response accessRequest(@PathParam("realm") String realmId,
|
public Response accessRequest(MultivaluedMap<String, String> formData) {
|
||||||
MultivaluedMap<String, String> formData)
|
if (!realm.isEnabled()) {
|
||||||
{
|
|
||||||
RealmModel realm = adapter.getRealm(realmId);
|
|
||||||
if (realm == null)
|
|
||||||
{
|
|
||||||
throw new NotFoundException("Realm not found");
|
|
||||||
}
|
|
||||||
if (!realm.isEnabled())
|
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Realm not enabled");
|
throw new NotAuthorizedException("Realm not enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
String code = formData.getFirst("code");
|
String code = formData.getFirst("code");
|
||||||
if (code == null)
|
if (code == null) {
|
||||||
{
|
|
||||||
logger.debug("code not specified");
|
logger.debug("code not specified");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_request");
|
error.put("error", "invalid_request");
|
||||||
|
@ -297,8 +203,7 @@ public class TokenService
|
||||||
|
|
||||||
}
|
}
|
||||||
String client_id = formData.getFirst("client_id");
|
String client_id = formData.getFirst("client_id");
|
||||||
if (client_id == null)
|
if (client_id == null) {
|
||||||
{
|
|
||||||
logger.debug("client_id not specified");
|
logger.debug("client_id not specified");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_request");
|
error.put("error", "invalid_request");
|
||||||
|
@ -306,8 +211,7 @@ public class TokenService
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
}
|
}
|
||||||
User client = realm.getIdm().getUser(client_id);
|
User client = realm.getIdm().getUser(client_id);
|
||||||
if (client == null)
|
if (client == null) {
|
||||||
{
|
|
||||||
logger.debug("Could not find user");
|
logger.debug("Could not find user");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_client");
|
error.put("error", "invalid_client");
|
||||||
|
@ -315,8 +219,7 @@ public class TokenService
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!client.isEnabled())
|
if (!client.isEnabled()) {
|
||||||
{
|
|
||||||
logger.debug("user is not enabled");
|
logger.debug("user is not enabled");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_client");
|
error.put("error", "invalid_client");
|
||||||
|
@ -325,61 +228,50 @@ public class TokenService
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean authenticated = authManager.authenticateForm(realm, client, formData);
|
boolean authenticated = authManager.authenticateForm(realm, client, formData);
|
||||||
if (!authenticated)
|
if (!authenticated) {
|
||||||
{
|
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "unauthorized_client");
|
error.put("error", "unauthorized_client");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
JWSInput input = new JWSInput(code, providers);
|
JWSInput input = new JWSInput(code, providers);
|
||||||
boolean verifiedCode = false;
|
boolean verifiedCode = false;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||||
}
|
} catch (Exception ignored) {
|
||||||
catch (Exception ignored)
|
|
||||||
{
|
|
||||||
logger.debug("Failed to verify signature", ignored);
|
logger.debug("Failed to verify signature", ignored);
|
||||||
}
|
}
|
||||||
if (!verifiedCode)
|
if (!verifiedCode) {
|
||||||
{
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
res.put("error", "invalid_grant");
|
res.put("error", "invalid_grant");
|
||||||
res.put("error_description", "Unable to verify code signature");
|
res.put("error_description", "Unable to verify code signature");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
||||||
}
|
}
|
||||||
String key = input.readContent(String.class);
|
String key = input.readContent(String.class);
|
||||||
AccessCode accessCode = null;
|
AccessCodeEntry accessCode = null;
|
||||||
synchronized (accessCodeMap)
|
synchronized (accessCodeMap) {
|
||||||
{
|
|
||||||
accessCode = accessCodeMap.remove(key);
|
accessCode = accessCodeMap.remove(key);
|
||||||
}
|
}
|
||||||
if (accessCode == null)
|
if (accessCode == null) {
|
||||||
{
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
res.put("error", "invalid_grant");
|
res.put("error", "invalid_grant");
|
||||||
res.put("error_description", "Code not found");
|
res.put("error_description", "Code not found");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
||||||
}
|
}
|
||||||
if (accessCode.isExpired())
|
if (accessCode.isExpired()) {
|
||||||
{
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
res.put("error", "invalid_grant");
|
res.put("error", "invalid_grant");
|
||||||
res.put("error_description", "Code is expired");
|
res.put("error_description", "Code is expired");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
||||||
}
|
}
|
||||||
if (!accessCode.getToken().isActive())
|
if (!accessCode.getToken().isActive()) {
|
||||||
{
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
res.put("error", "invalid_grant");
|
res.put("error", "invalid_grant");
|
||||||
res.put("error_description", "Token expired");
|
res.put("error_description", "Token expired");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
|
||||||
}
|
}
|
||||||
if (!client.getId().equals(accessCode.getClient().getId()))
|
if (!client.getId().equals(accessCode.getClient().getId())) {
|
||||||
{
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
res.put("error", "invalid_grant");
|
res.put("error", "invalid_grant");
|
||||||
res.put("error_description", "Auth error");
|
res.put("error_description", "Auth error");
|
||||||
|
@ -390,15 +282,11 @@ public class TokenService
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token)
|
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
|
||||||
{
|
|
||||||
byte[] tokenBytes = null;
|
byte[] tokenBytes = null;
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
tokenBytes = JsonSerialization.toByteArray(token, false);
|
tokenBytes = JsonSerialization.toByteArray(token, false);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
String encodedToken = new JWSBuilder()
|
String encodedToken = new JWSBuilder()
|
||||||
|
@ -408,35 +296,25 @@ public class TokenService
|
||||||
return accessTokenResponse(token, encodedToken);
|
return accessTokenResponse(token, encodedToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AccessTokenResponse accessTokenResponse(SkeletonKeyToken token, String encodedToken)
|
protected AccessTokenResponse accessTokenResponse(SkeletonKeyToken token, String encodedToken) {
|
||||||
{
|
|
||||||
AccessTokenResponse res = new AccessTokenResponse();
|
AccessTokenResponse res = new AccessTokenResponse();
|
||||||
res.setToken(encodedToken);
|
res.setToken(encodedToken);
|
||||||
res.setTokenType("bearer");
|
res.setTokenType("bearer");
|
||||||
if (token.getExpiration() != 0)
|
if (token.getExpiration() != 0) {
|
||||||
{
|
|
||||||
long time = token.getExpiration() - (System.currentTimeMillis() / 1000);
|
long time = token.getExpiration() - (System.currentTimeMillis() / 1000);
|
||||||
res.setExpiresIn(time);
|
res.setExpiresIn(time);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{realm}/auth/request")
|
@Path("auth/request")
|
||||||
@GET
|
@GET
|
||||||
public Response requestAccessCode(@PathParam("realm") String realmId,
|
public Response requestAccessCode(@QueryParam("response_type") String responseType,
|
||||||
@QueryParam("response_type") String responseType,
|
|
||||||
@QueryParam("redirect_uri") String redirect,
|
@QueryParam("redirect_uri") String redirect,
|
||||||
@QueryParam("client_id") String clientId,
|
@QueryParam("client_id") String clientId,
|
||||||
@QueryParam("scope") String scopeParam,
|
@QueryParam("scope") String scopeParam,
|
||||||
@QueryParam("state") String state)
|
@QueryParam("state") String state) {
|
||||||
{
|
if (!realm.isEnabled()) {
|
||||||
RealmModel realm = adapter.getRealm(realmId);
|
|
||||||
if (realm == null)
|
|
||||||
{
|
|
||||||
throw new NotFoundException("Realm not found");
|
|
||||||
}
|
|
||||||
if (!realm.isEnabled())
|
|
||||||
{
|
|
||||||
throw new NotAuthorizedException("Realm not enabled");
|
throw new NotAuthorizedException("Realm not enabled");
|
||||||
}
|
}
|
||||||
User client = realm.getIdm().getUser(clientId);
|
User client = realm.getIdm().getUser(clientId);
|
||||||
|
@ -446,20 +324,14 @@ public class TokenService
|
||||||
return loginForm(null, redirect, clientId, scopeParam, state, realm, client);
|
return loginForm(null, redirect, clientId, scopeParam, state, realm, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response loginForm(String validationError, String redirect, String clientId, String scopeParam, String state, RealmModel realm, User client)
|
private Response loginForm(String validationError, String redirect, String clientId, String scopeParam, String state, RealmModel realm, User client) {
|
||||||
{
|
|
||||||
StringBuffer html = new StringBuffer();
|
StringBuffer html = new StringBuffer();
|
||||||
if (scopeParam != null)
|
if (scopeParam != null) {
|
||||||
{
|
|
||||||
html.append("<h1>Grant Request For ").append(realm.getName()).append(" Realm</h1>");
|
html.append("<h1>Grant Request For ").append(realm.getName()).append(" Realm</h1>");
|
||||||
if (validationError != null)
|
if (validationError != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(1000); // put in a delay
|
Thread.sleep(1000); // put in a delay
|
||||||
}
|
} catch (InterruptedException e) {
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
html.append("<p/><p><b>").append(validationError).append("</b></p>");
|
html.append("<p/><p><b>").append(validationError).append("</b></p>");
|
||||||
|
@ -469,53 +341,37 @@ public class TokenService
|
||||||
SkeletonKeyScope scope = tokenManager.decodeScope(scopeParam);
|
SkeletonKeyScope scope = tokenManager.decodeScope(scopeParam);
|
||||||
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
|
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
|
||||||
|
|
||||||
for (String res : scope.keySet())
|
for (String res : scope.keySet()) {
|
||||||
{
|
|
||||||
ResourceModel resource = resourceMap.get(res);
|
ResourceModel resource = resourceMap.get(res);
|
||||||
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
|
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
|
||||||
Set<String> scopeMapping = resource.getScope(client);
|
Set<String> scopeMapping = resource.getScope(client);
|
||||||
for (String role : scope.get(res))
|
for (String role : scope.get(res)) {
|
||||||
{
|
|
||||||
html.append(" ").append(role);
|
html.append(" ").append(role);
|
||||||
if (!scopeMapping.contains("*") && !scopeMapping.contains(role))
|
if (!scopeMapping.contains("*") && !scopeMapping.contains(role)) {
|
||||||
{
|
|
||||||
return Response.ok("<h1>Security Alert</h1><p>Known client not authorized for the requested scope.</p>").type("text/html").build();
|
return Response.ok("<h1>Security Alert</h1><p>Known client not authorized for the requested scope.</p>").type("text/html").build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html.append("</td></tr>");
|
html.append("</td></tr>");
|
||||||
}
|
}
|
||||||
html.append("</table><p>To Authorize, please login below</p>");
|
html.append("</table><p>To Authorize, please login below</p>");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
Set<String> scopeMapping = realm.getScope(client);
|
Set<String> scopeMapping = realm.getScope(client);
|
||||||
if (scopeMapping.contains("*"))
|
if (scopeMapping.contains("*")) {
|
||||||
{
|
|
||||||
html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>");
|
html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>");
|
||||||
if (validationError != null)
|
if (validationError != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(1000); // put in a delay
|
Thread.sleep(1000); // put in a delay
|
||||||
}
|
} catch (InterruptedException e) {
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
html.append("<p/><p><b>").append(validationError).append("</b></p>");
|
html.append("<p/><p><b>").append(validationError).append("</b></p>");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
html.append("<h1>Grant Request For ").append(realm.getName()).append(" Realm</h1>");
|
html.append("<h1>Grant Request For ").append(realm.getName()).append(" Realm</h1>");
|
||||||
if (validationError != null)
|
if (validationError != null) {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
Thread.sleep(1000); // put in a delay
|
Thread.sleep(1000); // put in a delay
|
||||||
}
|
} catch (InterruptedException e) {
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
html.append("<p/><p><b>").append(validationError).append("</b></p>");
|
html.append("<p/><p><b>").append(validationError).append("</b></p>");
|
||||||
|
@ -523,37 +379,30 @@ public class TokenService
|
||||||
SkeletonKeyScope scope = new SkeletonKeyScope();
|
SkeletonKeyScope scope = new SkeletonKeyScope();
|
||||||
List<ResourceModel> resources = realm.getResources();
|
List<ResourceModel> resources = realm.getResources();
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (ResourceModel resource : resources)
|
for (ResourceModel resource : resources) {
|
||||||
{
|
|
||||||
Set<String> resourceScope = resource.getScope(client);
|
Set<String> resourceScope = resource.getScope(client);
|
||||||
if (resourceScope == null) continue;
|
if (resourceScope == null) continue;
|
||||||
if (resourceScope.size() == 0) continue;
|
if (resourceScope.size() == 0) continue;
|
||||||
if (!found)
|
if (!found) {
|
||||||
{
|
|
||||||
found = true;
|
found = true;
|
||||||
html.append("<p>A Third Party is requesting access to the following resources</p>");
|
html.append("<p>A Third Party is requesting access to the following resources</p>");
|
||||||
html.append("<table>");
|
html.append("<table>");
|
||||||
}
|
}
|
||||||
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
|
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
|
||||||
// todo add description of role
|
// todo add description of role
|
||||||
for (String role : resourceScope)
|
for (String role : resourceScope) {
|
||||||
{
|
|
||||||
html.append(" ").append(role);
|
html.append(" ").append(role);
|
||||||
scope.add(resource.getName(), role);
|
scope.add(resource.getName(), role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found) {
|
||||||
{
|
|
||||||
return Response.ok("<h1>Security Alert</h1><p>Known client not authorized to access this realm.</p>").type("text/html").build();
|
return Response.ok("<h1>Security Alert</h1><p>Known client not authorized to access this realm.</p>").type("text/html").build();
|
||||||
}
|
}
|
||||||
html.append("</table>");
|
html.append("</table>");
|
||||||
try
|
try {
|
||||||
{
|
|
||||||
String json = JsonSerialization.toString(scope, false);
|
String json = JsonSerialization.toString(scope, false);
|
||||||
scopeParam = Base64Url.encode(json.getBytes("UTF-8"));
|
scopeParam = Base64Url.encode(json.getBytes("UTF-8"));
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,22 +414,18 @@ public class TokenService
|
||||||
html.append("<form action=\"").append(action).append("\" method=\"POST\">");
|
html.append("<form action=\"").append(action).append("\" method=\"POST\">");
|
||||||
html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>");
|
html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>");
|
||||||
|
|
||||||
for (RequiredCredentialModel credential : realm.getRequiredCredentials())
|
for (RequiredCredentialModel credential : realm.getRequiredCredentials()) {
|
||||||
{
|
|
||||||
if (!credential.isInput()) continue;
|
if (!credential.isInput()) continue;
|
||||||
html.append(credential.getType()).append(": ");
|
html.append(credential.getType()).append(": ");
|
||||||
if (credential.isSecret())
|
if (credential.isSecret()) {
|
||||||
{
|
|
||||||
html.append("<input type=\"password\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>");
|
html.append("<input type=\"password\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>");
|
||||||
|
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
html.append("<input type=\"text\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>");
|
html.append("<input type=\"text\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
html.append("<input type=\"hidden\" name=\"client_id\" value=\"").append(clientId).append("\">");
|
html.append("<input type=\"hidden\" name=\"client_id\" value=\"").append(clientId).append("\">");
|
||||||
if (scopeParam != null)
|
if (scopeParam != null) {
|
||||||
{
|
|
||||||
html.append("<input type=\"hidden\" name=\"scope\" value=\"").append(scopeParam).append("\">");
|
html.append("<input type=\"hidden\" name=\"scope\" value=\"").append(scopeParam).append("\">");
|
||||||
}
|
}
|
||||||
if (state != null) html.append("<input type=\"hidden\" name=\"state\" value=\"").append(state).append("\">");
|
if (state != null) html.append("<input type=\"hidden\" name=\"state\" value=\"").append(state).append("\">");
|
||||||
|
|
|
@ -7,27 +7,23 @@ import org.junit.FixMethodOrder;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runners.MethodSorters;
|
import org.junit.runners.MethodSorters;
|
||||||
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||||
|
import org.keycloak.services.managers.InstallationManager;
|
||||||
import org.keycloak.services.models.RealmManager;
|
import org.keycloak.services.models.RealmManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.relationships.RealmResourceRelationship;
|
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
import org.keycloak.services.models.RequiredCredentialModel;
|
||||||
import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
|
|
||||||
import org.keycloak.services.models.relationships.ScopeRelationship;
|
|
||||||
import org.keycloak.services.models.UserCredentialModel;
|
import org.keycloak.services.models.UserCredentialModel;
|
||||||
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
|
import org.picketlink.idm.IdentitySessionFactory;
|
||||||
import org.picketlink.idm.IdentityManager;
|
import org.picketlink.idm.IdentityManager;
|
||||||
import org.picketlink.idm.config.IdentityConfigurationBuilder;
|
|
||||||
import org.picketlink.idm.credential.Credentials;
|
import org.picketlink.idm.credential.Credentials;
|
||||||
import org.picketlink.idm.credential.Password;
|
import org.picketlink.idm.credential.Password;
|
||||||
import org.picketlink.idm.credential.UsernamePasswordCredentials;
|
import org.picketlink.idm.credential.UsernamePasswordCredentials;
|
||||||
import org.picketlink.idm.file.internal.FileUtils;
|
|
||||||
import org.picketlink.idm.internal.IdentityManagerFactory;
|
|
||||||
import org.picketlink.idm.model.Realm;
|
|
||||||
import org.picketlink.idm.model.Role;
|
import org.picketlink.idm.model.Role;
|
||||||
import org.picketlink.idm.model.SimpleRole;
|
import org.picketlink.idm.model.SimpleRole;
|
||||||
import org.picketlink.idm.model.SimpleUser;
|
import org.picketlink.idm.model.SimpleUser;
|
||||||
import org.picketlink.idm.model.User;
|
import org.picketlink.idm.model.User;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,47 +31,34 @@ import java.util.List;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
public class AdapterTest
|
public class AdapterTest {
|
||||||
{
|
private IdentitySessionFactory factory;
|
||||||
private static IdentityManagerFactory factory;
|
private IdentitySession IdentitySession;
|
||||||
public static final String WORKING_DIRECTORY = "/tmp/keycloak";
|
private RealmManager adapter;
|
||||||
public RealmManager adapter;
|
private RealmModel realmModel;
|
||||||
public RealmModel realmModel;
|
|
||||||
@Before
|
@Before
|
||||||
public void before() throws Exception
|
public void before() throws Exception {
|
||||||
{
|
factory = KeycloakApplication.createFactory();
|
||||||
after();
|
IdentitySession = factory.createIdentitySession();
|
||||||
factory = createFactory();
|
adapter = new RealmManager(IdentitySession);
|
||||||
adapter = new RealmManager(factory);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IdentityManagerFactory createFactory() {
|
|
||||||
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
|
|
||||||
|
|
||||||
builder
|
|
||||||
.stores()
|
|
||||||
.file()
|
|
||||||
.addRealm(Realm.DEFAULT_REALM)
|
|
||||||
.workingDirectory(WORKING_DIRECTORY)
|
|
||||||
.preserveState(true)
|
|
||||||
.supportAllFeatures()
|
|
||||||
.supportRelationshipType(RealmResourceRelationship.class, RequiredCredentialRelationship.class, ScopeRelationship.class);
|
|
||||||
|
|
||||||
return new IdentityManagerFactory(builder.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after() throws Exception
|
public void after() throws Exception {
|
||||||
{
|
IdentitySession.close();
|
||||||
File file = new File(WORKING_DIRECTORY);
|
factory.close();
|
||||||
FileUtils.delete(file);
|
|
||||||
Thread.sleep(10); // my windows machine seems to have delays on deleting files sometimes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test1CreateRealm() throws Exception
|
public void installTest() throws Exception {
|
||||||
{
|
new InstallationManager().install(adapter);
|
||||||
realmModel = adapter.create("JUGGLER");
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test1CreateRealm() throws Exception {
|
||||||
|
realmModel = adapter.createRealm("JUGGLER");
|
||||||
realmModel.setAccessCodeLifespan(100);
|
realmModel.setAccessCodeLifespan(100);
|
||||||
realmModel.setCookieLoginAllowed(true);
|
realmModel.setCookieLoginAllowed(true);
|
||||||
realmModel.setEnabled(true);
|
realmModel.setEnabled(true);
|
||||||
|
@ -97,8 +80,7 @@ public class AdapterTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test2RequiredCredential() throws Exception
|
public void test2RequiredCredential() throws Exception {
|
||||||
{
|
|
||||||
test1CreateRealm();
|
test1CreateRealm();
|
||||||
RequiredCredentialModel creds = new RequiredCredentialModel();
|
RequiredCredentialModel creds = new RequiredCredentialModel();
|
||||||
creds.setSecret(true);
|
creds.setSecret(true);
|
||||||
|
@ -114,8 +96,7 @@ public class AdapterTest
|
||||||
Assert.assertEquals(2, storedCreds.size());
|
Assert.assertEquals(2, storedCreds.size());
|
||||||
boolean totp = false;
|
boolean totp = false;
|
||||||
boolean password = false;
|
boolean password = false;
|
||||||
for (RequiredCredentialModel cred : storedCreds)
|
for (RequiredCredentialModel cred : storedCreds) {
|
||||||
{
|
|
||||||
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) password = true;
|
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) password = true;
|
||||||
else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) totp = true;
|
else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) totp = true;
|
||||||
}
|
}
|
||||||
|
@ -124,8 +105,7 @@ public class AdapterTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCredentialValidation() throws Exception
|
public void testCredentialValidation() throws Exception {
|
||||||
{
|
|
||||||
test1CreateRealm();
|
test1CreateRealm();
|
||||||
User user = new SimpleUser("bburke");
|
User user = new SimpleUser("bburke");
|
||||||
realmModel.getIdm().add(user);
|
realmModel.getIdm().add(user);
|
||||||
|
@ -140,8 +120,7 @@ public class AdapterTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRoles() throws Exception
|
public void testRoles() throws Exception {
|
||||||
{
|
|
||||||
test1CreateRealm();
|
test1CreateRealm();
|
||||||
IdentityManager idm = realmModel.getIdm();
|
IdentityManager idm = realmModel.getIdm();
|
||||||
idm.add(new SimpleRole("admin"));
|
idm.add(new SimpleRole("admin"));
|
||||||
|
|
31
services/src/test/java/org/keycloak/test/KeycloakTestBase.java
Executable file
31
services/src/test/java/org/keycloak/test/KeycloakTestBase.java
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
package org.keycloak.test;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
|
import org.jboss.resteasy.test.BaseResourceTest;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class KeycloakTestBase extends BaseResourceTest
|
||||||
|
{
|
||||||
|
public static RealmRepresentation loadJson(String path) throws IOException
|
||||||
|
{
|
||||||
|
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
int c;
|
||||||
|
while ( (c = is.read()) != -1)
|
||||||
|
{
|
||||||
|
os.write(c);
|
||||||
|
}
|
||||||
|
byte[] bytes = os.toByteArray();
|
||||||
|
System.out.println(new String(bytes));
|
||||||
|
|
||||||
|
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
|
||||||
|
}
|
||||||
|
}
|
94
services/src/test/java/org/keycloak/test/RealmCreationTest.java
Executable file
94
services/src/test/java/org/keycloak/test/RealmCreationTest.java
Executable file
|
@ -0,0 +1,94 @@
|
||||||
|
package org.keycloak.test;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||||
|
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||||
|
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||||
|
import org.jboss.resteasy.test.EmbeddedContainer;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.SkeletonKeyContextResolver;
|
||||||
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
|
import org.keycloak.services.managers.InstallationManager;
|
||||||
|
import org.keycloak.services.models.RealmManager;
|
||||||
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
|
import org.picketlink.idm.IdentitySession;
|
||||||
|
import org.picketlink.idm.model.Realm;
|
||||||
|
|
||||||
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
|
import javax.ws.rs.client.Client;
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
|
import javax.ws.rs.client.WebTarget;
|
||||||
|
import javax.ws.rs.core.Form;
|
||||||
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import static org.jboss.resteasy.test.TestPortProvider.generateURL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class RealmCreationTest {
|
||||||
|
|
||||||
|
private static ResteasyDeployment deployment;
|
||||||
|
private static Client client;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void before() throws Exception {
|
||||||
|
deployment = new ResteasyDeployment();
|
||||||
|
deployment.setApplicationClass(KeycloakApplication.class.getName());
|
||||||
|
EmbeddedContainer.start(deployment);
|
||||||
|
KeycloakApplication application = (KeycloakApplication) deployment.getApplication();
|
||||||
|
IdentitySession IdentitySession = application.getFactory().createIdentitySession();
|
||||||
|
RealmManager manager = new RealmManager(IdentitySession);
|
||||||
|
new InstallationManager().install(manager);
|
||||||
|
client = new ResteasyClientBuilder().build();
|
||||||
|
client.register(SkeletonKeyContextResolver.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void after() throws Exception {
|
||||||
|
client.close();
|
||||||
|
EmbeddedContainer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRegisterLoginAndCreate() throws Exception {
|
||||||
|
UserRepresentation user = new UserRepresentation();
|
||||||
|
user.setUsername("bburke");
|
||||||
|
user.credential(RequiredCredentialRepresentation.PASSWORD, "geheim", false);
|
||||||
|
|
||||||
|
WebTarget target = client.target(generateURL("/"));
|
||||||
|
Response response = target.path("registrations").request().post(Entity.json(user));
|
||||||
|
Assert.assertEquals(201, response.getStatus());
|
||||||
|
response.close();
|
||||||
|
|
||||||
|
|
||||||
|
AccessTokenResponse tokenResponse = null;
|
||||||
|
try {
|
||||||
|
Form form = new Form();
|
||||||
|
form.param(AuthenticationManager.FORM_USERNAME, "bburke");
|
||||||
|
form.param(RequiredCredentialRepresentation.PASSWORD, "badpassword");
|
||||||
|
tokenResponse = target.path("realms").path(Realm.DEFAULT_REALM).path("tokens/grants/identity-token").request().post(Entity.form(form), AccessTokenResponse.class);
|
||||||
|
Assert.fail();
|
||||||
|
} catch (NotAuthorizedException e) {
|
||||||
|
}
|
||||||
|
Form form = new Form();
|
||||||
|
form.param(AuthenticationManager.FORM_USERNAME, "bburke");
|
||||||
|
form.param(RequiredCredentialRepresentation.PASSWORD, "geheim");
|
||||||
|
tokenResponse = target.path("realms").path(Realm.DEFAULT_REALM).path("tokens/grants/identity-token").request().post(Entity.form(form), AccessTokenResponse.class);
|
||||||
|
Assert.assertNotNull(tokenResponse);
|
||||||
|
System.out.println(tokenResponse.getToken());
|
||||||
|
//
|
||||||
|
|
||||||
|
RealmRepresentation realm = KeycloakTestBase.loadJson("testrealm.json");
|
||||||
|
response = target.path("realms").request().header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenResponse.getToken()).post(Entity.json(realm));
|
||||||
|
Assert.assertEquals(201, response.getStatus());
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
||||||
version="1.0">
|
version="1.0">
|
||||||
<persistence-unit name="identitydb" transaction-type="RESOURCE_LOCAL">
|
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
|
||||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||||
|
|
||||||
<class>org.picketlink.idm.jpa.schema.IdentityObject</class>
|
<class>org.picketlink.idm.jpa.schema.IdentityObject</class>
|
||||||
|
|
Loading…
Reference in a new issue