more stuff

This commit is contained in:
Bill Burke 2013-07-11 17:56:15 -04:00
parent 1586f461be
commit 1548065b7f
30 changed files with 2118 additions and 2123 deletions

View file

@ -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;
} }
} }

11
pom.xml
View file

@ -108,6 +108,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 +169,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>

View file

@ -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>

View file

@ -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();
}
}

View 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;
}
}

View file

@ -24,107 +24,91 @@ 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");
{ } else {
throw new NotAuthorizedException("Bearer"); String[] split = authHeader.trim().split("\\s+");
} if (split == null || split.length != 2) throw new NotAuthorizedException("Bearer");
else if (!split[0].equalsIgnoreCase("Bearer")) throw new NotAuthorizedException("Bearer");
{ tokenString = split[1];
String[] split = authHeader.trim().split("\\s+"); }
if (split == null || split.length != 2) throw new NotAuthorizedException("Bearer");
if (!split[0].equalsIgnoreCase("Bearer")) throw new NotAuthorizedException("Bearer");
tokenString = split[1];
}
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());
} if (user == null || !user.isEnabled()) {
User user = realm.getIdm().getUser(token.getPrincipal()); throw new NotAuthorizedException("invalid_user");
if (user == null || !user.isEnabled()) }
{ return user;
throw new NotAuthorizedException("invalid_user"); } catch (VerificationException e) {
} logger.error("Failed to verify token", e);
return user; throw new NotAuthorizedException("invalid_token");
} }
catch (VerificationException e) }
{
logger.error("Failed to verify token", e);
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");
{ return false;
logger.warn("Password not provided"); }
if (types.contains(RequiredCredentialRepresentation.TOTP)) {
String token = formData.getFirst(RequiredCredentialRepresentation.TOTP);
if (token == null) {
logger.warn("TOTP token not provided");
return false;
}
TOTPCredentials creds = new TOTPCredentials();
creds.setToken(token);
creds.setUsername(username);
creds.setPassword(new Password(password));
realm.getIdm().validateCredentials(creds);
if (creds.getStatus() != Credentials.Status.VALID) {
return false;
}
} else {
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, new Password(password));
realm.getIdm().validateCredentials(creds);
if (creds.getStatus() != Credentials.Status.VALID) {
return false;
}
}
} else {
logger.warn("Do not know how to authenticate user");
return false; return false;
} }
return true;
if (types.contains(RequiredCredentialRepresentation.TOTP)) }
{
String token = formData.getFirst(RequiredCredentialRepresentation.TOTP);
if (token == null)
{
logger.warn("TOTP token not provided");
return false;
}
TOTPCredentials creds = new TOTPCredentials();
creds.setToken(token);
creds.setUsername(username);
creds.setPassword(new Password(password));
realm.getIdm().validateCredentials(creds);
if (creds.getStatus() != Credentials.Status.VALID)
{
return false;
}
}
else
{
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(username, new Password(password));
realm.getIdm().validateCredentials(creds);
if (creds.getStatus() != Credentials.Status.VALID)
{
return false;
}
}
}
else
{
logger.warn("Do not know how to authenticate user");
return false;
}
return true;
}
} }

View file

@ -0,0 +1,29 @@
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);
manager.generateRealmKeys(defaultRealm);
defaultRealm.updateRealm();
defaultRealm.addRequiredCredential(RequiredCredentialModel.PASSWORD);
defaultRealm.getIdm().add(new SimpleRole(RegistrationService.REALM_CREATOR_ROLE));
}
}

View file

@ -21,156 +21,123 @@ 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) {
{ SkeletonKeyToken token = new SkeletonKeyToken();
this.adapter = adapter; token.id(RealmManager.generateId());
} token.principal(user.getLoginName());
token.audience(realm.getName());
token.issuedNow();
token.issuedFor(client.getLoginName());
if (realm.getTokenLifespan() > 0) {
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
}
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
public SkeletonKeyToken createScopedToken(SkeletonKeyScope scope, RealmModel realm, User client, User user) for (String res : scope.keySet()) {
{ ResourceModel resource = resourceMap.get(res);
SkeletonKeyToken token = new SkeletonKeyToken(); Set<String> scopeMapping = resource.getScope(client);
token.id(adapter.generateId()); Set<String> roleMapping = resource.getRoleMappings(user);
token.principal(user.getLoginName()); SkeletonKeyToken.Access access = token.addAccess(resource.getName());
token.audience(realm.getName()); for (String role : scope.get(res)) {
token.issuedNow(); if (!scopeMapping.contains("*") && !scopeMapping.contains(role)) {
token.issuedFor(client.getLoginName()); 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 (realm.getTokenLifespan() > 0) }
{ if (!roleMapping.contains(role)) {
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan()); 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());
}
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
for (String res : scope.keySet()) }
{ access.addRole(role);
ResourceModel resource = resourceMap.get(res);
Set<String> scopeMapping = resource.getScope(client);
Set<String> roleMapping = resource.getRoleMappings(user);
SkeletonKeyToken.Access access = token.addAccess(resource.getName());
for (String role : scope.get(res))
{
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());
} }
if (!roleMapping.contains(role)) }
{ return token;
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()); }
public SkeletonKeyToken createScopedToken(String scopeParam, RealmModel realm, User client, User user) {
SkeletonKeyScope scope = decodeScope(scopeParam);
return createScopedToken(scope, realm, client, user);
}
public SkeletonKeyToken createLoginToken(RealmModel realm, User client, User user) {
Set<String> mapping = realm.getScope(client);
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());
}
SkeletonKeyToken token = createAccessToken(realm, user);
token.issuedFor(client.getLoginName());
return token;
}
public SkeletonKeyScope decodeScope(String scopeParam) {
SkeletonKeyScope scope = null;
byte[] bytes = Base64Url.decode(scopeParam);
try {
scope = JsonSerialization.fromBytes(SkeletonKeyScope.class, bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
return scope;
}
public SkeletonKeyToken createAccessToken(RealmModel realm, User user) {
List<ResourceModel> resources = realm.getResources();
SkeletonKeyToken token = new SkeletonKeyToken();
token.id(RealmManager.generateId());
token.issuedNow();
token.principal(user.getLoginName());
token.audience(realm.getId());
if (realm.getTokenLifespan() > 0) {
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
}
Set<String> realmMapping = realm.getRoleMappings(user);
if (realmMapping != null && realmMapping.size() > 0) {
SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
for (String role : realmMapping) {
access.addRole(role);
} }
access.addRole(role); token.setRealmAccess(access);
} }
} if (resources != null) {
return token; for (ResourceModel resource : resources) {
} Set<String> mapping = resource.getRoleMappings(user);
if (mapping == null) continue;
public SkeletonKeyToken createScopedToken(String scopeParam, RealmModel realm, User client, User user) SkeletonKeyToken.Access access = token.addAccess(resource.getName())
{ .verifyCaller(resource.isSurrogateAuthRequired());
SkeletonKeyScope scope = decodeScope(scopeParam); for (String role : mapping) {
return createScopedToken(scope, realm, client, user); access.addRole(role);
} }
public SkeletonKeyToken createLoginToken(RealmModel realm, User client, User user)
{
Set<String> mapping = realm.getScope(client);
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());
}
SkeletonKeyToken token = createAccessToken(realm, user);
token.issuedFor(client.getLoginName());
return token;
}
public SkeletonKeyScope decodeScope(String scopeParam)
{
SkeletonKeyScope scope = null;
byte[] bytes = Base64Url.decode(scopeParam);
try
{
scope = JsonSerialization.fromBytes(SkeletonKeyScope.class, bytes);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
return scope;
}
public SkeletonKeyToken createAccessToken(RealmModel realm, User user)
{
List<ResourceModel> resources = realm.getResources();
SkeletonKeyToken token = new SkeletonKeyToken();
token.id(adapter.generateId());
token.issuedNow();
token.principal(user.getLoginName());
token.audience(realm.getId());
if (realm.getTokenLifespan() > 0)
{
token.expiration((System.currentTimeMillis() / 1000) + realm.getTokenLifespan());
}
Set<String> realmMapping = realm.getRoleMappings(user);
if (realmMapping != null && realmMapping.size() > 0)
{
SkeletonKeyToken.Access access = new SkeletonKeyToken.Access();
for (String role : realmMapping)
{
access.addRole(role);
}
token.setRealmAccess(access);
}
if (resources != null)
{
for (ResourceModel resource : resources)
{
Set<String> mapping = resource.getRoleMappings(user);
if (mapping == null) continue;
SkeletonKeyToken.Access access = token.addAccess(resource.getName())
.verifyCaller(resource.isSurrogateAuthRequired());
for (String role : mapping)
{
access.addRole(role);
} }
} }
} 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(RealmManager.generateId());
token.id(adapter.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);
{ } catch (Exception e) {
tokenBytes = JsonSerialization.toByteArray(token, false); throw new RuntimeException(e);
} }
catch (Exception e) String encodedToken = new JWSBuilder()
{ .content(tokenBytes)
throw new RuntimeException(e); .rsa256(realm.getPrivateKey());
} return encodedToken;
String encodedToken = new JWSBuilder() }
.content(tokenBytes)
.rsa256(realm.getPrivateKey());
return encodedToken;
}
} }

View file

@ -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)
{
return null;
}
return new RealmModel(existing, factory);
}
public RealmModel create(String name) public RealmModel getRealm(String id) {
{ Realm existing = IdentitySession.findRealm(id);
Realm newRealm = factory.createRealm(generateId()); if (existing == null) {
IdentityManager idm = factory.createIdentityManager(newRealm); return null;
SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID); }
idm.add(agent); return new RealmModel(existing, IdentitySession);
return new RealmModel(newRealm, factory); }
}
} public RealmModel createRealm(String name) {
return createRealm(generateId(), name);
}
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);
idm.add(agent);
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();
}
}

View file

@ -4,14 +4,14 @@ 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;
@ -39,374 +39,302 @@ 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"; public static final String REALM_TOKEN_LIFESPAN = "tokenLifespan";
public static final String REALM_TOKEN_LIFESPAN = "tokenLifespan"; public static final String REALM_PRIVATE_KEY = "privateKey";
public static final String REALM_PRIVATE_KEY = "privateKey"; 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";
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 factory) {
{ this.realm = realm;
this.realm = realm; this.IdentitySession = factory;
this.factory = factory; 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 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 {
{ publicKey = PemUtils.decodePublicKey(pem);
try } catch (Exception e) {
{ throw new RuntimeException(e);
publicKey = PemUtils.decodePublicKey(pem); }
} }
catch (Exception e) return publicKey;
{ }
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
StringWriter writer = new StringWriter();
PEMWriter pemWriter = new PEMWriter(writer);
try {
pemWriter.writeObject(publicKey);
pemWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} String s = writer.toString();
return publicKey; setPublicKeyPem(PemUtils.removeBeginEnd(s));
} }
public void setPublicKey(PublicKey publicKey) public PrivateKey getPrivateKey() {
{ if (privateKey != null) return privateKey;
this.publicKey = publicKey; String pem = getPrivateKeyPem();
StringWriter writer = new StringWriter(); if (pem != null) {
PEMWriter pemWriter = new PEMWriter(writer); try {
try privateKey = PemUtils.decodePrivateKey(pem);
{ } catch (Exception e) {
pemWriter.writeObject(publicKey); throw new RuntimeException(e);
pemWriter.flush(); }
} }
catch (IOException e) return privateKey;
{ }
throw new RuntimeException(e);
}
String s = writer.toString();
setPublicKeyPem(PemUtils.removeBeginEnd(s));
}
public PrivateKey getPrivateKey() public void setPrivateKey(PrivateKey privateKey) {
{ this.privateKey = privateKey;
if (privateKey != null) return privateKey; StringWriter writer = new StringWriter();
String pem = getPrivateKeyPem(); PEMWriter pemWriter = new PEMWriter(writer);
if (pem != null) try {
{ pemWriter.writeObject(privateKey);
try pemWriter.flush();
{ } catch (IOException e) {
privateKey = PemUtils.decodePrivateKey(pem);
}
catch (Exception e)
{
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} String s = writer.toString();
return privateKey; setPrivateKeyPem(PemUtils.removeBeginEnd(s));
} }
public void setPrivateKey(PrivateKey privateKey) public List<RequiredCredentialModel> getRequiredCredentials() {
{ IdentityManager idm = getIdm();
this.privateKey = privateKey; Agent realmAgent = idm.getAgent(REALM_AGENT_ID);
StringWriter writer = new StringWriter(); RelationshipQuery<RequiredCredentialRelationship> query = idm.createRelationshipQuery(RequiredCredentialRelationship.class);
PEMWriter pemWriter = new PEMWriter(writer); query.setParameter(RequiredCredentialRelationship.REALM_AGENT, realmAgent);
try List<RequiredCredentialRelationship> results = query.getResultList();
{ List<RequiredCredentialModel> rtn = new ArrayList<RequiredCredentialModel>();
pemWriter.writeObject(privateKey); for (RequiredCredentialRelationship relationship : results) {
pemWriter.flush(); RequiredCredentialModel model = new RequiredCredentialModel();
} model.setInput(relationship.isInput());
catch (IOException e) model.setSecret(relationship.isSecret());
{ model.setType(relationship.getCredentialType());
throw new RuntimeException(e); rtn.add(model);
} }
String s = writer.toString(); return rtn;
setPrivateKeyPem(PemUtils.removeBeginEnd(s)); }
}
public List<RequiredCredentialModel> getRequiredCredentials() 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();
RelationshipQuery<RequiredCredentialRelationship> query = idm.createRelationshipQuery(RequiredCredentialRelationship.class); relationship.setCredentialType(cred.getType());
query.setParameter(RequiredCredentialRelationship.REALM_AGENT, realmAgent); relationship.setInput(cred.isInput());
List<RequiredCredentialRelationship> results = query.getResultList(); relationship.setSecret(cred.isSecret());
List<RequiredCredentialModel> rtn = new ArrayList<RequiredCredentialModel>(); relationship.setRealmAgent(realmAgent);
for (RequiredCredentialRelationship relationship : results) idm.add(relationship);
{ }
RequiredCredentialModel model = new RequiredCredentialModel();
model.setInput(relationship.isInput());
model.setSecret(relationship.isSecret());
model.setType(relationship.getCredentialType());
rtn.add(model);
}
return rtn;
}
public void addRequiredCredential(RequiredCredentialModel cred) public void updateCredential(User user, UserCredentialModel cred) {
{ IdentityManager idm = getIdm();
IdentityManager idm = getIdm(); if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) {
Agent realmAgent = idm.getAgent(REALM_AGENT_ID); Password password = new Password(cred.getValue());
RequiredCredentialRelationship relationship = new RequiredCredentialRelationship(); idm.updateCredential(user, password);
relationship.setCredentialType(cred.getType()); } else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) {
relationship.setInput(cred.isInput()); TOTPCredential totp = new TOTPCredential(cred.getValue());
relationship.setSecret(cred.isSecret()); idm.updateCredential(user, totp);
relationship.setRealmAgent(realmAgent); } else if (cred.getType().equals(RequiredCredentialRepresentation.CLIENT_CERT)) {
idm.add(relationship); X509Certificate cert = null;
} try {
cert = org.keycloak.PemUtils.decodeCertificate(cred.getValue());
} catch (Exception e) {
throw new RuntimeException(e);
}
X509CertificateCredentials creds = new X509CertificateCredentials(cert);
idm.updateCredential(user, creds);
}
}
public void updateCredential(User user, UserCredentialModel cred) public List<Role> getRoles() {
{ IdentityManager idm = getIdm();
IdentityManager idm = getIdm(); IdentityQuery<Role> query = idm.createIdentityQuery(Role.class);
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) query.setParameter(Role.PARTITION, realm);
{ return query.getResultList();
Password password = new Password(cred.getValue()); }
idm.updateCredential(user, password);
}
else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP))
{
TOTPCredential totp = new TOTPCredential(cred.getValue());
idm.updateCredential(user, totp);
}
else if (cred.getType().equals(RequiredCredentialRepresentation.CLIENT_CERT))
{
X509Certificate cert = null;
try
{
cert = org.keycloak.PemUtils.decodeCertificate(cred.getValue());
}
catch (Exception e)
{
throw new RuntimeException(e);
}
X509CertificateCredentials creds = new X509CertificateCredentials(cert);
idm.updateCredential(user, creds);
}
}
public List<Role> getRoles()
{
IdentityManager idm = getIdm();
IdentityQuery<Role> query = idm.createIdentityQuery(Role.class);
query.setParameter(Role.PARTITION, realm);
return query.getResultList();
}
protected ResourceModel loadResource(Agent resource) /**
{ * Key name, value resource
Tier tier = factory.findTier(resource.getPartition().getId()); *
return new ResourceModel(tier, resource, this, factory); * @return
} */
public Map<String, ResourceModel> getResourceMap() {
Map<String, ResourceModel> resourceMap = new HashMap<String, ResourceModel>();
for (ResourceModel resource : getResources()) {
resourceMap.put(resource.getName(), resource);
}
return resourceMap;
}
/** public List<ResourceModel> getResources() {
* Key name, value resource IdentityManager idm = getIdm();
* RelationshipQuery<ResourceRelationship> query = idm.createRelationshipQuery(ResourceRelationship.class);
* @return query.setParameter(ResourceRelationship.REALM_AGENT, realmAgent);
*/ List<ResourceRelationship> results = query.getResultList();
public Map<String, ResourceModel> getResourceMap() List<ResourceModel> resources = new ArrayList<ResourceModel>();
{ for (ResourceRelationship relationship : results) {
Map<String, ResourceModel> resourceMap = new HashMap<String, ResourceModel>(); Tier resourceTier = IdentitySession.findTier(relationship.getResourceId());
for (ResourceModel resource : getResources()) ResourceModel model = new ResourceModel(resourceTier,relationship, this, IdentitySession);
{ resources.add(model);
resourceMap.put(resource.getName(), resource); }
}
return resourceMap;
}
public List<ResourceModel> getResources() return resources;
{ }
IdentityManager idm = getIdm();
RelationshipQuery<RealmResourceRelationship> query = idm.createRelationshipQuery(RealmResourceRelationship.class);
query.setParameter(RealmResourceRelationship.REALM_AGENT, realmAgent);
List<RealmResourceRelationship> results = query.getResultList();
List<ResourceModel> resources = new ArrayList<ResourceModel>();
for (RealmResourceRelationship relationship : results)
{
ResourceModel model = loadResource(relationship.getResourceAgent());
resources.add(model);
}
return resources; public ResourceModel addResource(String name) {
} Tier newTier = IdentitySession.createTier(RealmManager.generateId());
IdentityManager idm = getIdm();
ResourceRelationship relationship = new ResourceRelationship();
relationship.setResourceName(name);
relationship.setRealmAgent(realmAgent);
relationship.setResourceId(newTier.getId());
idm.add(relationship);
return new ResourceModel(newTier, relationship, this, IdentitySession);
}
public ResourceModel addResource(String name) public Set<String> getRoleMappings(User user) {
{ RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class);
Tier newTier = factory.createTier(RealmManager.generateId()); query.setParameter(Grant.ASSIGNEE, user);
IdentityManager idm = factory.createIdentityManager(newTier); List<Grant> grants = query.getResultList();
SimpleAgent resourceAgent = new SimpleAgent(ResourceModel.RESOURCE_AGENT_ID); HashSet<String> set = new HashSet<String>();
resourceAgent.setAttribute(new Attribute<String>(ResourceModel.RESOURCE_NAME, name)); for (Grant grant : grants) {
idm.add(resourceAgent); if (grant.getRole().getPartition().getId().equals(realm.getId())) set.add(grant.getRole().getName());
idm = getIdm(); }
RealmResourceRelationship relationship = new RealmResourceRelationship(); return set;
relationship.setRealmAgent(realmAgent); }
relationship.setResourceAgent(resourceAgent);
idm.add(relationship);
return new ResourceModel(newTier, resourceAgent, this, factory);
}
public Set<String> getRoleMappings(User user) public void addScope(Agent agent, String roleName) {
{ IdentityManager idm = getIdm();
RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class); Role role = idm.getRole(roleName);
query.setParameter(Grant.ASSIGNEE, user); if (role == null) throw new RuntimeException("role not found");
List<Grant> grants = query.getResultList(); ScopeRelationship scope = new ScopeRelationship();
HashSet<String> set = new HashSet<String>(); scope.setClient(agent);
for (Grant grant : grants) scope.setScope(role);
{
if (grant.getRole().getPartition().getId().equals(realm.getId()))set.add(grant.getRole().getName());
}
return set;
}
public void addScope(Agent agent, String roleName) }
{
IdentityManager idm = getIdm();
Role role = idm.getRole(roleName);
if (role == null) throw new RuntimeException("role not found");
ScopeRelationship scope = new ScopeRelationship();
scope.setClient(agent);
scope.setScope(role);
}
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.getId());
query.setParameter(RealmAdminRelationship.REALM, realm); 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.getId());
relationship.setRealm(realm); idm.add(relationship);
idm.add(relationship); }
}
} }

View file

@ -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() {
{ }
return type;
}
public void setType(String type) public RequiredCredentialModel(String type, boolean input, boolean secret) {
{ this.type = type;
this.type = type; this.input = input;
} this.secret = secret;
}
public boolean isInput() public String getType() {
{ return type;
return input; }
}
public void setInput(boolean input) public void setType(String type) {
{ this.type = type;
this.input = input; }
}
public boolean isSecret() public boolean isInput() {
{ return input;
return secret; }
}
public void setSecret(boolean secret) public void setInput(boolean input) {
{ this.input = input;
this.secret = secret; }
}
public boolean isSecret() {
return secret;
}
public void setSecret(boolean secret) {
this.secret = secret;
}
public static final RequiredCredentialModel PASSWORD = new RequiredCredentialModel(RequiredCredentialRepresentation.PASSWORD, true, true);
} }

View file

@ -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,112 +21,94 @@ 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.IdentitySession = factory;
this.factory = 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"); ScopeRelationship scope = new ScopeRelationship();
ScopeRelationship scope = new ScopeRelationship(); scope.setClient(agent);
scope.setClient(agent); scope.setScope(role);
scope.setScope(role);
} }
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;
}
} }

View file

@ -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; }
}
} }

View file

@ -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,48 +12,43 @@ 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() {
@Override @Override
public String getName() { public String getName() {
return "realm"; return "realm";
} }
}; };
public static final RelationshipQueryParameter ADMIN = new RelationshipQueryParameter() { public static final RelationshipQueryParameter ADMIN = new RelationshipQueryParameter() {
@Override @Override
public String getName() { public String getName() {
return "admin"; return "admin";
} }
}; };
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; }
}
} }

View file

@ -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;
}
}

View file

@ -11,69 +11,59 @@ 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() {
@Override @Override
public String getName() { public String getName() {
return "realmAgent"; return "realmAgent";
} }
}; };
protected Agent realmAgent; protected Agent realmAgent;
protected String credentialType; protected String credentialType;
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; }
}
} }

View file

@ -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;
}
}

View file

@ -11,40 +11,35 @@ 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() {
@Override @Override
public String getName() { public String getName() {
return "client"; return "client";
} }
}; };
protected Agent client; protected Agent client;
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; }
}
} }

View file

@ -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;
}
}

View file

@ -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());
}
}
}
}
}
}
}

View file

@ -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;
}
}

View 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;
}
}

View 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());
}
}
}
}
}
}
}

View file

@ -1,10 +1,11 @@
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;
@ -23,47 +24,47 @@ 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
@Consumes(MediaType.APPLICATION_JSON)
public Response register(UserRepresentation newUser) {
IdentitySession.getTransaction().begin();
try {
RealmManager realmManager = new RealmManager(IdentitySession);
RealmModel defaultRealm = realmManager.defaultRealm();
User user = defaultRealm.getIdm().getUser(newUser.getUsername());
if (user != null) {
return Response.status(400).type("text/plain").entity("user exists").build();
}
user = new SimpleUser(newUser.getUsername());
@POST defaultRealm.getIdm().add(user);
@Consumes(MediaType.APPLICATION_JSON) for (UserRepresentation.Credential cred : newUser.getCredentials()) {
public Response register(UserRepresentation newUser) UserCredentialModel credModel = new UserCredentialModel();
{ credModel.setType(cred.getType());
User user = defaultRealm.getIdm().getUser(newUser.getUsername()); credModel.setValue(cred.getValue());
if (user != null) defaultRealm.updateCredential(user, credModel);
{ }
return Response.status(400).type("text/plain").entity("user exists").build(); Role realmCreator = defaultRealm.getIdm().getRole(REALM_CREATOR_ROLE);
} defaultRealm.getIdm().grantRole(user, realmCreator);
IdentitySession.getTransaction().commit();
user = new SimpleUser(newUser.getUsername()); URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
defaultRealm.getIdm().add(user); return Response.created(uri).build();
for (UserRepresentation.Credential cred : newUser.getCredentials()) } catch (RuntimeException e) {
{ logger.error("Failed to register", e);
UserCredentialModel credModel = new UserCredentialModel(); IdentitySession.getTransaction().rollback();
credModel.setType(cred.getType()); throw e;
credModel.setValue(cred.getValue()); }
defaultRealm.updateCredential(user, credModel); }
}
Role realmCreator = defaultRealm.getIdm().getRole(REALM_CREATOR_ROLE);
defaultRealm.getIdm().grantRole(user, realmCreator);
URI uri = uriInfo.getBaseUriBuilder().path(RealmFactory.class).path(user.getLoginName()).build();
return Response.created(uri).build();
}
} }

View file

@ -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);
}
}
}

View file

@ -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,555 +41,400 @@ 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()
{
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
protected UriInfo uriInfo;
@Context
protected Providers providers;
@Context
protected SecurityContext securityContext;
@Context
protected HttpHeaders headers;
private static AtomicLong counter = new AtomicLong(1);
private static String generateId()
{
return counter.getAndIncrement() + "." + UUID.randomUUID().toString();
}
public TokenService(RealmManager adapter)
{
this.adapter = adapter;
this.tokenManager = new TokenManager(adapter);
this.authManager = new AuthenticationManager(adapter);
}
@Path("{realm}/grants/identity-token")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response identityTokenGrant(@PathParam("realm") String realmId, MultivaluedMap<String, String> form)
{
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
if (username == null)
{
throw new NotAuthorizedException("No user");
}
RealmModel realm = adapter.getRealm(realmId);
if (realm == null)
{
throw new NotFoundException("Realm not found");
}
if (!realm.isEnabled())
{
throw new NotAuthorizedException("Disabled realm");
}
User user = realm.getIdm().getUser(username);
if (user == null)
{
throw new NotAuthorizedException("No user");
}
if (!user.isEnabled())
{
throw new NotAuthorizedException("Disabled user.");
}
SkeletonKeyToken token = tokenManager.createIdentityToken(realm, username);
String encoded = tokenManager.encodeToken(realm, token);
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
@Path("{realm}/grants/access")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response accessTokenGrant(@PathParam("realm") String realmId, MultivaluedMap<String, String> form)
{
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
if (username == null)
{
throw new NotAuthorizedException("No user");
}
RealmModel realm = adapter.getRealm(realmId);
if (realm == null)
{
throw new NotFoundException("Realm not found");
}
if (!realm.isEnabled())
{
throw new NotAuthorizedException("Disabled realm");
}
User user = realm.getIdm().getUser(username);
if (user == null)
{
throw new NotAuthorizedException("No user");
}
if (!user.isEnabled())
{
throw new NotAuthorizedException("Disabled user.");
}
if (authManager.authenticateForm(realm, user, form))
{
throw new NotAuthorizedException("Auth failed");
}
SkeletonKeyToken token = tokenManager.createAccessToken(realm, user);
String encoded = tokenManager.encodeToken(realm, token);
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
@Path("{realm}/auth/request/login")
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response login(@PathParam("realm") String realmId,
MultivaluedMap<String, String> formData)
{
String clientId = formData.getFirst("client_id");
String scopeParam = formData.getFirst("scope");
String state = formData.getFirst("state");
String redirect = formData.getFirst("redirect_uri");
RealmModel realm = adapter.getRealm(realmId);
if (realm == null)
{
throw new NotFoundException("Realm not found");
}
if (!realm.isEnabled())
{
return Response.ok("Realm not enabled").type("text/html").build();
}
User client = realm.getIdm().getUser(clientId);
if (client == null)
{
throw new NotAuthorizedException("No client");
}
if (!client.isEnabled())
{
return Response.ok("Requester not enabled").type("text/html").build();
}
String username = formData.getFirst("username");
User user = realm.getIdm().getUser(username);
if (user == null)
{
logger.debug("user not found");
return loginForm("Not valid user", redirect, clientId, scopeParam, state, realm, client);
}
if (!user.isEnabled())
{
return Response.ok("Your account is not enabled").type("text/html").build();
}
boolean authenticated = authManager.authenticateForm(realm, user, formData);
if (!authenticated) return loginForm("Unable to authenticate, try again", redirect, clientId, scopeParam, state, realm, client);
SkeletonKeyToken token = null;
if (scopeParam != null) token = tokenManager.createScopedToken(scopeParam, realm, client, user);
else token = tokenManager.createLoginToken(realm, client, user);
AccessCode code = new AccessCode();
code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
code.setToken(token);
code.setClient(client);
synchronized (accessCodeMap)
{
accessCodeMap.put(code.getId(), code);
}
String accessCode = null;
try
{
accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realm.getPrivateKey());
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam("code", accessCode);
if (state != null) redirectUri.queryParam("state", state);
return Response.status(302).location(redirectUri.build()).build();
}
@Path("{realm}/access/codes")
@POST
@Produces("application/json")
public Response accessRequest(@PathParam("realm") String realmId,
MultivaluedMap<String, String> formData)
{
RealmModel realm = adapter.getRealm(realmId);
if (realm == null)
{
throw new NotFoundException("Realm not found");
}
if (!realm.isEnabled())
{
throw new NotAuthorizedException("Realm not enabled");
}
String code = formData.getFirst("code");
if (code == null)
{
logger.debug("code not specified");
Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_request");
error.put("error_description", "code not specified");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
String client_id = formData.getFirst("client_id");
if (client_id == null)
{
logger.debug("client_id not specified");
Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_request");
error.put("error_description", "client_id not specified");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
User client = realm.getIdm().getUser(client_id);
if (client == null)
{
logger.debug("Could not find user");
Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_client");
error.put("error_description", "Could not find user");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
if (!client.isEnabled())
{
logger.debug("user is not enabled");
Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_client");
error.put("error_description", "User is not enabled");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
boolean authenticated = authManager.authenticateForm(realm, client, formData);
if (!authenticated)
{
Map<String, String> error = new HashMap<String, String>();
error.put("error", "unauthorized_client");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
protected static final Logger logger = Logger.getLogger(TokenService.class);
protected Map<String, AccessCodeEntry> accessCodeMap;
JWSInput input = new JWSInput(code, providers); @Context
boolean verifiedCode = false; protected UriInfo uriInfo;
try @Context
{ protected Providers providers;
verifiedCode = RSAProvider.verify(input, realm.getPublicKey()); @Context
} protected SecurityContext securityContext;
catch (Exception ignored) @Context
{ protected HttpHeaders headers;
logger.debug("Failed to verify signature", ignored); @Context
} protected
if (!verifiedCode) IdentitySession IdentitySession;
{
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Unable to verify code signature");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
String key = input.readContent(String.class);
AccessCode accessCode = null;
synchronized (accessCodeMap)
{
accessCode = accessCodeMap.remove(key);
}
if (accessCode == null)
{
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Code not found");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
if (accessCode.isExpired())
{
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Code is expired");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
if (!accessCode.getToken().isActive())
{
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Token expired");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
if (!client.getId().equals(accessCode.getClient().getId()))
{
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Auth error");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken());
return Response.ok(res).build();
} protected RealmModel realm;
protected TokenManager tokenManager = new TokenManager();
protected AuthenticationManager authManager = new AuthenticationManager();
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) public TokenService(RealmModel realm, Map<String, AccessCodeEntry> accessCodeMap) {
{ this.realm = realm;
byte[] tokenBytes = null; this.accessCodeMap = accessCodeMap;
try }
{
tokenBytes = JsonSerialization.toByteArray(token, false);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
String encodedToken = new JWSBuilder()
.content(tokenBytes)
.rsa256(privateKey);
return accessTokenResponse(token, encodedToken); @Path("grants/identity-token")
} @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response identityTokenGrant(MultivaluedMap<String, String> form) {
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
if (username == null) {
throw new NotAuthorizedException("No user");
}
if (!realm.isEnabled()) {
throw new NotAuthorizedException("Disabled realm");
}
User user = realm.getIdm().getUser(username);
if (user == null) {
throw new NotAuthorizedException("No user");
}
if (!user.isEnabled()) {
throw new NotAuthorizedException("Disabled user.");
}
if (!authManager.authenticateForm(realm, user, form)) {
throw new NotAuthorizedException("FORM");
}
tokenManager = new TokenManager();
SkeletonKeyToken token = tokenManager.createIdentityToken(realm, username);
String encoded = tokenManager.encodeToken(realm, token);
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
protected AccessTokenResponse accessTokenResponse(SkeletonKeyToken token, String encodedToken) @Path("grants/access")
{ @POST
AccessTokenResponse res = new AccessTokenResponse(); @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
res.setToken(encodedToken); @Produces(MediaType.APPLICATION_JSON)
res.setTokenType("bearer"); public Response accessTokenGrant(MultivaluedMap<String, String> form) {
if (token.getExpiration() != 0) String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
{ if (username == null) {
long time = token.getExpiration() - (System.currentTimeMillis() / 1000); throw new NotAuthorizedException("No user");
res.setExpiresIn(time); }
} if (!realm.isEnabled()) {
return res; throw new NotAuthorizedException("Disabled realm");
} }
User user = realm.getIdm().getUser(username);
if (user == null) {
throw new NotAuthorizedException("No user");
}
if (!user.isEnabled()) {
throw new NotAuthorizedException("Disabled user.");
}
if (authManager.authenticateForm(realm, user, form)) {
throw new NotAuthorizedException("Auth failed");
}
SkeletonKeyToken token = tokenManager.createAccessToken(realm, user);
String encoded = tokenManager.encodeToken(realm, token);
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
@Path("{realm}/auth/request") @Path("auth/request/login")
@GET @POST
public Response requestAccessCode(@PathParam("realm") String realmId, @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@QueryParam("response_type") String responseType, public Response login(MultivaluedMap<String, String> formData) {
@QueryParam("redirect_uri") String redirect, String clientId = formData.getFirst("client_id");
@QueryParam("client_id") String clientId, String scopeParam = formData.getFirst("scope");
@QueryParam("scope") String scopeParam, String state = formData.getFirst("state");
@QueryParam("state") String state) String redirect = formData.getFirst("redirect_uri");
{
RealmModel realm = adapter.getRealm(realmId);
if (realm == null)
{
throw new NotFoundException("Realm not found");
}
if (!realm.isEnabled())
{
throw new NotAuthorizedException("Realm not enabled");
}
User client = realm.getIdm().getUser(clientId);
if (client == null)
return Response.ok("<h1>Security Alert</h1><p>Unknown client trying to get access to your account.</p>").type("text/html").build();
return loginForm(null, redirect, clientId, scopeParam, state, realm, client); if (!realm.isEnabled()) {
} return Response.ok("Realm not enabled").type("text/html").build();
}
User client = realm.getIdm().getUser(clientId);
if (client == null) {
throw new NotAuthorizedException("No client");
}
if (!client.isEnabled()) {
return Response.ok("Requester not enabled").type("text/html").build();
}
String username = formData.getFirst("username");
User user = realm.getIdm().getUser(username);
if (user == null) {
logger.debug("user not found");
return loginForm("Not valid user", redirect, clientId, scopeParam, state, realm, client);
}
if (!user.isEnabled()) {
return Response.ok("Your account is not enabled").type("text/html").build();
private Response loginForm(String validationError, String redirect, String clientId, String scopeParam, String state, RealmModel realm, User client) }
{ boolean authenticated = authManager.authenticateForm(realm, user, formData);
StringBuffer html = new StringBuffer(); if (!authenticated)
if (scopeParam != null) return loginForm("Unable to authenticate, try again", redirect, clientId, scopeParam, state, realm, client);
{
html.append("<h1>Grant Request For ").append(realm.getName()).append(" Realm</h1>");
if (validationError != null)
{
try
{
Thread.sleep(1000); // put in a delay
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
html.append("<p/><p><b>").append(validationError).append("</b></p>");
}
html.append("<p>A Third Party is requesting access to the following resources</p>");
html.append("<table>");
SkeletonKeyScope scope = tokenManager.decodeScope(scopeParam);
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
for (String res : scope.keySet()) SkeletonKeyToken token = null;
{ if (scopeParam != null) token = tokenManager.createScopedToken(scopeParam, realm, client, user);
ResourceModel resource = resourceMap.get(res); else token = tokenManager.createLoginToken(realm, client, user);
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
Set<String> scopeMapping = resource.getScope(client); AccessCodeEntry code = new AccessCodeEntry();
for (String role : scope.get(res)) code.setExpiration((System.currentTimeMillis() / 1000) + realm.getAccessCodeLifespan());
{ code.setToken(token);
html.append(" ").append(role); code.setClient(client);
if (!scopeMapping.contains("*") && !scopeMapping.contains(role)) synchronized (accessCodeMap) {
{ accessCodeMap.put(code.getId(), code);
return Response.ok("<h1>Security Alert</h1><p>Known client not authorized for the requested scope.</p>").type("text/html").build(); }
} String accessCode = null;
} try {
html.append("</td></tr>"); accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realm.getPrivateKey());
} } catch (UnsupportedEncodingException e) {
html.append("</table><p>To Authorize, please login below</p>"); throw new RuntimeException(e);
} }
else UriBuilder redirectUri = UriBuilder.fromUri(redirect).queryParam("code", accessCode);
{ if (state != null) redirectUri.queryParam("state", state);
Set<String> scopeMapping = realm.getScope(client); return Response.status(302).location(redirectUri.build()).build();
if (scopeMapping.contains("*")) }
{
html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>"); @Path("access/codes")
if (validationError != null) @POST
{ @Produces("application/json")
try public Response accessRequest(MultivaluedMap<String, String> formData) {
{ if (!realm.isEnabled()) {
Thread.sleep(1000); // put in a delay throw new NotAuthorizedException("Realm not enabled");
} }
catch (InterruptedException e)
{ String code = formData.getFirst("code");
throw new RuntimeException(e); if (code == null) {
} logger.debug("code not specified");
html.append("<p/><p><b>").append(validationError).append("</b></p>"); Map<String, String> error = new HashMap<String, String>();
} error.put("error", "invalid_request");
} error.put("error_description", "code not specified");
else return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
{
}
String client_id = formData.getFirst("client_id");
if (client_id == null) {
logger.debug("client_id not specified");
Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_request");
error.put("error_description", "client_id not specified");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
User client = realm.getIdm().getUser(client_id);
if (client == null) {
logger.debug("Could not find user");
Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_client");
error.put("error_description", "Could not find user");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
if (!client.isEnabled()) {
logger.debug("user is not enabled");
Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_client");
error.put("error_description", "User is not enabled");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
boolean authenticated = authManager.authenticateForm(realm, client, formData);
if (!authenticated) {
Map<String, String> error = new HashMap<String, String>();
error.put("error", "unauthorized_client");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
}
JWSInput input = new JWSInput(code, providers);
boolean verifiedCode = false;
try {
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
} catch (Exception ignored) {
logger.debug("Failed to verify signature", ignored);
}
if (!verifiedCode) {
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Unable to verify code signature");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
String key = input.readContent(String.class);
AccessCodeEntry accessCode = null;
synchronized (accessCodeMap) {
accessCode = accessCodeMap.remove(key);
}
if (accessCode == null) {
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Code not found");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
if (accessCode.isExpired()) {
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Code is expired");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
if (!accessCode.getToken().isActive()) {
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Token expired");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
if (!client.getId().equals(accessCode.getClient().getId())) {
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Auth error");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
}
AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken());
return Response.ok(res).build();
}
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
byte[] tokenBytes = null;
try {
tokenBytes = JsonSerialization.toByteArray(token, false);
} catch (Exception e) {
throw new RuntimeException(e);
}
String encodedToken = new JWSBuilder()
.content(tokenBytes)
.rsa256(privateKey);
return accessTokenResponse(token, encodedToken);
}
protected AccessTokenResponse accessTokenResponse(SkeletonKeyToken token, String encodedToken) {
AccessTokenResponse res = new AccessTokenResponse();
res.setToken(encodedToken);
res.setTokenType("bearer");
if (token.getExpiration() != 0) {
long time = token.getExpiration() - (System.currentTimeMillis() / 1000);
res.setExpiresIn(time);
}
return res;
}
@Path("auth/request")
@GET
public Response requestAccessCode(@QueryParam("response_type") String responseType,
@QueryParam("redirect_uri") String redirect,
@QueryParam("client_id") String clientId,
@QueryParam("scope") String scopeParam,
@QueryParam("state") String state) {
if (!realm.isEnabled()) {
throw new NotAuthorizedException("Realm not enabled");
}
User client = realm.getIdm().getUser(clientId);
if (client == null)
return Response.ok("<h1>Security Alert</h1><p>Unknown client trying to get access to your account.</p>").type("text/html").build();
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) {
StringBuffer html = new StringBuffer();
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
{ } catch (InterruptedException e) {
Thread.sleep(1000); // put in a delay throw new RuntimeException(e);
} }
catch (InterruptedException e) html.append("<p/><p><b>").append(validationError).append("</b></p>");
{
throw new RuntimeException(e);
}
html.append("<p/><p><b>").append(validationError).append("</b></p>");
}
SkeletonKeyScope scope = new SkeletonKeyScope();
List<ResourceModel> resources = realm.getResources();
boolean found = false;
for (ResourceModel resource : resources)
{
Set<String> resourceScope = resource.getScope(client);
if (resourceScope == null) continue;
if (resourceScope.size() == 0) continue;
if (!found)
{
found = true;
html.append("<p>A Third Party is requesting access to the following resources</p>");
html.append("<table>");
}
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
// todo add description of role
for (String role : resourceScope)
{
html.append(" ").append(role);
scope.add(resource.getName(), role);
}
}
if (!found)
{
return Response.ok("<h1>Security Alert</h1><p>Known client not authorized to access this realm.</p>").type("text/html").build();
}
html.append("</table>");
try
{
String json = JsonSerialization.toString(scope, false);
scopeParam = Base64Url.encode(json.getBytes("UTF-8"));
}
catch (Exception e)
{
throw new RuntimeException(e);
} }
html.append("<p>A Third Party is requesting access to the following resources</p>");
html.append("<table>");
SkeletonKeyScope scope = tokenManager.decodeScope(scopeParam);
Map<String, ResourceModel> resourceMap = realm.getResourceMap();
} for (String res : scope.keySet()) {
} ResourceModel resource = resourceMap.get(res);
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
Set<String> scopeMapping = resource.getScope(client);
for (String role : scope.get(res)) {
html.append(" ").append(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();
}
}
html.append("</td></tr>");
}
html.append("</table><p>To Authorize, please login below</p>");
} else {
Set<String> scopeMapping = realm.getScope(client);
if (scopeMapping.contains("*")) {
html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>");
if (validationError != null) {
try {
Thread.sleep(1000); // put in a delay
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
html.append("<p/><p><b>").append(validationError).append("</b></p>");
}
} else {
html.append("<h1>Grant Request For ").append(realm.getName()).append(" Realm</h1>");
if (validationError != null) {
try {
Thread.sleep(1000); // put in a delay
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
html.append("<p/><p><b>").append(validationError).append("</b></p>");
}
SkeletonKeyScope scope = new SkeletonKeyScope();
List<ResourceModel> resources = realm.getResources();
boolean found = false;
for (ResourceModel resource : resources) {
Set<String> resourceScope = resource.getScope(client);
if (resourceScope == null) continue;
if (resourceScope.size() == 0) continue;
if (!found) {
found = true;
html.append("<p>A Third Party is requesting access to the following resources</p>");
html.append("<table>");
}
html.append("<tr><td><b>Resource: </b>").append(resource.getName()).append("</td><td><b>Roles:</b>");
// todo add description of role
for (String role : resourceScope) {
html.append(" ").append(role);
scope.add(resource.getName(), role);
}
}
if (!found) {
return Response.ok("<h1>Security Alert</h1><p>Known client not authorized to access this realm.</p>").type("text/html").build();
}
html.append("</table>");
try {
String json = JsonSerialization.toString(scope, false);
scopeParam = Base64Url.encode(json.getBytes("UTF-8"));
} catch (Exception e) {
throw new RuntimeException(e);
}
UriBuilder formActionUri = uriInfo.getBaseUriBuilder().path(TokenService.class).path(TokenService.class, "login"); }
String action = formActionUri.build(realm.getId()).toString(); }
html.append("<form action=\"").append(action).append("\" method=\"POST\">");
html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>");
for (RequiredCredentialModel credential : realm.getRequiredCredentials()) UriBuilder formActionUri = uriInfo.getBaseUriBuilder().path(TokenService.class).path(TokenService.class, "login");
{ String action = formActionUri.build(realm.getId()).toString();
if (!credential.isInput()) continue; html.append("<form action=\"").append(action).append("\" method=\"POST\">");
html.append(credential.getType()).append(": "); html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>");
if (credential.isSecret())
{
html.append("<input type=\"password\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>");
} else for (RequiredCredentialModel credential : realm.getRequiredCredentials()) {
{ if (!credential.isInput()) continue;
html.append("<input type=\"text\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>"); html.append(credential.getType()).append(": ");
} if (credential.isSecret()) {
} html.append("<input type=\"password\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>");
html.append("<input type=\"hidden\" name=\"client_id\" value=\"").append(clientId).append("\">");
if (scopeParam != null) } else {
{ html.append("<input type=\"text\" name=\"").append(credential.getType()).append("\" size=\"20\"><br>");
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("\">"); html.append("<input type=\"hidden\" name=\"client_id\" value=\"").append(clientId).append("\">");
html.append("<input type=\"hidden\" name=\"redirect_uri\" value=\"").append(redirect).append("\">"); if (scopeParam != null) {
html.append("<input type=\"submit\" value=\""); html.append("<input type=\"hidden\" name=\"scope\" value=\"").append(scopeParam).append("\">");
if (scopeParam == null) html.append("Login"); }
else html.append("Grant Access"); if (state != null) html.append("<input type=\"hidden\" name=\"state\" value=\"").append(state).append("\">");
html.append("\">"); html.append("<input type=\"hidden\" name=\"redirect_uri\" value=\"").append(redirect).append("\">");
html.append("</form>"); html.append("<input type=\"submit\" value=\"");
return Response.ok(html.toString()).type("text/html").build(); if (scopeParam == null) html.append("Login");
} else html.append("Grant Access");
html.append("\">");
html.append("</form>");
return Response.ok(html.toString()).type("text/html").build();
}
} }

View file

@ -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,125 +31,108 @@ 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
public void before() throws Exception
{
after();
factory = createFactory();
adapter = new RealmManager(factory);
}
private static IdentityManagerFactory createFactory() { @Before
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder(); public void before() throws Exception {
factory = KeycloakApplication.createFactory();
IdentitySession = factory.createIdentitySession();
adapter = new RealmManager(IdentitySession);
}
builder @After
.stores() public void after() throws Exception {
.file() IdentitySession.close();
.addRealm(Realm.DEFAULT_REALM) factory.close();
.workingDirectory(WORKING_DIRECTORY) }
.preserveState(true)
.supportAllFeatures()
.supportRelationshipType(RealmResourceRelationship.class, RequiredCredentialRelationship.class, ScopeRelationship.class);
return new IdentityManagerFactory(builder.build()); @Test
} public void installTest() throws Exception {
new InstallationManager().install(adapter);
@After }
public void after() throws Exception
{
File file = new File(WORKING_DIRECTORY);
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 test1CreateRealm() throws Exception {
{ realmModel = adapter.createRealm("JUGGLER");
realmModel = adapter.create("JUGGLER"); realmModel.setAccessCodeLifespan(100);
realmModel.setAccessCodeLifespan(100); realmModel.setCookieLoginAllowed(true);
realmModel.setCookieLoginAllowed(true); realmModel.setEnabled(true);
realmModel.setEnabled(true); realmModel.setName("JUGGLER");
realmModel.setName("JUGGLER"); realmModel.setPrivateKeyPem("0234234");
realmModel.setPrivateKeyPem("0234234"); realmModel.setPublicKeyPem("0234234");
realmModel.setPublicKeyPem("0234234"); realmModel.setTokenLifespan(1000);
realmModel.setTokenLifespan(1000); realmModel.updateRealm();
realmModel.updateRealm();
System.out.println(realmModel.getId()); System.out.println(realmModel.getId());
realmModel = adapter.getRealm(realmModel.getId()); realmModel = adapter.getRealm(realmModel.getId());
Assert.assertNotNull(realmModel); Assert.assertNotNull(realmModel);
Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100); Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
Assert.assertEquals(realmModel.getTokenLifespan(), 1000); Assert.assertEquals(realmModel.getTokenLifespan(), 1000);
Assert.assertEquals(realmModel.isEnabled(), true); Assert.assertEquals(realmModel.isEnabled(), true);
Assert.assertEquals(realmModel.getName(), "JUGGLER"); Assert.assertEquals(realmModel.getName(), "JUGGLER");
Assert.assertEquals(realmModel.getPrivateKeyPem(), "0234234"); Assert.assertEquals(realmModel.getPrivateKeyPem(), "0234234");
Assert.assertEquals(realmModel.getPublicKeyPem(), "0234234"); Assert.assertEquals(realmModel.getPublicKeyPem(), "0234234");
} }
@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); creds.setType(RequiredCredentialRepresentation.PASSWORD);
creds.setType(RequiredCredentialRepresentation.PASSWORD); creds.setInput(true);
creds.setInput(true); realmModel.addRequiredCredential(creds);
realmModel.addRequiredCredential(creds); creds = new RequiredCredentialModel();
creds = new RequiredCredentialModel(); creds.setSecret(true);
creds.setSecret(true); creds.setType(RequiredCredentialRepresentation.TOTP);
creds.setType(RequiredCredentialRepresentation.TOTP); creds.setInput(true);
creds.setInput(true); realmModel.addRequiredCredential(creds);
realmModel.addRequiredCredential(creds); List<RequiredCredentialModel> storedCreds = realmModel.getRequiredCredentials();
List<RequiredCredentialModel> storedCreds = realmModel.getRequiredCredentials(); 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;
{ else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) totp = true;
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) password = true; }
else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) totp = true; Assert.assertTrue(totp);
} Assert.assertTrue(password);
Assert.assertTrue(totp); }
Assert.assertTrue(password);
}
@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); UserCredentialModel cred = new UserCredentialModel();
UserCredentialModel cred = new UserCredentialModel(); cred.setType(RequiredCredentialRepresentation.PASSWORD);
cred.setType(RequiredCredentialRepresentation.PASSWORD); cred.setValue("geheim");
cred.setValue("geheim"); realmModel.updateCredential(user, cred);
realmModel.updateCredential(user, cred); IdentityManager idm = realmModel.getIdm();
IdentityManager idm = realmModel.getIdm(); UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user.getLoginName(), new Password("geheim"));
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user.getLoginName(), new Password("geheim")); idm.validateCredentials(creds);
idm.validateCredentials(creds); Assert.assertEquals(creds.getStatus(), Credentials.Status.VALID);
Assert.assertEquals(creds.getStatus(), Credentials.Status.VALID); }
}
@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")); idm.add(new SimpleRole("user"));
idm.add(new SimpleRole("user")); List<Role> roles = realmModel.getRoles();
List<Role> roles = realmModel.getRoles(); Assert.assertEquals(2, roles.size());
Assert.assertEquals(2, roles.size()); SimpleUser user = new SimpleUser("bburke");
SimpleUser user = new SimpleUser("bburke"); idm.add(user);
idm.add(user); Role role = idm.getRole("user");
Role role = idm.getRole("user"); idm.grantRole(user, role);
idm.grantRole(user, role); Assert.assertTrue(idm.hasRole(user, role));
Assert.assertTrue(idm.hasRole(user, role)); }
}
} }

View 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);
}
}

View 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();
}
}

View file

@ -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>