jpa backend

This commit is contained in:
Bill Burke 2013-11-05 21:26:33 -05:00
parent d6ee6aef9f
commit d04ca2c34f
182 changed files with 6199 additions and 1740 deletions

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
</web-fragment>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
</web-fragment>

View file

@ -37,7 +37,8 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
.queryParam("state", state)
.build();
NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true);
logger.info("NewCookie: " + cookie.toString());
logger.debug("NewCookie: " + cookie.toString());
logger.debug("Oauth Redirect to: " + url);
return Response.status(302)
.location(url)
.cookie(cookie).build();

View file

@ -4,7 +4,10 @@ import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.jboss.resteasy.jwt.JsonWebToken;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>

View file

@ -1,7 +1,6 @@
package org.keycloak.representations.idm.admin;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
/**
* Posted to managed client from admin server.

View file

@ -6,13 +6,10 @@ import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.x509.X509V1CertificateGenerator;
import org.jboss.resteasy.jose.jws.JWSBuilder;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.keycloak.RSATokenVerifier;
import org.keycloak.ResourceMetadata;
import org.keycloak.VerificationException;
import org.keycloak.representations.SkeletonKeyToken;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.keycloak.representations.SkeletonKeyToken;
import javax.security.auth.x500.X500Principal;
import java.io.IOException;

View file

@ -5,9 +5,9 @@ import org.jboss.resteasy.jose.jws.JWSBuilder;
import org.jboss.resteasy.jose.jws.JWSInput;
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.junit.Test;
import org.keycloak.representations.SkeletonKeyScope;
import org.keycloak.representations.SkeletonKeyToken;
import org.junit.Test;
import java.security.KeyPair;
import java.security.KeyPairGenerator;

View file

@ -1,4 +1,4 @@
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
<%@ page import="javax.ws.rs.core.UriBuilder" language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>

View file

@ -1,4 +1,4 @@
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
<%@ page import="javax.ws.rs.core.UriBuilder" language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>

View file

@ -35,11 +35,6 @@
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-picketlink</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-social-core</artifactId>
@ -75,22 +70,6 @@
<artifactId>keycloak-admin-ui-styles</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-api</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-impl</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-simple-schema</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-config</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>

View file

@ -1,11 +1,11 @@
package org.keycloak.example.demo;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.KeycloakApplication;
import javax.servlet.ServletContext;

View file

@ -2,24 +2,22 @@
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"
version="1.0">
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
<class>org.keycloak.models.picketlink.mappings.RealmEntity</class>
<class>org.keycloak.models.picketlink.mappings.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.jpa.entities.RealmScopeMappingEntity</class>
<class>org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
<class>org.keycloak.models.jpa.entities.UserEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>

View file

@ -1,5 +1,6 @@
<%@ page import="org.keycloak.models.*,org.keycloak.services.resources.*,javax.ws.rs.core.*,java.util.*" language="java" contentType="text/html; charset=ISO-8859-1"
<%@ page import="org.keycloak.models.RealmModel,org.keycloak.models.RoleModel,org.keycloak.models.UserModel,javax.ws.rs.core.MultivaluedMap" language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ page import="java.util.List" %>
<%
RealmModel realm = (RealmModel)request.getAttribute(RealmModel.class.getName());
String username = (String)request.getAttribute("username");

View file

@ -1,4 +1,4 @@
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>

View file

@ -35,11 +35,6 @@
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-picketlink</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-social-core</artifactId>
@ -65,22 +60,6 @@
<artifactId>keycloak-forms</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-api</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-impl</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-simple-schema</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-config</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>

View file

@ -1,11 +1,11 @@
package org.keycloak.example.demo;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.ApplianceBootstrap;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.resources.KeycloakApplication;
import javax.servlet.ServletContext;

View file

@ -2,24 +2,22 @@
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"
version="1.0">
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
<class>org.keycloak.models.picketlink.mappings.RealmEntity</class>
<class>org.keycloak.models.picketlink.mappings.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity</class>
<class>org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.jpa.entities.RealmScopeMappingEntity</class>
<class>org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
<class>org.keycloak.models.jpa.entities.UserEntity</class>
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
@ -30,4 +28,5 @@
</properties>
</persistence-unit>
</persistence>

View file

@ -1,5 +1,6 @@
<%@ page import="org.keycloak.models.*,org.keycloak.services.resources.*,javax.ws.rs.core.*,java.util.*" language="java" contentType="text/html; charset=ISO-8859-1"
<%@ page import="org.keycloak.models.RealmModel,org.keycloak.models.RoleModel,org.keycloak.models.UserModel,javax.ws.rs.core.MultivaluedMap" language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ page import="java.util.List" %>
<%
RealmModel realm = (RealmModel)request.getAttribute(RealmModel.class.getName());
String username = (String)request.getAttribute("username");

View file

@ -33,11 +33,6 @@
<artifactId>keycloak-social-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>

View file

@ -21,12 +21,11 @@
*/
package org.keycloak.forms;
import java.util.LinkedList;
import java.util.List;
import org.keycloak.forms.model.RequiredCredential;
import javax.ws.rs.core.MultivaluedMap;
import org.keycloak.forms.model.RequiredCredential;
import java.util.LinkedList;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -21,14 +21,13 @@
*/
package org.keycloak.forms;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.core.MultivaluedMap;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import javax.ws.rs.core.MultivaluedMap;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
*/

View file

@ -21,11 +21,10 @@
*/
package org.keycloak.forms;
import javax.ws.rs.core.MultivaluedMap;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.MultivaluedMap;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/

11
forms/src/main/java/org/keycloak/forms/SocialBean.java Normal file → Executable file
View file

@ -21,15 +21,14 @@
*/
package org.keycloak.forms;
import java.net.URI;
import java.util.*;
import javax.imageio.spi.ServiceRegistry;
import javax.ws.rs.core.UriBuilder;
import org.keycloak.forms.model.SocialProvider;
import org.keycloak.services.resources.flows.Urls;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.LinkedList;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/

3
forms/src/main/java/org/keycloak/forms/TotpBean.java Normal file → Executable file
View file

@ -21,11 +21,12 @@
*/
package org.keycloak.forms;
import org.keycloak.models.utils.Base32;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Random;
import org.picketlink.common.util.Base32;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -21,10 +21,10 @@
*/
package org.keycloak.forms;
import java.net.URI;
import org.keycloak.services.resources.flows.Urls;
import java.net.URI;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/

View file

@ -21,19 +21,12 @@
*/
package org.keycloak.service;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.forms.MessageBean;
import org.keycloak.forms.LoginBean;
import org.keycloak.forms.MessageBean;
import org.keycloak.forms.OAuthGrantBean;
import org.keycloak.forms.RealmBean;
import org.keycloak.forms.RegisterBean;
@ -45,6 +38,13 @@ import org.keycloak.forms.UserBean;
import org.keycloak.services.FormService;
import org.keycloak.services.resources.flows.Pages;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;
/**
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
*/

View file

@ -7,7 +7,6 @@ import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.SkeletonKeySession;
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
import org.keycloak.representations.SkeletonKeyToken;

View file

@ -1,879 +0,0 @@
package org.keycloak.adapters.as7;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.authenticator.FormAuthenticator;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.realm.GenericPrincipal;
import org.bouncycastle.openssl.PEMWriter;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.jboss.logging.Logger;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.jose.jws.JWSBuilder;
import org.jboss.resteasy.jose.jws.JWSInput;
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.plugins.server.servlet.ServletUtil;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.ResteasyUriInfo;
import org.jboss.resteasy.util.BasicAuthHelper;
import org.keycloak.EnvUtil;
import org.keycloak.PemUtils;
import org.keycloak.ResourceMetadata;
import org.keycloak.SkeletonKeySession;
import org.keycloak.adapters.as7.config.AuthServerConfig;
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.SkeletonKeyToken;
import javax.security.auth.login.LoginException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.UriBuilder;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
/**
* Turns a web deployment into an authentication server that follwos the OAuth 2 protocol and Skeleton Key bearer tokens.
* Authentication store is backed by a JBoss security domain.
* <p/>
* Servlet FORM authentication that uses the local security domain to authenticate and for role mappings.
* <p/>
* Supports bearer token creation and authentication. The client asking for access must be set up as a valid user
* within the security domain.
* <p/>
* If no an OAuth access request, this works like normal FORM authentication and authorization.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class OAuthAuthenticationServerValve extends FormAuthenticator implements LifecycleListener {
public static class AccessCode {
protected String id = UUID.randomUUID().toString() + System.currentTimeMillis();
protected long expiration;
protected SkeletonKeyToken token;
protected String client;
protected boolean sso;
protected String redirect;
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 String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public boolean isSso() {
return sso;
}
public void setSso(boolean sso) {
this.sso = sso;
}
public String getRedirect() {
return redirect;
}
public void setRedirect(String redirect) {
this.redirect = redirect;
}
}
protected ConcurrentHashMap<String, AccessCode> accessCodeMap = new ConcurrentHashMap<String, AccessCode>();
private static final Logger log = Logger.getLogger(OAuthAuthenticationServerValve.class);
private static AtomicLong counter = new AtomicLong(1);
private static String generateId() {
return counter.getAndIncrement() + "." + UUID.randomUUID().toString();
}
protected AuthServerConfig skeletonKeyConfig;
protected PrivateKey realmPrivateKey;
protected PublicKey realmPublicKey;
protected String realmPublicKeyPem;
protected ResteasyProviderFactory providers;
protected ResourceMetadata resourceMetadata;
protected UserSessionManagement userSessionManagement = new UserSessionManagement();
protected ObjectMapper mapper;
protected ObjectWriter accessTokenResponseWriter;
protected ObjectWriter mapWriter;
private static KeyStore loadKeyStore(String filename, String password) throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
File truststoreFile = new File(filename);
FileInputStream trustStream = new FileInputStream(truststoreFile);
trustStore.load(trustStream, password.toCharArray());
trustStream.close();
return trustStore;
}
@Override
public void start() throws LifecycleException {
super.start();
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
}
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
}
protected void init() {
mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
accessTokenResponseWriter = mapper.writerWithType(AccessTokenResponse.class);
mapWriter = mapper.writerWithType(mapper.getTypeFactory().constructMapType(Map.class, String.class, String.class));
InputStream is = null;
String path = context.getServletContext().getInitParameter("skeleton.key.config.file");
if (path == null) {
is = context.getServletContext().getResourceAsStream("/WEB-INF/resteasy-oauth.json");
} else {
try {
is = new FileInputStream(path);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
try {
skeletonKeyConfig = mapper.readValue(is, AuthServerConfig.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (skeletonKeyConfig.getLoginRole() == null) {
throw new RuntimeException("You must define the login-role in your config file");
}
if (skeletonKeyConfig.getClientRole() == null) {
throw new RuntimeException("You must define the oauth-client-role in your config file");
}
if (skeletonKeyConfig.getRealmPrivateKey() != null) {
try {
realmPrivateKey = PemUtils.decodePrivateKey(skeletonKeyConfig.getRealmPrivateKey());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (skeletonKeyConfig.getRealmPublicKey() != null) {
try {
realmPublicKey = PemUtils.decodePublicKey(skeletonKeyConfig.getRealmPublicKey());
realmPublicKeyPem = skeletonKeyConfig.getRealmPublicKey();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (skeletonKeyConfig.getRealmKeyStore() != null) {
if (skeletonKeyConfig.getRealmKeyAlias() == null) throw new RuntimeException("Must define realm-key-alias");
String keystorePath = EnvUtil.replace(skeletonKeyConfig.getRealmKeyStore());
try {
KeyStore ks = loadKeyStore(keystorePath, skeletonKeyConfig.getRealmKeystorePassword());
if (realmPrivateKey == null) {
realmPrivateKey = (PrivateKey) ks.getKey(skeletonKeyConfig.getRealmKeyAlias(), skeletonKeyConfig.getRealmPrivateKeyPassword().toCharArray());
}
if (realmPublicKey == null) {
Certificate cert = ks.getCertificate(skeletonKeyConfig.getRealmKeyAlias());
realmPublicKey = cert.getPublicKey();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (realmPublicKey == null) throw new RuntimeException("You have not declared a keystore or public key");
if (realmPrivateKey == null) throw new RuntimeException("You have not declared a keystore or private key");
if (realmPublicKeyPem == null) {
StringWriter sw = new StringWriter();
PEMWriter writer = new PEMWriter(sw);
try {
writer.writeObject(realmPublicKey);
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
realmPublicKeyPem = sw.toString();
realmPublicKeyPem = PemUtils.removeBeginEnd(realmPublicKeyPem);
}
providers = new ResteasyProviderFactory();
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(OAuthAuthenticationServerValve.class.getClassLoader());
try {
ResteasyProviderFactory.getInstance(); // initialize builtins
RegisterBuiltin.register(providers);
} finally {
Thread.currentThread().setContextClassLoader(old);
}
resourceMetadata = new ResourceMetadata();
resourceMetadata.setRealm(skeletonKeyConfig.getRealm());
resourceMetadata.setRealmKey(realmPublicKey);
String truststore = skeletonKeyConfig.getTruststore();
if (truststore != null) {
truststore = EnvUtil.replace(truststore);
String truststorePassword = skeletonKeyConfig.getTruststorePassword();
KeyStore trust = null;
try {
trust = loadKeyStore(truststore, truststorePassword);
} catch (Exception e) {
throw new RuntimeException("Failed to load truststore", e);
}
resourceMetadata.setTruststore(trust);
}
String clientKeystore = skeletonKeyConfig.getClientKeystore();
String clientKeyPassword = null;
if (clientKeystore != null) {
clientKeystore = EnvUtil.replace(clientKeystore);
String clientKeystorePassword = skeletonKeyConfig.getClientKeystorePassword();
KeyStore serverKS = null;
try {
serverKS = loadKeyStore(clientKeystore, clientKeystorePassword);
} catch (Exception e) {
throw new RuntimeException("Failed to load keystore", e);
}
resourceMetadata.setClientKeystore(serverKS);
clientKeyPassword = skeletonKeyConfig.getClientKeyPassword();
resourceMetadata.setClientKeyPassword(clientKeyPassword);
}
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
String contextPath = request.getContextPath();
String requestURI = request.getDecodedRequestURI();
log.debug("--- invoke: " + requestURI);
if (request.getMethod().equalsIgnoreCase("GET")
&& context.getLoginConfig().getLoginPage().equals(request.getRequestPathMB().toString())) {
if (handleLoginPage(request, response)) return;
} else if (request.getMethod().equalsIgnoreCase("GET")
&& requestURI.endsWith(Actions.J_OAUTH_LOGOUT)) {
logoutCurrentUser(request, response);
return;
} else if (request.getMethod().equalsIgnoreCase("POST")
&& requestURI.endsWith(Actions.J_OAUTH_ADMIN_FORCED_LOGOUT)) {
adminLogout(request, response);
return;
} else if (request.getMethod().equalsIgnoreCase("POST")
&& requestURI.startsWith(contextPath) &&
requestURI.endsWith(Constants.FORM_ACTION)
&& request.getParameter("client_id") != null) {
handleOAuth(request, response);
return;
} else if (request.getMethod().equalsIgnoreCase("POST")
&& requestURI.endsWith(Actions.J_OAUTH_TOKEN_GRANT)) {
tokenGrant(request, response);
return;
} else if (request.getMethod().equalsIgnoreCase("POST")
&& requestURI.startsWith(contextPath) &&
requestURI.endsWith(Actions.J_OAUTH_RESOLVE_ACCESS_CODE)) {
resolveAccessCode(request, response);
return;
} else if (request.getMethod().equalsIgnoreCase("GET")
&& requestURI.startsWith(contextPath) &&
requestURI.endsWith("j_oauth_realm_info.html")) {
publishRealmInfoHtml(request, response);
return;
}
// propagate the skeleton key token string?
if (!skeletonKeyConfig.isCancelPropagation()) {
if (request.getAttribute(SkeletonKeySession.class.getName()) == null && request.getSessionInternal() != null) {
SkeletonKeySession skSession = (SkeletonKeySession) request.getSessionInternal().getNote(SkeletonKeySession.class.getName());
if (skSession != null) {
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
}
}
}
request.setAttribute("OAUTH_FORM_ACTION", "j_security_check");
super.invoke(request, response);
} finally {
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
}
}
protected boolean handleLoginPage(Request request, Response response) throws IOException, ServletException {
String client_id = request.getParameter("client_id");
// if this is not an OAUTH redirect, just return and let the default flow happen
if (client_id == null) return false;
String redirect_uri = request.getParameter("redirect_uri");
String state = request.getParameter("state");
if (redirect_uri == null) {
response.sendError(400, "No oauth redirect query parameter set");
return true;
}
// only bypass authentication if our session is authenticated,
// the login query parameter is on request URL,
// and we have configured the login-role
else if (!skeletonKeyConfig.isSsoDisabled()
&& request.getSessionInternal() != null
&& request.getSessionInternal().getPrincipal() != null
&& request.getParameter("login") != null) {
log.debug("We're ALREADY LOGGED IN!!!");
GenericPrincipal gp = (GenericPrincipal) request.getSessionInternal().getPrincipal();
redirectAccessCode(true, response, redirect_uri, client_id, state, gp);
} else {
UriBuilder builder = UriBuilder.fromUri("j_security_check")
.queryParam("redirect_uri", redirect_uri)
.queryParam("client_id", client_id);
if (state != null) builder.queryParam("state", state);
String loginAction = builder.build().toString();
request.setAttribute("OAUTH_FORM_ACTION", loginAction);
getNext().invoke(request, response);
}
return true;
}
protected GenericPrincipal checkLoggedIn(Request request, HttpServletResponse response) {
if (request.getPrincipal() != null) {
return (GenericPrincipal) request.getPrincipal();
} else if (request.getSessionInternal() != null && request.getSessionInternal().getPrincipal() != null) {
return (GenericPrincipal) request.getSessionInternal().getPrincipal();
}
return null;
}
protected void adminLogout(Request request, HttpServletResponse response) throws IOException {
log.debug("<< adminLogout");
GenericPrincipal gp = checkLoggedIn(request, response);
if (gp == null) {
if (bearer(request, response, false)) {
gp = (GenericPrincipal) request.getPrincipal();
} else {
response.sendError(403);
return;
}
}
if (!gp.hasRole(skeletonKeyConfig.getAdminRole())) {
response.sendError(403);
return;
}
String logoutUser = request.getParameter("user");
if (logoutUser != null) {
userSessionManagement.logout(logoutUser);
logoutResources(logoutUser, gp.getName());
} else {
userSessionManagement.logoutAllBut(gp.getName());
logoutResources(null, gp.getName());
}
String forwardTo = request.getParameter("forward");
if (forwardTo == null) {
response.setStatus(204);
return;
}
RequestDispatcher disp =
context.getServletContext().getRequestDispatcher(forwardTo);
try {
disp.forward(request.getRequest(), response);
} catch (Throwable t) {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
"failed to forward");
}
}
protected void logoutCurrentUser(Request request, HttpServletResponse response) throws IOException {
if (request.getSessionInternal() == null || request.getSessionInternal().getPrincipal() == null) {
redirectToWelcomePage(request, response);
return;
}
GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal();
String username = principal.getName();
String admin = username;
userSessionManagement.logout(username);
request.setUserPrincipal(null);
request.setAuthType(null);
// logout user on all declared authenticated applications
logoutResources(username, admin);
redirectToWelcomePage(request, response);
}
protected void logoutResources(String username, String admin) {
if (skeletonKeyConfig.getResources().size() != 0) {
SkeletonKeyToken token = new SkeletonKeyToken();
token.id(generateId());
token.principal(admin);
token.audience(skeletonKeyConfig.getRealm());
SkeletonKeyToken.Access realmAccess = new SkeletonKeyToken.Access();
realmAccess.addRole(skeletonKeyConfig.getAdminRole());
token.setRealmAccess(realmAccess);
String tokenString = buildTokenString(realmPrivateKey, token);
ResteasyClient client = new ResteasyClientBuilder()
.providerFactory(providers)
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
.trustStore(resourceMetadata.getTruststore())
.keyStore(resourceMetadata.getClientKeystore(), resourceMetadata.getClientKeyPassword())
.build();
try {
for (String resource : skeletonKeyConfig.getResources()) {
try {
log.debug("logging out: " + resource);
WebTarget target = client.target(resource).path(Actions.J_OAUTH_REMOTE_LOGOUT);
if (username != null) target = target.queryParam("user", username);
javax.ws.rs.core.Response response = target.request()
.header("Authorization", "Bearer " + tokenString)
.put(null);
if (response.getStatus() != 204) log.error("Failed to log out");
response.close();
} catch (Exception ignored) {
log.error("Failed to log out", ignored);
}
}
} finally {
client.close();
}
}
}
protected void redirectToWelcomePage(Request request, HttpServletResponse response) throws IOException {
ResteasyUriInfo uriInfo = ServletUtil.extractUriInfo(request, null);
String[] welcomes = context.findWelcomeFiles();
if (welcomes.length > 0) {
UriBuilder welcome = uriInfo.getBaseUriBuilder().path(welcomes[0]);
response.sendRedirect(welcome.toTemplate());
} else {
response.setStatus(204);
}
}
protected void publishRealmInfoHtml(Request request, HttpServletResponse response) throws IOException {
ManagedResourceConfig rep = getRealmRepresentation(request);
StringWriter writer;
String json;
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
StringBuffer html = new StringBuffer();
html.append("<html><body bgcolor=\"#CED8F6\">");
html.append("<h1>Realm: ").append(rep.getRealm()).append("</h1>");
ManagedResourceConfig bearer = new ManagedResourceConfig();
bearer.setRealm(rep.getRealm());
bearer.setRealmKey(rep.getRealmKey());
writer = new StringWriter();
mapper.writeValue(writer, bearer);
json = writer.toString();
html.append("<h3>BearerTokenAuthValve Json Config</h3>");
html.append("<form><textarea rows=\"7\" cols=\"80\">").append(json).append("</textarea></form>");
html.append("<br>");
writer = new StringWriter();
rep.getCredentials().put("password", "REQUIRED");
//rep.setClientId("REQUIRED");
rep.setTruststore("REQUIRED");
rep.setTruststorePassword("REQUIRED");
mapper.writeValue(writer, rep);
json = writer.toString();
html.append("<h3>OAuthManagedResourceValve Json Config</h3>");
html.append("<form><textarea rows=\"20\" cols=\"80\">").append(json).append("</textarea></form>");
html.append("</body></html>");
response.setStatus(200);
response.setContentType("text/html");
response.getOutputStream().println(html.toString());
response.getOutputStream().flush();
}
protected ManagedResourceConfig getRealmRepresentation(Request request) {
ManagedResourceConfig rep = new ManagedResourceConfig();
ResteasyUriInfo uriInfo = ServletUtil.extractUriInfo(request, null);
UriBuilder authUrl = uriInfo.getBaseUriBuilder().path(context.getLoginConfig().getLoginPage());
UriBuilder codeUrl = uriInfo.getBaseUriBuilder().path(Actions.J_OAUTH_RESOLVE_ACCESS_CODE);
rep.setRealm(skeletonKeyConfig.getRealm());
rep.setRealmKey(realmPublicKeyPem);
rep.setAuthUrl(authUrl.toTemplate());
rep.setCodeUrl(codeUrl.toTemplate());
rep.setAdminRole(skeletonKeyConfig.getAdminRole());
return rep;
}
public boolean bearer(Request request, HttpServletResponse response, boolean propagate) throws IOException {
if (request.getHeader("Authorization") != null) {
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, false, false);
try {
if (bearer.login(request, response)) {
return true;
}
} catch (LoginException e) {
}
}
return false;
}
@Override
protected void register(Request request, HttpServletResponse response, Principal principal, String authType, String username, String password) {
super.register(request, response, principal, authType, username, password);
log.debug("authenticate userSessionManage.login(): " + principal.getName());
userSessionManagement.login(request.getSessionInternal(), principal.getName());
if (!skeletonKeyConfig.isCancelPropagation()) {
GenericPrincipal gp = (GenericPrincipal) request.getPrincipal();
if (gp != null) {
SkeletonKeyToken token = buildToken(gp);
String stringToken = buildTokenString(realmPrivateKey, token);
SkeletonKeySession skSession = new SkeletonKeySession(stringToken, token, resourceMetadata);
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
request.getSessionInternal(true).setNote(SkeletonKeySession.class.getName(), skSession);
}
}
}
@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
if (bearer(request, response, true)) {
return true;
}
return super.authenticate(request, response, config);
}
protected void resolveAccessCode(Request request, Response response) throws IOException {
if (!request.isSecure()) {
response.sendError(400);
return;
}
// always verify code and remove access code from map before authenticating user
// if user authentication fails, we want the code to be removed irreguardless just in case we're under attack
String code = request.getParameter("code");
JWSInput input = new JWSInput(code, providers);
boolean verifiedCode = false;
try {
verifiedCode = RSAProvider.verify(input, realmPublicKey);
} catch (Exception ignored) {
log.error("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");
response.sendError(400);
response.setContentType("application/json");
mapWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
return;
}
String key = input.readContent(String.class);
AccessCode accessCode = accessCodeMap.remove(key);
String redirect = request.getParameter("redirect_uri");
GenericPrincipal gp = basicAuth(request, response);
if (gp == null) {
log.error("Failed to authenticate client_id");
return;
}
if (accessCode == null) {
log.error("No access code: " + code);
response.sendError(400);
return;
}
if (accessCode.isExpired()) {
log.debug("Access code expired");
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Code is expired");
response.setStatus(400);
response.setContentType("application/json");
mapWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
return;
}
if (!accessCode.getToken().isActive()) {
log.debug("token not active");
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Token expired");
response.setStatus(400);
response.setContentType("application/json");
mapWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
return;
}
if (!gp.getName().equals(accessCode.getClient())) {
log.debug("not equal client");
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Auth error");
response.setStatus(400);
response.setContentType("application/json");
mapWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
return;
}
if (!accessCode.getRedirect().equals(redirect)) {
log.debug("not equal redirect");
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Auth error");
response.setStatus(400);
response.setContentType("application/json");
mapWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
return;
}
if (accessCode.isSso() && !gp.hasRole(skeletonKeyConfig.getLoginRole())) {
// we did not authenticate user on an access code request because a session was already established
// but, the client_id does not have permission to bypass this on a simple grant. We want
// to always ask for credentials from a simple oath request
log.debug("does not have login permission");
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Auth error");
response.setStatus(400);
response.setContentType("application/json");
mapWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
return;
} else if (!gp.hasRole(skeletonKeyConfig.getClientRole()) && !gp.hasRole(skeletonKeyConfig.getLoginRole())) {
log.debug("does not have login or client role permission for access token request");
Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant");
res.put("error_description", "Auth error");
response.setStatus(400);
response.setContentType("application/json");
mapWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
return;
}
String wildcard = skeletonKeyConfig.getWildcardRole() == null ? "*" : skeletonKeyConfig.getWildcardRole();
Set<String> codeRoles = accessCode.getToken().getRealmAccess().getRoles();
if (codeRoles != null &&
(codeRoles.contains(skeletonKeyConfig.getClientRole()) || codeRoles.contains(skeletonKeyConfig.getLoginRole()))) {
// we store roles a oauth client is granted in the user role mapping, remove those roles as we don't want those clients with those
// permissions if they are logging in.
Set<String> newRoles = new HashSet<String>();
if (codeRoles.contains(skeletonKeyConfig.getClientRole())) newRoles.add(skeletonKeyConfig.getClientRole());
if (codeRoles.contains(skeletonKeyConfig.getLoginRole())) newRoles.add(skeletonKeyConfig.getLoginRole());
if (codeRoles.contains(wildcard)) newRoles.add(wildcard);
codeRoles.clear();
codeRoles.addAll(newRoles);
}
// is we have a login role, then we don't need to filter out roles, just grant all the roles the user has
// Also, if the client has the "wildcard" role, then we don't need to filter out roles
if (codeRoles != null
&& !gp.hasRole(wildcard)
&& !gp.hasRole(skeletonKeyConfig.getLoginRole())) {
Set<String> clientAllowed = new HashSet<String>();
for (String role : gp.getRoles()) {
clientAllowed.add(role);
}
Set<String> newRoles = new HashSet<String>();
newRoles.addAll(codeRoles);
for (String role : newRoles) {
if (!clientAllowed.contains(role)) {
codeRoles.remove(role);
}
}
}
AccessTokenResponse res = accessTokenResponse(realmPrivateKey, accessCode.getToken());
response.setStatus(200);
response.setContentType("application/json");
accessTokenResponseWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
}
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
String encodedToken = buildTokenString(privateKey, token);
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;
}
protected String buildTokenString(PrivateKey privateKey, SkeletonKeyToken token) {
byte[] tokenBytes = null;
try {
tokenBytes = JsonSerialization.toByteArray(token, false);
} catch (Exception e) {
throw new RuntimeException(e);
}
return new JWSBuilder()
.content(tokenBytes)
.rsa256(privateKey);
}
protected void handleOAuth(Request request, Response response) throws IOException {
log.debug("<--- Begin oauthAuthenticate");
String redirect_uri = request.getParameter("redirect_uri");
String client_id = request.getParameter("client_id");
String state = request.getParameter("state");
String username = request.getParameter(Constants.FORM_USERNAME);
String password = request.getParameter(Constants.FORM_PASSWORD);
Principal principal = context.getRealm().authenticate(username, password);
if (principal == null) {
UriBuilder builder = UriBuilder.fromUri(redirect_uri).queryParam("error", "unauthorized_client");
if (state != null) builder.queryParam("state", state);
response.sendRedirect(builder.toTemplate());
return;
}
GenericPrincipal gp = (GenericPrincipal) principal;
register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
userSessionManagement.login(request.getSessionInternal(), username);
redirectAccessCode(false, response, redirect_uri, client_id, state, gp);
return;
}
protected void tokenGrant(Request request, Response response) throws IOException {
if (!request.isSecure()) {
response.sendError(400);
return;
}
GenericPrincipal gp = basicAuth(request, response);
if (gp == null) return;
SkeletonKeyToken token = buildToken(gp);
AccessTokenResponse res = accessTokenResponse(realmPrivateKey, token);
response.setStatus(200);
response.setContentType("application/json");
accessTokenResponseWriter.writeValue(response.getOutputStream(), res);
response.getOutputStream().flush();
}
protected GenericPrincipal basicAuth(Request request, Response response) throws IOException {
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
if (authHeader == null) {
basicAuthError(response);
return null;
}
String[] creds = BasicAuthHelper.parseHeader(authHeader);
if (creds == null) {
basicAuthError(response);
return null;
}
String username = creds[0];
String password = creds[1];
GenericPrincipal gp = (GenericPrincipal) context.getRealm().authenticate(username, password);
if (gp == null) {
basicAuthError(response);
return null;
}
return gp;
}
protected void basicAuthError(Response response) throws IOException {
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"" + context.getLoginConfig().getRealmName() + "\"");
response.sendError(401);
}
protected void redirectAccessCode(boolean sso, Response response, String redirect_uri, String client_id, String state, GenericPrincipal gp) throws IOException {
SkeletonKeyToken token = buildToken(gp);
AccessCode code = new AccessCode();
code.setToken(token);
code.setClient(client_id);
code.setSso(sso);
code.setRedirect(redirect_uri);
int expiration = skeletonKeyConfig.getAccessCodeLifetime() == 0 ? 300 : skeletonKeyConfig.getAccessCodeLifetime();
code.setExpiration((System.currentTimeMillis() / 1000) + expiration);
accessCodeMap.put(code.getId(), code);
log.debug("--- sign access code");
String accessCode = null;
try {
accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realmPrivateKey);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
log.debug("--- build redirect");
UriBuilder redirectUri = UriBuilder.fromUri(redirect_uri).queryParam("code", accessCode);
if (state != null) redirectUri.queryParam("state", state);
response.sendRedirect(redirectUri.toTemplate());
log.debug("<--- end oauthAuthenticate");
}
protected SkeletonKeyToken buildToken(GenericPrincipal gp) {
SkeletonKeyToken token = new SkeletonKeyToken();
token.id(generateId());
token.principal(gp.getName());
token.audience(skeletonKeyConfig.getRealm());
int expiration = skeletonKeyConfig.getAccessCodeLifetime() == 0 ? 3600 : skeletonKeyConfig.getAccessCodeLifetime();
if (skeletonKeyConfig.getTokenLifetime() > 0) {
token.expiration((System.currentTimeMillis() / 1000) + expiration);
}
SkeletonKeyToken.Access realmAccess = new SkeletonKeyToken.Access();
for (String role : gp.getRoles()) {
realmAccess.addRole(role);
}
token.setRealmAccess(realmAccess);
return token;
}
}

View file

@ -5,7 +5,6 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>

View file

@ -13,7 +13,6 @@ import org.keycloak.PemUtils;
import org.keycloak.ResourceMetadata;
import org.keycloak.representations.idm.PublishedRealmRepresentation;
import javax.ws.rs.client.WebTarget;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

View file

@ -1,8 +1,5 @@
package org.keycloak.models;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $

View file

@ -0,0 +1,9 @@
package org.keycloak.models;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ModelProvider {
KeycloakSessionFactory createFactory();
}

View file

@ -1,7 +1,5 @@
package org.keycloak.models;
import org.keycloak.models.UserModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
@ -10,8 +8,4 @@ public interface OAuthClientModel {
String getId();
UserModel getOAuthAgent();
String getBaseUrl();
void setBaseUrl(String base);
}

View file

@ -2,7 +2,6 @@ package org.keycloak.models;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -138,11 +137,11 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
List<OAuthClientModel> getOAuthClients();
HashMap<String, String> getSmtpConfig();
Map<String, String> getSmtpConfig();
void setSmtpConfig(HashMap<String, String> smtpConfig);
void setSmtpConfig(Map<String, String> smtpConfig);
HashMap<String, String> getSocialConfig();
Map<String, String> getSocialConfig();
void setSocialConfig(HashMap<String, String> socialConfig);
void setSocialConfig(Map<String, String> socialConfig);
}

View file

@ -0,0 +1,113 @@
package org.keycloak.models.utils;
/* (PD) 2006 The Bitzi Corporation
* Please see http://bitzi.com/publicdomain for more info.
*
* $Id: Base32.java,v 1.2 2006/07/14 04:58:39 gojomo Exp $
*/
/**
* Base32 - encodes and decodes RFC3548 Base32 (see http://www.faqs.org/rfcs/rfc3548.html )
*
* @author Robert Kaye
* @author Gordon Mohr
*/
public class Base32 {
private static final String base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
private static final int[] base32Lookup = { 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/**
* Encodes byte array to Base32 String.
*
* @param bytes Bytes to encode.
* @return Encoded byte array <code>bytes</code> as a String.
*
*/
public static String encode(final byte[] bytes) {
int i = 0, index = 0, digit = 0;
int currByte, nextByte;
StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
while (i < bytes.length) {
currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
/* Is the current digit going to span a byte boundary? */
if (index > 3) {
if ((i + 1) < bytes.length) {
nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1] : (bytes[i + 1] + 256);
} else {
nextByte = 0;
}
digit = currByte & (0xFF >> index);
index = (index + 5) % 8;
digit <<= index;
digit |= nextByte >> (8 - index);
i++;
} else {
digit = (currByte >> (8 - (index + 5))) & 0x1F;
index = (index + 5) % 8;
if (index == 0)
i++;
}
base32.append(base32Chars.charAt(digit));
}
return base32.toString();
}
/**
* Decodes the given Base32 String to a raw byte array.
*
* @param base32
* @return Decoded <code>base32</code> String as a raw byte array.
*/
public static byte[] decode(final String base32) {
int i, index, lookup, offset, digit;
byte[] bytes = new byte[base32.length() * 5 / 8];
for (i = 0, index = 0, offset = 0; i < base32.length(); i++) {
lookup = base32.charAt(i) - '0';
/* Skip chars outside the lookup table */
if (lookup < 0 || lookup >= base32Lookup.length) {
continue;
}
digit = base32Lookup[lookup];
/* If this digit is not in the table, ignore it */
if (digit == 0xFF) {
continue;
}
if (index <= 3) {
index = (index + 5) % 8;
if (index == 0) {
bytes[offset] |= digit;
offset++;
if (offset >= bytes.length)
break;
} else {
bytes[offset] |= digit << (8 - index);
}
} else {
index = (index + 5) % 8;
bytes[offset] |= (digit >>> index);
offset++;
if (offset >= bytes.length) {
break;
}
bytes[offset] |= digit << (8 - index);
}
}
return bytes;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,58 @@
package org.keycloak.models.utils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* <p>
* Password that uses SHA to encode passwords. You can always change the SHA strength by specifying a valid
* integer when creating a new instance.
* </p>
* <p>Passwords are returned with a Base64 encoding.</p>
*
* @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
*
*/
public class SHAPasswordEncoder {
private int strength;
public SHAPasswordEncoder(int strength) {
this.strength = strength;
}
public String encode(String rawPassword) {
MessageDigest messageDigest = getMessageDigest();
String encodedPassword = null;
try {
byte[] digest = messageDigest.digest(rawPassword.getBytes("UTF-8"));
encodedPassword = Base64.encodeBytes(digest);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Credential could not be encoded");
}
return encodedPassword;
}
public boolean verify(String rawPassword, String encodedPassword) {
return encode(rawPassword).equals(encodedPassword);
}
protected final MessageDigest getMessageDigest() throws IllegalArgumentException {
String algorithm = "SHA-" + this.strength;
try {
return MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("invalid credential encoding algorithm");
}
}
public int getStrength() {
return this.strength;
}
}

View file

@ -0,0 +1,216 @@
package org.keycloak.models.utils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
/**
* TOTP: Time-based One-time Password Algorithm Based on http://tools.ietf.org/html/draft-mraihi-totp-timebased-06
*
* @author anil saldhana
* @since Sep 20, 2010
*/
public class TimeBasedOTP {
public static final String HMAC_SHA1 = "HmacSHA1";
public static final String HMAC_SHA256 = "HmacSHA256";
public static final String HMAC_SHA512 = "HmacSHA512";
public static final String DEFAULT_ALGORITHM = HMAC_SHA1;
public static final int DEFAULT_NUMBER_DIGITS = 6;
public static final int DEFAULT_INTERVAL_SECONDS = 30;
public static final int DEFAULT_DELAY_WINDOW = 1;
// 0 1 2 3 4 5 6 7 8
private static final int[] DIGITS_POWER = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
private Clock clock;
private final String algorithm;
private final int numberDigits;
private final int delayWindow;
public TimeBasedOTP() {
this(DEFAULT_ALGORITHM, DEFAULT_NUMBER_DIGITS, DEFAULT_INTERVAL_SECONDS, DEFAULT_DELAY_WINDOW);
}
/**
* @param algorithm the encryption algorithm
* @param numberDigits the number of digits for tokens
* @param timeIntervalInSeconds the number of seconds a token is valid
* @param delayWindow the number of previous intervals that should be used to validate tokens.
*/
public TimeBasedOTP(String algorithm, int numberDigits, int timeIntervalInSeconds, int delayWindow) {
this.algorithm = algorithm;
this.numberDigits = numberDigits;
this.clock = new Clock(timeIntervalInSeconds);
this.delayWindow = delayWindow;
}
/**
* <p>Generates a token.</p>
*
* @param secretKey the secret key to derive the token from.
*/
public String generate(String secretKey) {
long T = this.clock.getCurrentInterval();
String steps = Long.toHexString(T).toUpperCase();
// Just get a 16 digit string
while (steps.length() < 16)
steps = "0" + steps;
return generateTOTP(secretKey, steps, this.numberDigits, this.algorithm);
}
/**
* This method generates an TOTP value for the given set of parameters.
*
* @param key the shared secret, HEX encoded
* @param time a value that reflects a time
* @param returnDigits number of digits to return
* @param crypto the crypto function to use
* @return A numeric String in base 10 that includes {@link truncationDigits} digits
* @throws java.security.GeneralSecurityException
*
*/
public String generateTOTP(String key, String time, int returnDigits, String crypto) {
String result = null;
byte[] hash;
// Using the counter
// First 8 bytes are for the movingFactor
// Complaint with base RFC 4226 (HOTP)
while (time.length() < 16)
time = "0" + time;
// Get the HEX in a Byte[]
byte[] msg = hexStr2Bytes(time);
// Adding one byte to get the right conversion
// byte[] k = hexStr2Bytes(key);
byte[] k = key.getBytes();
hash = hmac_sha1(crypto, k, msg);
// put selected bytes into result int
int offset = hash[hash.length - 1] & 0xf;
int binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8)
| (hash[offset + 3] & 0xff);
int otp = binary % DIGITS_POWER[returnDigits];
result = Integer.toString(otp);
while (result.length() < returnDigits) {
result = "0" + result;
}
return result;
}
/**
* <p>Validates a token using a secret key.</p>
*
* @param token OTP string to validate
* @param secret Shared secret
* @return
*/
public boolean validate(String token, byte[] secret) {
long currentInterval = this.clock.getCurrentInterval();
for (int i = this.delayWindow; i >= 0; --i) {
String steps = Long.toHexString(currentInterval - i).toUpperCase();
// Just get a 16 digit string
while (steps.length() < 16)
steps = "0" + steps;
String candidate = generateTOTP(new String(secret), steps, this.numberDigits, this.algorithm);
if (candidate.equals(token)) {
return true;
}
}
return false;
}
public void setCalendar(Calendar calendar) {
this.clock.setCalendar(calendar);
}
/**
* This method uses the JCE to provide the crypto algorithm. HMAC computes a Hashed Message Authentication Code with the
* crypto hash algorithm as a parameter.
*
* @param crypto the crypto algorithm (HmacSHA1, HmacSHA256, HmacSHA512)
* @param keyBytes the bytes to use for the HMAC key
* @param text the message or text to be authenticated.
* @throws java.security.NoSuchAlgorithmException
*
* @throws java.security.InvalidKeyException
*
*/
private byte[] hmac_sha1(String crypto, byte[] keyBytes, byte[] text) {
byte[] value;
try {
Mac hmac = Mac.getInstance(crypto);
SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
hmac.init(macKey);
value = hmac.doFinal(text);
} catch (Exception e) {
throw new RuntimeException(e);
}
return value;
}
/**
* This method converts HEX string to Byte[]
*
* @param hex the HEX string
* @return A byte array
*/
private byte[] hexStr2Bytes(String hex) {
// Adding one byte to get the right conversion
// values starting with "0" can be converted
byte[] bArray = new BigInteger("10" + hex, 16).toByteArray();
// Copy all the REAL bytes, not the "first"
byte[] ret = new byte[bArray.length - 1];
for (int i = 0; i < ret.length; i++)
ret[i] = bArray[i + 1];
return ret;
}
private class Clock {
private final int interval;
private Calendar calendar;
public Clock(int interval) {
this.interval = interval;
}
public long getCurrentInterval() {
Calendar currentCalendar = this.calendar;
if (currentCalendar == null) {
currentCalendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
}
return (currentCalendar.getTimeInMillis() / 1000) / this.interval;
}
public void setCalendar(Calendar calendar) {
this.calendar = calendar;
}
}
}

View file

@ -0,0 +1,275 @@
package org.keycloak.models.jpa;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.ApplicationEntity;
import org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity;
import org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ApplicationAdapter implements ApplicationModel {
protected EntityManager em;
protected ApplicationEntity application;
public ApplicationAdapter(EntityManager em, ApplicationEntity application) {
this.em = em;
this.application = application;
}
@Override
public void updateApplication() {
em.flush();
}
@Override
public UserModel getApplicationUser() {
return new UserAdapter(application.getApplicationUser());
}
@Override
public String getId() {
return application.getId();
}
@Override
public String getName() {
return application.getName();
}
@Override
public void setName(String name) {
application.setName(name);
}
@Override
public boolean isEnabled() {
return application.isEnabled();
}
@Override
public void setEnabled(boolean enabled) {
application.setEnabled(enabled);
}
@Override
public boolean isSurrogateAuthRequired() {
return application.isSurrogateAuthRequired();
}
@Override
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
application.setSurrogateAuthRequired(surrogateAuthRequired);
}
@Override
public String getManagementUrl() {
return application.getManagementUrl();
}
@Override
public void setManagementUrl(String url) {
application.setManagementUrl(url);
}
@Override
public String getBaseUrl() {
return null;
}
@Override
public void setBaseUrl(String url) {
}
@Override
public RoleModel getRole(String name) {
Collection<RoleEntity> roles = application.getRoles();
if (roles == null) return null;
for (RoleEntity role : roles) {
if (role.getName().equals(name)) {
return new RoleAdapter(role);
}
}
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public RoleModel addRole(String name) {
RoleModel role = getRole(name);
if (role != null) return role;
RoleEntity entity = new RoleEntity();
entity.setName(name);
em.persist(entity);
application.getRoles().add(entity);
em.flush();
return new RoleAdapter(entity);
}
@Override
public List<RoleModel> getRoles() {
ArrayList<RoleModel> list = new ArrayList<RoleModel>();
Collection<RoleEntity> roles = application.getRoles();
if (roles == null) return list;
for (RoleEntity entity : roles) {
list.add(new RoleAdapter(entity));
}
return list;
}
@Override
public RoleModel getRoleById(String id) {
RoleEntity entity = em.find(RoleEntity.class, id);
if (entity == null) return null;
return new RoleAdapter(entity);
}
@Override
public boolean hasRole(UserModel user, RoleModel role) {
TypedQuery<ApplicationUserRoleMappingEntity> query = getApplicationUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
return query.getResultList().size() > 0;
}
protected TypedQuery<ApplicationUserRoleMappingEntity> getApplicationUserRoleMappingEntityTypedQuery(UserAdapter user, RoleAdapter role) {
TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userHasApplicationRole", ApplicationUserRoleMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("role", ((RoleAdapter)role).getRole());
query.setParameter("application", application);
return query;
}
@Override
public void grantRole(UserModel user, RoleModel role) {
if (hasRole(user, role)) return;
ApplicationUserRoleMappingEntity entity = new ApplicationUserRoleMappingEntity();
entity.setApplication(application);
entity.setUser(((UserAdapter) user).getUser());
entity.setRole(((RoleAdapter)role).getRole());
em.persist(entity);
em.flush();
}
@Override
public List<RoleModel> getRoleMappings(UserModel user) {
TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userApplicationMappings", ApplicationUserRoleMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("application", application);
List<ApplicationUserRoleMappingEntity> entities = query.getResultList();
List<RoleModel> roles = new ArrayList<RoleModel>();
for (ApplicationUserRoleMappingEntity entity : entities) {
roles.add(new RoleAdapter(entity.getRole()));
}
return roles;
}
@Override
public Set<String> getRoleMappingValues(UserModel user) {
TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userApplicationMappings", ApplicationUserRoleMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("application", application);
List<ApplicationUserRoleMappingEntity> entities = query.getResultList();
Set<String> roles = new HashSet<String>();
for (ApplicationUserRoleMappingEntity entity : entities) {
roles.add(entity.getRole().getName());
}
return roles;
}
@Override
public void deleteRoleMapping(UserModel user, RoleModel role) {
TypedQuery<ApplicationUserRoleMappingEntity> query = getApplicationUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
List<ApplicationUserRoleMappingEntity> results = query.getResultList();
if (results.size() == 0) return;
for (ApplicationUserRoleMappingEntity entity : results) {
em.remove(entity);
}
}
@Override
public boolean hasRole(UserModel user, String roleName) {
RoleModel role = getRole(roleName);
if (role == null) return false;
return hasRole(user, role);
}
@Override
public void addScopeMapping(UserModel agent, String roleName) {
RoleModel role = getRole(roleName);
if (role == null) throw new RuntimeException("role does not exist");
addScopeMapping(agent, role);
}
@Override
public Set<String> getScopeMappingValues(UserModel agent) {
TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userApplicationScopeMappings", ApplicationScopeMappingEntity.class);
query.setParameter("user", ((UserAdapter)agent).getUser());
query.setParameter("application", application);
List<ApplicationScopeMappingEntity> entities = query.getResultList();
Set<String> roles = new HashSet<String>();
for (ApplicationScopeMappingEntity entity : entities) {
roles.add(entity.getRole().getName());
}
return roles;
}
@Override
public List<RoleModel> getScopeMappings(UserModel agent) {
TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userApplicationScopeMappings", ApplicationScopeMappingEntity.class);
query.setParameter("user", ((UserAdapter)agent).getUser());
query.setParameter("application", application);
List<ApplicationScopeMappingEntity> entities = query.getResultList();
List<RoleModel> roles = new ArrayList<RoleModel>();
for (ApplicationScopeMappingEntity entity : entities) {
roles.add(new RoleAdapter(entity.getRole()));
}
return roles;
}
@Override
public void addScopeMapping(UserModel agent, RoleModel role) {
if (hasScope(agent, role)) return;
ApplicationScopeMappingEntity entity = new ApplicationScopeMappingEntity();
entity.setApplication(application);
entity.setUser(((UserAdapter) agent).getUser());
entity.setRole(((RoleAdapter)role).getRole());
em.persist(entity);
em.flush();
}
@Override
public void deleteScopeMapping(UserModel user, RoleModel role) {
TypedQuery<ApplicationScopeMappingEntity> query = getApplicationScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
List<ApplicationScopeMappingEntity> results = query.getResultList();
if (results.size() == 0) return;
for (ApplicationScopeMappingEntity entity : results) {
em.remove(entity);
}
}
public boolean hasScope(UserModel user, RoleModel role) {
TypedQuery<ApplicationScopeMappingEntity> query = getApplicationScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
return query.getResultList().size() > 0;
}
protected TypedQuery<ApplicationScopeMappingEntity> getApplicationScopeMappingQuery(UserAdapter user, RoleAdapter role) {
TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userHasApplicationScope", ApplicationScopeMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("role", ((RoleAdapter)role).getRole());
query.setParameter("application", application);
return query;
}
}

View file

@ -0,0 +1,74 @@
package org.keycloak.models.jpa;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.RealmEntity;
import org.keycloak.models.utils.KeycloakSessionUtils;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaKeycloakSession implements KeycloakSession {
protected EntityManager em;
public JpaKeycloakSession(EntityManager em) {
this.em = em;
}
@Override
public KeycloakTransaction getTransaction() {
return new JpaKeycloakTransaction(em);
}
@Override
public RealmModel createRealm(String name) {
return createRealm(KeycloakSessionUtils.generateId(), name);
}
@Override
public RealmModel createRealm(String id, String name) {
RealmEntity realm = new RealmEntity();
realm.setName(name);
realm.setId(id);
em.persist(realm);
em.flush();
return new RealmAdapter(em, realm);
}
@Override
public RealmModel getRealm(String id) {
RealmEntity realm = em.find(RealmEntity.class, id);
if (realm == null) return null;
return new RealmAdapter(em, realm);
}
@Override
public List<RealmModel> getRealms(UserModel admin) {
TypedQuery<RealmEntity> query = em.createQuery("select r from RealmEntity r", RealmEntity.class);
List<RealmEntity> entities = query.getResultList();
List<RealmModel> realms = new ArrayList<RealmModel>();
for (RealmEntity entity : entities) {
realms.add(new RealmAdapter(em, entity));
}
return realms;
}
@Override
public void deleteRealm(RealmModel realm) {
throw new RuntimeException("Not Implemented Yet");
}
@Override
public void close() {
if (em.getTransaction().isActive()) em.getTransaction().rollback();
if (em.isOpen()) em.close();
}
}

View file

@ -0,0 +1,28 @@
package org.keycloak.models.jpa;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import javax.persistence.EntityManagerFactory;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaKeycloakSessionFactory implements KeycloakSessionFactory {
protected EntityManagerFactory factory;
public JpaKeycloakSessionFactory(EntityManagerFactory factory) {
this.factory = factory;
}
@Override
public KeycloakSession createSession() {
return new JpaKeycloakSession(factory.createEntityManager());
}
@Override
public void close() {
factory.close();
}
}

View file

@ -0,0 +1,48 @@
package org.keycloak.models.jpa;
import org.keycloak.models.KeycloakTransaction;
import javax.persistence.EntityManager;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaKeycloakTransaction implements KeycloakTransaction {
protected EntityManager em;
public JpaKeycloakTransaction(EntityManager em) {
this.em = em;
}
@Override
public void begin() {
em.getTransaction().begin();
}
@Override
public void commit() {
em.getTransaction().commit();
}
@Override
public void rollback() {
em.getTransaction().rollback();
}
@Override
public void setRollbackOnly() {
em.getTransaction().setRollbackOnly();
}
@Override
public boolean getRollbackOnly() {
return em.getTransaction().getRollbackOnly();
}
@Override
public boolean isActive() {
return em.getTransaction().isActive();
}
}

View file

@ -0,0 +1,20 @@
package org.keycloak.models.jpa;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ModelProvider;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaModelProvider implements ModelProvider {
@Override
public KeycloakSessionFactory createFactory() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store");
return new JpaKeycloakSessionFactory(emf);
}
}

View file

@ -0,0 +1,32 @@
package org.keycloak.models.jpa;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.OAuthClientEntity;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class OAuthClientAdapter implements OAuthClientModel {
protected OAuthClientEntity entity;
public OAuthClientAdapter(OAuthClientEntity entity) {
this.entity = entity;
}
public OAuthClientEntity getEntity() {
return entity;
}
@Override
public String getId() {
return entity.getId();
}
@Override
public UserModel getOAuthAgent() {
return new UserAdapter(entity.getAgent());
}
}

View file

@ -0,0 +1,954 @@
package org.keycloak.models.jpa;
import org.bouncycastle.openssl.PEMWriter;
import org.keycloak.PemUtils;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.ApplicationEntity;
import org.keycloak.models.jpa.entities.CredentialEntity;
import org.keycloak.models.jpa.entities.OAuthClientEntity;
import org.keycloak.models.jpa.entities.RealmEntity;
import org.keycloak.models.jpa.entities.RealmScopeMappingEntity;
import org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity;
import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.jpa.entities.SocialLinkEntity;
import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.utils.SHAPasswordEncoder;
import org.keycloak.models.utils.TimeBasedOTP;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.io.IOException;
import java.io.StringWriter;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmAdapter implements RealmModel {
protected RealmEntity realm;
protected EntityManager em;
protected volatile transient PublicKey publicKey;
protected volatile transient PrivateKey privateKey;
public RealmAdapter(EntityManager em, RealmEntity realm) {
this.em = em;
this.realm = realm;
}
@Override
public String getId() {
return realm.getId();
}
@Override
public String getName() {
return realm.getName();
}
@Override
public void setName(String name) {
realm.setName(name);
em.flush();
}
@Override
public boolean isEnabled() {
return realm.isEnabled();
}
@Override
public void setEnabled(boolean enabled) {
realm.setEnabled(enabled);
em.flush();
}
@Override
public boolean isSslNotRequired() {
return realm.isSslNotRequired();
}
@Override
public void setSslNotRequired(boolean sslNotRequired) {
realm.setSslNotRequired(sslNotRequired);
em.flush();
}
@Override
public boolean isCookieLoginAllowed() {
return realm.isCookieLoginAllowed();
}
@Override
public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
realm.setCookieLoginAllowed(cookieLoginAllowed);
em.flush();
}
@Override
public boolean isRegistrationAllowed() {
return realm.isRegistrationAllowed();
}
@Override
public void setRegistrationAllowed(boolean registrationAllowed) {
realm.setRegistrationAllowed(registrationAllowed);
em.flush();
}
@Override
public boolean isVerifyEmail() {
return realm.isVerifyEmail();
}
@Override
public void setVerifyEmail(boolean verifyEmail) {
realm.setVerifyEmail(verifyEmail);
em.flush();
}
@Override
public boolean isResetPasswordAllowed() {
return realm.isResetPasswordAllowed();
}
@Override
public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
realm.setResetPasswordAllowed(resetPasswordAllowed);
em.flush();
}
@Override
public int getTokenLifespan() {
return realm.getTokenLifespan();
}
@Override
public void setTokenLifespan(int tokenLifespan) {
realm.setTokenLifespan(tokenLifespan);
em.flush();
}
@Override
public int getAccessCodeLifespan() {
return realm.getAccessCodeLifespan();
}
@Override
public void setAccessCodeLifespan(int accessCodeLifespan) {
realm.setAccessCodeLifespan(accessCodeLifespan);
em.flush();
}
@Override
public int getAccessCodeLifespanUserAction() {
return realm.getAccessCodeLifespanUserAction();
}
@Override
public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
em.flush();
}
@Override
public String getPublicKeyPem() {
return realm.getPublicKeyPem();
}
@Override
public void setPublicKeyPem(String publicKeyPem) {
realm.setPublicKeyPem(publicKeyPem);
em.flush();
}
@Override
public String getPrivateKeyPem() {
return realm.getPrivateKeyPem();
}
@Override
public void setPrivateKeyPem(String privateKeyPem) {
realm.setPrivateKeyPem(privateKeyPem);
em.flush();
}
@Override
public PublicKey getPublicKey() {
if (publicKey != null) return publicKey;
String pem = getPublicKeyPem();
if (pem != null) {
try {
publicKey = PemUtils.decodePublicKey(pem);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return publicKey;
}
@Override
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);
}
String s = writer.toString();
setPublicKeyPem(PemUtils.removeBeginEnd(s));
}
@Override
public PrivateKey getPrivateKey() {
if (privateKey != null) return privateKey;
String pem = getPrivateKeyPem();
if (pem != null) {
try {
privateKey = PemUtils.decodePrivateKey(pem);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return privateKey;
}
@Override
public void setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
StringWriter writer = new StringWriter();
PEMWriter pemWriter = new PEMWriter(writer);
try {
pemWriter.writeObject(privateKey);
pemWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
String s = writer.toString();
setPrivateKeyPem(PemUtils.removeBeginEnd(s));
}
protected RequiredCredentialModel initRequiredCredentialModel(String type) {
RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
if (model == null) {
throw new RuntimeException("Unknown credential type " + type);
}
return model;
}
@Override
public void addRequiredCredential(String type) {
RequiredCredentialModel model = initRequiredCredentialModel(type);
addRequiredCredential(model);
em.flush();
}
public void addRequiredCredential(RequiredCredentialModel model) {
RequiredCredentialEntity entity = new RequiredCredentialEntity();
entity.setInput(model.isInput());
entity.setSecret(model.isSecret());
entity.setType(model.getType());
entity.setFormLabel(model.getFormLabel());
em.persist(entity);
realm.getRequiredCredentials().add(entity);
em.flush();
}
@Override
public void updateRequiredCredentials(Set<String> creds) {
Collection<RequiredCredentialEntity> relationships = realm.getRequiredCredentials();
if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
Set<String> already = new HashSet<String>();
List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
for (RequiredCredentialEntity rel : relationships) {
if (!creds.contains(rel.getType())) {
remove.add(rel);
} else {
already.add(rel.getType());
}
}
for (RequiredCredentialEntity entity : remove) {
relationships.remove(entity);
em.remove(entity);
}
for (String cred : creds) {
if (!already.contains(cred)) {
addRequiredCredential(cred);
}
}
em.flush();
}
@Override
public List<RequiredCredentialModel> getRequiredCredentials() {
List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
if (entities == null) return requiredCredentialModels;
for (RequiredCredentialEntity entity : entities) {
RequiredCredentialModel model = new RequiredCredentialModel();
model.setFormLabel(entity.getFormLabel());
model.setType(entity.getType());
model.setSecret(entity.isSecret());
model.setInput(entity.isInput());
requiredCredentialModels.add(model);
}
return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<RequiredCredentialModel> getRequiredApplicationCredentials() {
List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
Collection<RequiredCredentialEntity> entities = realm.getRequiredApplicationCredentials();
if (entities == null) return requiredCredentialModels;
for (RequiredCredentialEntity entity : entities) {
RequiredCredentialModel model = new RequiredCredentialModel();
model.setFormLabel(entity.getFormLabel());
model.setType(entity.getType());
model.setSecret(entity.isSecret());
model.setInput(entity.isInput());
requiredCredentialModels.add(model);
}
return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<RequiredCredentialModel> getRequiredOAuthClientCredentials() {
List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
Collection<RequiredCredentialEntity> entities = realm.getRequiredOAuthClientCredentials();
if (entities == null) return requiredCredentialModels;
for (RequiredCredentialEntity entity : entities) {
RequiredCredentialModel model = new RequiredCredentialModel();
model.setFormLabel(entity.getFormLabel());
model.setType(entity.getType());
model.setSecret(entity.isSecret());
model.setInput(entity.isInput());
requiredCredentialModels.add(model);
}
return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates.
}
public void addRequiredOAuthClientCredential(RequiredCredentialModel model) {
RequiredCredentialEntity entity = new RequiredCredentialEntity();
entity.setInput(model.isInput());
entity.setSecret(model.isSecret());
entity.setType(model.getType());
entity.setFormLabel(model.getFormLabel());
em.persist(entity);
realm.getRequiredOAuthClientCredentials().add(entity);
em.flush();
}
@Override
public void addRequiredOAuthClientCredential(String type) {
RequiredCredentialModel model = initRequiredCredentialModel(type);
addRequiredOAuthClientCredential(model);
em.flush();
}
public void addRequiredResourceCredential(RequiredCredentialModel model) {
RequiredCredentialEntity entity = new RequiredCredentialEntity();
entity.setInput(model.isInput());
entity.setSecret(model.isSecret());
entity.setType(model.getType());
entity.setFormLabel(model.getFormLabel());
em.persist(entity);
realm.getRequiredApplicationCredentials().add(entity);
em.flush();
}
@Override
public void addRequiredResourceCredential(String type) {
RequiredCredentialModel model = initRequiredCredentialModel(type);
addRequiredResourceCredential(model);
em.flush();
}
@Override
public void updateRequiredOAuthClientCredentials(Set<String> creds) {
Collection<RequiredCredentialEntity> relationships = realm.getRequiredOAuthClientCredentials();
if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
Set<String> already = new HashSet<String>();
List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
for (RequiredCredentialEntity rel : relationships) {
if (!creds.contains(rel.getType())) {
remove.add(rel);
} else {
already.add(rel.getType());
}
}
for (RequiredCredentialEntity entity : remove) {
relationships.remove(entity);
em.remove(entity);
}
for (String cred : creds) {
if (!already.contains(cred)) {
addRequiredOAuthClientCredential(cred);
}
}
em.flush();
}
@Override
public void updateRequiredApplicationCredentials(Set<String> creds) {
Collection<RequiredCredentialEntity> relationships = realm.getRequiredApplicationCredentials();
if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
Set<String> already = new HashSet<String>();
List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
for (RequiredCredentialEntity rel : relationships) {
if (!creds.contains(rel.getType())) {
remove.add(rel);
} else {
already.add(rel.getType());
}
}
for (RequiredCredentialEntity entity : remove) {
relationships.remove(entity);
em.remove(entity);
}
for (String cred : creds) {
if (!already.contains(cred)) {
addRequiredResourceCredential(cred);
}
}
em.flush();
}
@Override
public UserModel getUser(String name) {
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
query.setParameter("loginName", name);
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
if (results.size() == 0) return null;
return new UserAdapter(results.get(0));
}
@Override
public UserModel addUser(String username) {
UserEntity entity = new UserEntity();
entity.setLoginName(username);
entity.setRealm(realm);
em.persist(entity);
em.flush();
return new UserAdapter(entity);
}
@Override
public List<RoleModel> getDefaultRoles() {
Collection<RoleEntity> entities = realm.getDefaultRoles();
List<RoleModel> roles = new ArrayList<RoleModel>();
if (entities == null) return roles;
for (RoleEntity entity : entities) {
roles.add(new RoleAdapter(entity));
}
return roles;
}
@Override
public void addDefaultRole(String name) {
RoleModel role = getRole(name);
if (role == null) {
role = addRole(name);
}
Collection<RoleEntity> entities = realm.getDefaultRoles();
for (RoleEntity entity : entities) {
if (entity.getId().equals(role.getId())) {
return;
}
}
entities.add(((RoleAdapter) role).getRole());
em.flush();
}
public static boolean contains(String str, String[] array) {
for (String s : array) {
if (str.equals(s)) return true;
}
return false;
}
@Override
public void updateDefaultRoles(String[] defaultRoles) {
Collection<RoleEntity> entities = realm.getDefaultRoles();
Set<String> already = new HashSet<String>();
List<RoleEntity> remove = new ArrayList<RoleEntity>();
for (RoleEntity rel : entities) {
if (!contains(rel.getName(), defaultRoles)) {
remove.add(rel);
} else {
already.add(rel.getName());
}
}
for (RoleEntity entity : remove) {
entities.remove(entity);
em.remove(entity);
}
for (String roleName : defaultRoles) {
if (!already.contains(roleName)) {
addDefaultRole(roleName);
}
}
em.flush();
}
@Override
public Map<String, ApplicationModel> getApplicationNameMap() {
Map<String, ApplicationModel> map = new HashMap<String, ApplicationModel>();
for (ApplicationModel app : getApplications()) {
map.put(app.getName(), app);
}
return map; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public List<ApplicationModel> getApplications() {
List<ApplicationModel> list = new ArrayList<ApplicationModel>();
if (realm.getApplications() == null) return list;
for (ApplicationEntity entity : realm.getApplications()) {
list.add(new ApplicationAdapter(em, entity));
}
return list;
}
@Override
public ApplicationModel addApplication(String name) {
ApplicationEntity applicationData = new ApplicationEntity();
UserEntity user = new UserEntity();
user.setLoginName(name);
user.setRealm(realm);
user.setEnabled(true);
em.persist(user);
applicationData.setApplicationUser(user);
applicationData.setName(name);
realm.getApplications().add(applicationData);
em.persist(applicationData);
em.flush();
ApplicationModel resource = new ApplicationAdapter(em, applicationData);
resource.addRole("*");
resource.addScopeMapping(new UserAdapter(user), "*");
em.flush();
return resource;
}
@Override
public ApplicationModel getApplicationById(String id) {
ApplicationEntity app = em.find(ApplicationEntity.class, id);
if (app == null) return null;
return new ApplicationAdapter(em, app);
}
@Override
public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
TypedQuery<UserEntity> query = em.createNamedQuery("findUserByLinkAndRealm", UserEntity.class);
query.setParameter("realm", realm);
query.setParameter("socialProvider", socialLink.getSocialProvider());
query.setParameter("socialUsername", socialLink.getSocialUsername());
List<UserEntity> results = query.getResultList();
if (results.isEmpty()) {
return null;
} else if (results.size() > 1) {
throw new IllegalStateException("More results found for socialProvider=" + socialLink.getSocialProvider() +
", socialUsername=" + socialLink.getSocialUsername() + ", results=" + results);
} else {
UserEntity user = results.get(0);
return new UserAdapter(user);
}
}
@Override
public Set<SocialLinkModel> getSocialLinks(UserModel user) {
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByUser", SocialLinkEntity.class);
query.setParameter("user", ((UserAdapter) user).getUser());
List<SocialLinkEntity> results = query.getResultList();
Set<SocialLinkModel> set = new HashSet<SocialLinkModel>();
for (SocialLinkEntity entity : results) {
set.add(new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUsername()));
}
return set;
}
@Override
public void addSocialLink(UserModel user, SocialLinkModel socialLink) {
SocialLinkEntity entity = new SocialLinkEntity();
entity.setRealm(realm);
entity.setSocialProvider(socialLink.getSocialProvider());
entity.setSocialUsername(socialLink.getSocialUsername());
entity.setUser(((UserAdapter) user).getUser());
em.persist(entity);
em.flush();
}
@Override
public void removeSocialLink(UserModel user, SocialLinkModel socialLink) {
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByAll", SocialLinkEntity.class);
query.setParameter("realm", realm);
query.setParameter("user", ((UserAdapter) user).getUser());
query.setParameter("socialProvider", socialLink.getSocialProvider());
query.setParameter("socialUsername", socialLink.getSocialUsername());
List<SocialLinkEntity> results = query.getResultList();
for (SocialLinkEntity entity : results) em.remove(entity);
em.flush();
}
@Override
public boolean isSocial() {
return realm.isSocial();
}
@Override
public void setSocial(boolean social) {
realm.setSocial(social);
em.flush();
}
@Override
public boolean isAutomaticRegistrationAfterSocialLogin() {
return realm.isAutomaticRegistrationAfterSocialLogin();
}
@Override
public void setAutomaticRegistrationAfterSocialLogin(boolean automaticRegistrationAfterSocialLogin) {
realm.setAutomaticRegistrationAfterSocialLogin(automaticRegistrationAfterSocialLogin);
em.flush();
}
@Override
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
StringBuilder builder = new StringBuilder("select u from UserEntity u");
boolean first = true;
for (Map.Entry<String, String> entry : attributes.entrySet()) {
String attribute = null;
if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
attribute = "loginName";
} else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
attribute = "firstName";
} else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
attribute = "lastName";
} else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
attribute = "email";
}
if (attribute == null) continue;
if (first) {
first = false;
builder.append(" where ");
} else {
builder.append(" and ");
}
builder.append(attribute).append("='").append(entry.getValue()).append("'");
}
TypedQuery<UserEntity> query = em.createQuery(builder.toString(), UserEntity.class);
List<UserEntity> results = query.getResultList();
List<UserModel> users = new ArrayList<UserModel>();
for (UserEntity entity : results) users.add(new UserAdapter(entity));
return users;
}
@Override
public OAuthClientModel addOAuthClient(String name) {
OAuthClientEntity data = new OAuthClientEntity();
UserEntity user = new UserEntity();
user.setLoginName(name);
user.setRealm(realm);
user.setEnabled(true);
em.persist(user);
data.setAgent(user);
data.setName(name);
data.setRealm(realm);
em.persist(data);
em.flush();
return new OAuthClientAdapter(data);
}
@Override
public OAuthClientModel getOAuthClient(String name) {
TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByUser", OAuthClientEntity.class);
query.setParameter("name", name);
query.setParameter("realm", realm);
List<OAuthClientEntity> entities = query.getResultList();
if (entities.size() == 0) return null;
return new OAuthClientAdapter(entities.get(0));
}
@Override
public List<OAuthClientModel> getOAuthClients() {
TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByRealm", OAuthClientEntity.class);
query.setParameter("realm", realm);
List<OAuthClientEntity> entities = query.getResultList();
List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
for (OAuthClientEntity entity : entities) list.add(new OAuthClientAdapter(entity));
return list;
}
@Override
public Map<String, String> getSmtpConfig() {
return realm.getSmtpConfig();
}
@Override
public void setSmtpConfig(Map<String, String> smtpConfig) {
realm.setSmtpConfig(smtpConfig);
em.flush();
}
@Override
public Map<String, String> getSocialConfig() {
return realm.getSocialConfig();
}
@Override
public void setSocialConfig(Map<String, String> socialConfig) {
realm.setSocialConfig(socialConfig);
em.flush();
}
@Override
public RoleModel getRole(String name) {
Collection<RoleEntity> roles = realm.getRoles();
if (roles == null) return null;
for (RoleEntity role : roles) {
if (role.getName().equals(name)) {
return new RoleAdapter(role);
}
}
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public RoleModel addRole(String name) {
RoleModel role = getRole(name);
if (role != null) return role;
RoleEntity entity = new RoleEntity();
entity.setName(name);
em.persist(entity);
realm.getRoles().add(entity);
em.flush();
return new RoleAdapter(entity);
}
@Override
public List<RoleModel> getRoles() {
ArrayList<RoleModel> list = new ArrayList<RoleModel>();
Collection<RoleEntity> roles = realm.getRoles();
if (roles == null) return list;
for (RoleEntity entity : roles) {
list.add(new RoleAdapter(entity));
}
return list;
}
@Override
public RoleModel getRoleById(String id) {
RoleEntity entity = em.find(RoleEntity.class, id);
if (entity == null) return null;
return new RoleAdapter(entity);
}
@Override
public boolean hasRole(UserModel user, RoleModel role) {
TypedQuery<RealmUserRoleMappingEntity> query = getRealmUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
return query.getResultList().size() > 0;
}
protected TypedQuery<RealmUserRoleMappingEntity> getRealmUserRoleMappingEntityTypedQuery(UserAdapter user, RoleAdapter role) {
TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userHasRealmRole", RealmUserRoleMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("role", ((RoleAdapter)role).getRole());
query.setParameter("realm", realm);
return query;
}
@Override
public void grantRole(UserModel user, RoleModel role) {
if (hasRole(user, role)) return;
RealmUserRoleMappingEntity entity = new RealmUserRoleMappingEntity();
entity.setRealm(realm);
entity.setUser(((UserAdapter) user).getUser());
entity.setRole(((RoleAdapter)role).getRole());
em.persist(entity);
em.flush();
}
@Override
public List<RoleModel> getRoleMappings(UserModel user) {
TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userRealmMappings", RealmUserRoleMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("realm", realm);
List<RealmUserRoleMappingEntity> entities = query.getResultList();
List<RoleModel> roles = new ArrayList<RoleModel>();
for (RealmUserRoleMappingEntity entity : entities) {
roles.add(new RoleAdapter(entity.getRole()));
}
return roles;
}
@Override
public Set<String> getRoleMappingValues(UserModel user) {
TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userRealmMappings", RealmUserRoleMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("realm", realm);
List<RealmUserRoleMappingEntity> entities = query.getResultList();
Set<String> roles = new HashSet<String>();
for (RealmUserRoleMappingEntity entity : entities) {
roles.add(entity.getRole().getName());
}
return roles;
}
@Override
public void deleteRoleMapping(UserModel user, RoleModel role) {
TypedQuery<RealmUserRoleMappingEntity> query = getRealmUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
List<RealmUserRoleMappingEntity> results = query.getResultList();
if (results.size() == 0) return;
for (RealmUserRoleMappingEntity entity : results) {
em.remove(entity);
}
em.flush();
}
@Override
public boolean hasRole(UserModel user, String roleName) {
RoleModel role = getRole(roleName);
if (role == null) return false;
return hasRole(user, role);
}
@Override
public void addScopeMapping(UserModel agent, String roleName) {
RoleModel role = getRole(roleName);
if (role == null) throw new RuntimeException("role does not exist");
addScopeMapping(agent, role);
em.flush();
}
@Override
public Set<String> getScopeMappingValues(UserModel agent) {
TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userRealmScopeMappings", RealmScopeMappingEntity.class);
query.setParameter("user", ((UserAdapter)agent).getUser());
query.setParameter("realm", realm);
List<RealmScopeMappingEntity> entities = query.getResultList();
Set<String> roles = new HashSet<String>();
for (RealmScopeMappingEntity entity : entities) {
roles.add(entity.getRole().getName());
}
return roles;
}
@Override
public List<RoleModel> getScopeMappings(UserModel agent) {
TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userRealmScopeMappings", RealmScopeMappingEntity.class);
query.setParameter("user", ((UserAdapter)agent).getUser());
query.setParameter("realm", realm);
List<RealmScopeMappingEntity> entities = query.getResultList();
List<RoleModel> roles = new ArrayList<RoleModel>();
for (RealmScopeMappingEntity entity : entities) {
roles.add(new RoleAdapter(entity.getRole()));
}
return roles;
}
@Override
public void addScopeMapping(UserModel agent, RoleModel role) {
if (hasScope(agent, role)) return;
RealmScopeMappingEntity entity = new RealmScopeMappingEntity();
entity.setRealm(realm);
entity.setUser(((UserAdapter) agent).getUser());
entity.setRole(((RoleAdapter)role).getRole());
em.persist(entity);
em.flush();
}
@Override
public void deleteScopeMapping(UserModel user, RoleModel role) {
TypedQuery<RealmScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
List<RealmScopeMappingEntity> results = query.getResultList();
if (results.size() == 0) return;
for (RealmScopeMappingEntity entity : results) {
em.remove(entity);
}
}
public boolean hasScope(UserModel user, RoleModel role) {
TypedQuery<RealmScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
return query.getResultList().size() > 0;
}
protected TypedQuery<RealmScopeMappingEntity> getRealmScopeMappingQuery(UserAdapter user, RoleAdapter role) {
TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userHasRealmScope", RealmScopeMappingEntity.class);
query.setParameter("user", ((UserAdapter)user).getUser());
query.setParameter("role", ((RoleAdapter)role).getRole());
query.setParameter("realm", realm);
return query;
}
@Override
public boolean validatePassword(UserModel user, String password) {
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
return new SHAPasswordEncoder(512).verify(password, cred.getValue());
}
}
return false;
}
@Override
public boolean validateTOTP(UserModel user, String password, String token) {
if (!validatePassword(user, password)) return false;
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
if (cred.getType().equals(UserCredentialModel.TOTP)) {
return new TimeBasedOTP().validate(token, cred.getValue().getBytes());
}
}
return false;
}
@Override
public void updateCredential(UserModel user, UserCredentialModel cred) {
CredentialEntity credentialEntity = null;
UserEntity userEntity = ((UserAdapter) user).getUser();
for (CredentialEntity entity : userEntity.getCredentials()) {
if (entity.getType().equals(cred.getType())) {
credentialEntity = entity;
}
}
if (credentialEntity == null) {
credentialEntity = new CredentialEntity();
credentialEntity.setType(cred.getType());
credentialEntity.setDevice(cred.getDevice());
credentialEntity.setUser(userEntity);
em.persist(credentialEntity);
userEntity.getCredentials().add(credentialEntity);
}
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
credentialEntity.setValue(new SHAPasswordEncoder(512).encode(cred.getValue()));
} else {
credentialEntity.setValue(cred.getValue());
}
credentialEntity.setDevice(cred.getDevice());
em.flush();
}
}

View file

@ -0,0 +1,49 @@
package org.keycloak.models.jpa;
import org.keycloak.models.RoleModel;
import org.keycloak.models.jpa.entities.RoleEntity;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RoleAdapter implements RoleModel {
protected RoleEntity role;
public RoleAdapter(RoleEntity role) {
this.role = role;
}
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
@Override
public String getName() {
return role.getName();
}
@Override
public String getDescription() {
return role.getDescription();
}
@Override
public void setDescription(String description) {
role.setDescription(description);
}
@Override
public String getId() {
return role.getId();
}
@Override
public void setName(String name) {
role.setName(name);
}
}

View file

@ -0,0 +1,185 @@
package org.keycloak.models.jpa;
import org.keycloak.models.UserModel;
import org.keycloak.models.jpa.entities.UserEntity;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAdapter implements UserModel {
protected UserEntity user;
public UserAdapter(UserEntity user) {
this.user = user;
}
public UserEntity getUser() {
return user;
}
@Override
public String getLoginName() {
return user.getLoginName();
}
@Override
public boolean isEnabled() {
return user.isEnabled();
}
@Override
public boolean isTotp() {
return user.isTotp();
}
@Override
public void setEnabled(boolean enabled) {
user.setEnabled(enabled);
}
@Override
public void setAttribute(String name, String value) {
Map<String, String> attributes = user.getAttributes();
if (attributes == null) {
attributes = new HashMap<String, String>();
}
attributes.put(name, value);
user.setAttributes(attributes);
}
@Override
public void removeAttribute(String name) {
Map<String, String> attributes = user.getAttributes();
if (attributes == null) {
attributes = new HashMap<String, String>();
}
attributes.remove(name);
user.setAttributes(attributes);
}
@Override
public String getAttribute(String name) {
if (user.getAttributes() == null) return null;
return user.getAttributes().get(name);
}
@Override
public Map<String, String> getAttributes() {
Map<String, String> result = new HashMap<String, String>();
result.putAll(user.getAttributes());
return result;
}
@Override
public Set<RequiredAction> getRequiredActions() {
Set<RequiredAction> result = new HashSet<RequiredAction>();
result.addAll(user.getRequiredActions());
return result;
}
@Override
public void addRequiredAction(RequiredAction action) {
user.getRequiredActions().add(action);
}
@Override
public void removeRequiredAction(RequiredAction action) {
user.getRequiredActions().remove(action);
}
@Override
public Set<String> getWebOrigins() {
Set<String> result = new HashSet<String>();
result.addAll(user.getWebOrigins());
return result;
}
@Override
public void setWebOrigins(Set<String> webOrigins) {
user.setWebOrigins(webOrigins);
}
@Override
public void addWebOrigin(String webOrigin) {
user.getWebOrigins().add(webOrigin);
}
@Override
public void removeWebOrigin(String webOrigin) {
user.getWebOrigins().remove(webOrigin);
}
@Override
public Set<String> getRedirectUris() {
Set<String> result = new HashSet<String>();
result.addAll(user.getRedirectUris());
return result;
}
@Override
public void setRedirectUris(Set<String> redirectUris) {
user.setRedirectUris(redirectUris);
}
@Override
public void addRedirectUri(String redirectUri) {
user.getRedirectUris().add(redirectUri);
}
@Override
public void removeRedirectUri(String redirectUri) {
user.getRedirectUris().remove(redirectUri);
}
@Override
public String getFirstName() {
return user.getFirstName();
}
@Override
public void setFirstName(String firstName) {
user.setFirstName(firstName);
}
@Override
public String getLastName() {
return user.getLastName();
}
@Override
public void setLastName(String lastName) {
user.setLastName(lastName);
}
@Override
public String getEmail() {
return user.getEmail();
}
@Override
public void setEmail(String email) {
user.setEmail(email);
}
@Override
public boolean isEmailVerified() {
return user.isEmailVerified();
}
@Override
public void setEmailVerified(boolean verified) {
user.setEmailVerified(verified);
}
@Override
public void setTotp(boolean totp) {
user.setTotp(totp);
}
}

View file

@ -1,6 +1,14 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.*;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import java.util.ArrayList;
import java.util.Collection;
/**
@ -8,37 +16,27 @@ import java.util.Collection;
* @version $Revision: 1 $
*/
@Entity
public class ResourceEntity {
public class ApplicationEntity {
@Id
@GeneratedValue
private String id;
private String resourceName;
private String name;
private boolean enabled;
private boolean surrogateAuthRequired;
private String managementUrl;
@ManyToOne
private UserEntity resourceUser;
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<RoleEntity> roles;
@OneToOne(fetch = FetchType.EAGER)
private UserEntity applicationUser;
@OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="APPLICATION_ROLES")
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public boolean isEnabled() {
return enabled;
}
@ -63,12 +61,12 @@ public class ResourceEntity {
this.managementUrl = managementUrl;
}
public UserEntity getResourceUser() {
return resourceUser;
public UserEntity getApplicationUser() {
return applicationUser;
}
public void setResourceUser(UserEntity resourceUser) {
this.resourceUser = resourceUser;
public void setApplicationUser(UserEntity applicationUser) {
this.applicationUser = applicationUser;
}
public Collection<RoleEntity> getRoles() {
@ -78,4 +76,12 @@ public class ResourceEntity {
public void setRoles(Collection<RoleEntity> roles) {
this.roles = roles;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View file

@ -0,0 +1,29 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="userHasApplicationScope", query="select m from ApplicationScopeMappingEntity m where m.user = :user and m.role = :role and m.application = :application"),
@NamedQuery(name="userApplicationScopeMappings", query="select m from ApplicationScopeMappingEntity m where m.user = :user and m.application = :application")
})
@Entity
public class ApplicationScopeMappingEntity extends UserRoleMappingEntity {
@ManyToOne
protected ApplicationEntity application;
public ApplicationEntity getApplication() {
return application;
}
public void setApplication(ApplicationEntity application) {
this.application = application;
}
}

View file

@ -0,0 +1,29 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="userHasApplicationRole", query="select m from ApplicationUserRoleMappingEntity m where m.user = :user and m.role = :role and m.application = :application"),
@NamedQuery(name="userApplicationMappings", query="select m from ApplicationUserRoleMappingEntity m where m.user = :user and m.application = :application")
})
@Entity
public class ApplicationUserRoleMappingEntity extends UserRoleMappingEntity {
@ManyToOne
protected ApplicationEntity application;
public ApplicationEntity getApplication() {
return application;
}
public void setApplication(ApplicationEntity application) {
this.application = application;
}
}

View file

@ -0,0 +1,69 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="credentialByUserAndType", query="select cred from CredentialEntity cred where cred.user = :user and cred.type = :type")
})
@Entity
public class CredentialEntity {
@Id
@GeneratedValue
protected String id;
protected String type;
protected String value;
protected String device;
@ManyToOne
protected UserEntity user;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDevice() {
return device;
}
public void setDevice(String device) {
this.device = device;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
}

View file

@ -0,0 +1,62 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="findOAuthClientByUser", query="select o from OAuthClientEntity o where o.agent.loginName=:name and o.realm = :realm"),
@NamedQuery(name="findOAuthClientByRealm", query="select o from OAuthClientEntity o where o.realm = :realm")
})
@Entity
public class OAuthClientEntity {
@Id
@GeneratedValue
private String id;
private String name;
@OneToOne(fetch = FetchType.EAGER)
private UserEntity agent;
@ManyToOne
protected RealmEntity realm;
public String getId() {
return id;
}
public UserEntity getAgent() {
return agent;
}
public void setAgent(UserEntity agent) {
this.agent = agent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
}

View file

@ -1,43 +1,272 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.*;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.MapKeyColumn;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class RealmEntity {
@Id
protected String id;
protected String realmName;
protected String name;
protected boolean enabled;
protected boolean sslNotRequired;
protected boolean cookieLoginAllowed;
protected boolean registrationAllowed;
protected boolean verifyEmail;
protected boolean resetPasswordAllowed;
protected boolean social;
protected boolean automaticRegistrationAfterSocialLogin;
protected int tokenLifespan;
protected int accessCodeLifespan;
protected int accessCodeLifespanUserAction;
@Column(length = 2048)
protected String publicKeyPem;
@Column(length = 2048)
protected String privateKeyPem;
protected String[] defaultRoles;
@Lob
protected HashMap<String, String> smtpConfig;
@Lob
protected HashMap<String, String> socialConfig;
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<RequiredCredentailEntity> requiredCredentials;
@JoinTable(name="USER_REQUIRED_CREDENTIALS")
Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<ResourceEntity> resources;
@JoinTable(name="APPLICATION_REQUIRED_CREDENTIALS")
Collection<RequiredCredentialEntity> requiredApplicationCredentials = new ArrayList<RequiredCredentialEntity>();
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="OAUTH_CLIENT_REQUIRED_CREDENTIALS")
Collection<RequiredCredentialEntity> requiredOAuthClientCredentials = new ArrayList<RequiredCredentialEntity>();
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<ApplicationEntity> applications = new ArrayList<ApplicationEntity>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<RoleEntity> roles;
@JoinTable(name="REALM_ROLES")
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> smtpConfig = new HashMap<String, String>();
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> socialConfig = new HashMap<String, String>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
@JoinTable(name="REALM_DEFAULT_ROLES")
Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isSslNotRequired() {
return sslNotRequired;
}
public void setSslNotRequired(boolean sslNotRequired) {
this.sslNotRequired = sslNotRequired;
}
public boolean isCookieLoginAllowed() {
return cookieLoginAllowed;
}
public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
this.cookieLoginAllowed = cookieLoginAllowed;
}
public boolean isRegistrationAllowed() {
return registrationAllowed;
}
public void setRegistrationAllowed(boolean registrationAllowed) {
this.registrationAllowed = registrationAllowed;
}
public boolean isVerifyEmail() {
return verifyEmail;
}
public void setVerifyEmail(boolean verifyEmail) {
this.verifyEmail = verifyEmail;
}
public boolean isResetPasswordAllowed() {
return resetPasswordAllowed;
}
public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
this.resetPasswordAllowed = resetPasswordAllowed;
}
public boolean isSocial() {
return social;
}
public void setSocial(boolean social) {
this.social = social;
}
public boolean isAutomaticRegistrationAfterSocialLogin() {
return automaticRegistrationAfterSocialLogin;
}
public void setAutomaticRegistrationAfterSocialLogin(boolean automaticRegistrationAfterSocialLogin) {
this.automaticRegistrationAfterSocialLogin = automaticRegistrationAfterSocialLogin;
}
public int getTokenLifespan() {
return tokenLifespan;
}
public void setTokenLifespan(int tokenLifespan) {
this.tokenLifespan = tokenLifespan;
}
public int getAccessCodeLifespan() {
return accessCodeLifespan;
}
public void setAccessCodeLifespan(int accessCodeLifespan) {
this.accessCodeLifespan = accessCodeLifespan;
}
public int getAccessCodeLifespanUserAction() {
return accessCodeLifespanUserAction;
}
public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
}
public String getPublicKeyPem() {
return publicKeyPem;
}
public void setPublicKeyPem(String publicKeyPem) {
this.publicKeyPem = publicKeyPem;
}
public String getPrivateKeyPem() {
return privateKeyPem;
}
public void setPrivateKeyPem(String privateKeyPem) {
this.privateKeyPem = privateKeyPem;
}
public Collection<RequiredCredentialEntity> getRequiredCredentials() {
return requiredCredentials;
}
public void setRequiredCredentials(Collection<RequiredCredentialEntity> requiredCredentials) {
this.requiredCredentials = requiredCredentials;
}
public Collection<RequiredCredentialEntity> getRequiredApplicationCredentials() {
return requiredApplicationCredentials;
}
public void setRequiredApplicationCredentials(Collection<RequiredCredentialEntity> requiredApplicationCredentials) {
this.requiredApplicationCredentials = requiredApplicationCredentials;
}
public Collection<RequiredCredentialEntity> getRequiredOAuthClientCredentials() {
return requiredOAuthClientCredentials;
}
public void setRequiredOAuthClientCredentials(Collection<RequiredCredentialEntity> requiredOAuthClientCredentials) {
this.requiredOAuthClientCredentials = requiredOAuthClientCredentials;
}
public Collection<ApplicationEntity> getApplications() {
return applications;
}
public void setApplications(Collection<ApplicationEntity> applications) {
this.applications = applications;
}
public Collection<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Collection<RoleEntity> roles) {
this.roles = roles;
}
public void addRole(RoleEntity role) {
if (roles == null) {
roles = new ArrayList<RoleEntity>();
}
roles.add(role);
}
public Map<String, String> getSmtpConfig() {
return smtpConfig;
}
public void setSmtpConfig(Map<String, String> smtpConfig) {
this.smtpConfig = smtpConfig;
}
public Map<String, String> getSocialConfig() {
return socialConfig;
}
public void setSocialConfig(Map<String, String> socialConfig) {
this.socialConfig = socialConfig;
}
public Collection<RoleEntity> getDefaultRoles() {
return defaultRoles;
}
public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
this.defaultRoles = defaultRoles;
}
}

View file

@ -0,0 +1,29 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="userHasRealmScope", query="select m from RealmScopeMappingEntity m where m.user = :user and m.role = :role and m.realm = :realm"),
@NamedQuery(name="userRealmScopeMappings", query="select m from RealmScopeMappingEntity m where m.user = :user and m.realm = :realm")
})
@Entity
public class RealmScopeMappingEntity extends UserRoleMappingEntity {
@ManyToOne
protected RealmEntity realm;
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
}

View file

@ -0,0 +1,29 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="userHasRealmRole", query="select m from RealmUserRoleMappingEntity m where m.user = :user and m.role = :role and m.realm = :realm"),
@NamedQuery(name="userRealmMappings", query="select m from RealmUserRoleMappingEntity m where m.user = :user and m.realm = :realm")
})
@Entity
public class RealmUserRoleMappingEntity extends UserRoleMappingEntity {
@ManyToOne
protected RealmEntity realm;
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
}

View file

@ -1,11 +0,0 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class RequiredCredentailEntity {
}

View file

@ -0,0 +1,61 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class RequiredCredentialEntity {
@Id
@GeneratedValue
protected String id;
protected String type;
protected boolean input;
protected boolean secret;
protected String formLabel;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isInput() {
return input;
}
public void setInput(boolean input) {
this.input = input;
}
public boolean isSecret() {
return secret;
}
public void setSecret(boolean secret) {
this.secret = secret;
}
public String getFormLabel() {
return formLabel;
}
public void setFormLabel(String formLabel) {
this.formLabel = formLabel;
}
}

View file

@ -1,46 +0,0 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class ScopeMappingEntity {
@Id
@GeneratedValue
private long id;
@ManyToOne
private UserEntity user;
@ManyToOne
private RoleEntity role;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
}

View file

@ -0,0 +1,73 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="findSocialLinkByUser", query="select link from SocialLinkEntity link where link.user = :user"),
@NamedQuery(name="findUserByLinkAndRealm", query="select link.user from SocialLinkEntity link where link.realm = :realm and link.socialProvider = :socialProvider and link.socialUsername = :socialUsername"),
@NamedQuery(name="findSocialLinkByAll", query="select link.user from SocialLinkEntity link where link.realm = :realm and link.socialProvider = :socialProvider and link.socialUsername = :socialUsername and link.user = :user")
})
@Entity
public class SocialLinkEntity {
@Id
@GeneratedValue
private long id;
@ManyToOne
private UserEntity user;
@ManyToOne
protected RealmEntity realm;
protected String socialProvider;
protected String socialUsername;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public String getSocialProvider() {
return socialProvider;
}
public void setSocialProvider(String socialProvider) {
this.socialProvider = socialProvider;
}
public String getSocialUsername() {
return socialUsername;
}
public void setSocialUsername(String socialUsername) {
this.socialUsername = socialUsername;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
}

View file

@ -1,20 +1,72 @@
package org.keycloak.models.jpa.entities;
import org.keycloak.models.UserModel;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@NamedQueries({
@NamedQuery(name="getRealmUserByLoginName", query="select u from UserEntity u where u.loginName = :loginName and u.realm = :realm"),
@NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realm = :realm"),
@NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realm = :realm"),
@NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realm = :realm")
})
@Entity
public class UserEntity {
@Id
@GeneratedValue
private String id;
protected String id;
private String loginName;
protected String loginName;
protected String firstName;
protected String lastName;
protected String email;
protected boolean enabled;
protected boolean totp;
protected boolean emailVerified;
@ManyToOne
protected RealmEntity realm;
@ElementCollection
@MapKeyColumn(name="name")
@Column(name="value")
@CollectionTable
protected Map<String, String> attributes = new HashMap<String, String>();
@ElementCollection
@CollectionTable
protected Set<UserModel.RequiredAction> requiredActions = new HashSet<UserModel.RequiredAction>();
@ElementCollection
@CollectionTable
protected Set<String> webOrigins = new HashSet<String>();
@ElementCollection
@CollectionTable
protected Set<String> redirectUris = new HashSet<String>();
@OneToMany
protected Collection<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
public String getId() {
return id;
@ -31,4 +83,100 @@ public class UserEntity {
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isTotp() {
return totp;
}
public void setTotp(boolean totp) {
this.totp = totp;
}
public boolean isEmailVerified() {
return emailVerified;
}
public void setEmailVerified(boolean emailVerified) {
this.emailVerified = emailVerified;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public Set<UserModel.RequiredAction> getRequiredActions() {
return requiredActions;
}
public void setRequiredActions(Set<UserModel.RequiredAction> requiredActions) {
this.requiredActions = requiredActions;
}
public Set<String> getWebOrigins() {
return webOrigins;
}
public void setWebOrigins(Set<String> webOrigins) {
this.webOrigins = webOrigins;
}
public Set<String> getRedirectUris() {
return redirectUris;
}
public void setRedirectUris(Set<String> redirectUris) {
this.redirectUris = redirectUris;
}
public RealmEntity getRealm() {
return realm;
}
public void setRealm(RealmEntity realm) {
this.realm = realm;
}
public Collection<CredentialEntity> getCredentials() {
return credentials;
}
public void setCredentials(Collection<CredentialEntity> credentials) {
this.credentials = credentials;
}
}

View file

@ -1,24 +1,23 @@
package org.keycloak.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class UserRoleMappingEntity {
@MappedSuperclass
public abstract class UserRoleMappingEntity {
@Id
@GeneratedValue
private long id;
protected long id;
@ManyToOne
private UserEntity user;
protected UserEntity user;
@ManyToOne
private RoleEntity role;
protected RoleEntity role;
public long getId() {
return id;

View file

@ -1,10 +1,9 @@
package org.keycloak.models.mongo.api;
import java.util.List;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
import org.picketlink.common.properties.Property;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>

View file

@ -3,8 +3,6 @@ package org.keycloak.models.mongo.api.types;
import java.util.HashMap;
import java.util.Map;
import org.picketlink.common.reflection.Reflections;
/**
* Registry of converters, which allow to convert application object to database objects. TypeConverter is main entry point to be used by application.
* Application can create instance of TypeConverter and then register required Converter objects.

View file

@ -1,12 +1,5 @@
package org.keycloak.models.mongo.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
@ -24,10 +17,10 @@ import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
import org.keycloak.models.mongo.api.types.Converter;
import org.keycloak.models.mongo.api.types.TypeConverter;
import org.keycloak.models.mongo.impl.types.EnumToStringConverter;
import org.keycloak.models.mongo.impl.types.ListConverter;
import org.keycloak.models.mongo.impl.types.BasicDBListConverter;
import org.keycloak.models.mongo.impl.types.BasicDBObjectConverter;
import org.keycloak.models.mongo.impl.types.EnumToStringConverter;
import org.keycloak.models.mongo.impl.types.ListConverter;
import org.keycloak.models.mongo.impl.types.NoSQLObjectConverter;
import org.keycloak.models.mongo.impl.types.SimpleConverter;
import org.keycloak.models.mongo.impl.types.StringToEnumConverter;
@ -35,6 +28,13 @@ import org.picketlink.common.properties.Property;
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
import org.picketlink.common.properties.query.PropertyQueries;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,13 +1,13 @@
package org.keycloak.models.mongo.impl;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import com.mongodb.BasicDBObject;
import org.bson.types.ObjectId;
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,14 +1,14 @@
package org.keycloak.models.mongo.impl;
import org.keycloak.models.mongo.api.NoSQLObject;
import org.picketlink.common.properties.Property;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.keycloak.models.mongo.api.NoSQLObject;
import org.picketlink.common.properties.Property;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,12 +1,12 @@
package org.keycloak.models.mongo.impl.types;
import java.util.ArrayList;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import org.keycloak.models.mongo.api.types.Converter;
import org.keycloak.models.mongo.api.types.TypeConverter;
import java.util.ArrayList;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,12 +1,12 @@
package org.keycloak.models.mongo.impl.types;
import java.util.List;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import org.keycloak.models.mongo.api.types.Converter;
import org.keycloak.models.mongo.api.types.TypeConverter;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,8 +1,5 @@
package org.keycloak.models.mongo.impl.types;
import java.util.Collection;
import java.util.Map;
import com.mongodb.BasicDBObject;
import org.keycloak.models.mongo.api.AttributedNoSQLObject;
import org.keycloak.models.mongo.api.NoSQLObject;
@ -12,6 +9,9 @@ import org.keycloak.models.mongo.impl.MongoDBImpl;
import org.keycloak.models.mongo.impl.ObjectInfo;
import org.picketlink.common.properties.Property;
import java.util.Collection;
import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -0,0 +1,15 @@
package org.keycloak.models.mongo.keycloak;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ModelProvider;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class MongoModelProvider implements ModelProvider {
@Override
public KeycloakSessionFactory createFactory() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}

View file

@ -1,10 +1,5 @@
package org.keycloak.models.mongo.keycloak.adapters;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
@ -14,6 +9,11 @@ import org.keycloak.models.mongo.keycloak.data.ApplicationData;
import org.keycloak.models.mongo.keycloak.data.RoleData;
import org.keycloak.models.mongo.keycloak.data.UserData;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,7 +1,5 @@
package org.keycloak.models.mongo.keycloak.adapters;
import java.net.UnknownHostException;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import org.jboss.logging.Logger;
@ -9,6 +7,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.api.NoSQLObject;
import org.keycloak.models.mongo.impl.MongoDBImpl;
import org.keycloak.models.mongo.keycloak.data.ApplicationData;
import org.keycloak.models.mongo.keycloak.data.OAuthClientData;
import org.keycloak.models.mongo.keycloak.data.RealmData;
@ -16,10 +15,11 @@ import org.keycloak.models.mongo.keycloak.data.RequiredCredentialData;
import org.keycloak.models.mongo.keycloak.data.RoleData;
import org.keycloak.models.mongo.keycloak.data.SocialLinkData;
import org.keycloak.models.mongo.keycloak.data.UserData;
import org.keycloak.models.mongo.impl.MongoDBImpl;
import org.keycloak.models.mongo.keycloak.data.credentials.OTPData;
import org.keycloak.models.mongo.keycloak.data.credentials.PasswordData;
import java.net.UnknownHostException;
/**
* NoSQL implementation based on MongoDB
*

View file

@ -1,17 +1,17 @@
package org.keycloak.models.mongo.keycloak.adapters;
import java.util.ArrayList;
import java.util.List;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.keycloak.data.RealmData;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.utils.KeycloakSessionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -41,14 +41,4 @@ public class OAuthClientAdapter implements OAuthClientModel {
return oauthAgent;
}
@Override
public String getBaseUrl() {
return delegate.getBaseUrl();
}
@Override
public void setBaseUrl(String base) {
delegate.setBaseUrl(base);
noSQL.saveObject(delegate);
}
}

View file

@ -1,16 +1,5 @@
package org.keycloak.models.mongo.keycloak.adapters;
import java.io.IOException;
import java.io.StringWriter;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bouncycastle.openssl.PEMWriter;
import org.keycloak.PemUtils;
import org.keycloak.models.ApplicationModel;
@ -21,21 +10,31 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
import org.keycloak.models.mongo.keycloak.data.OAuthClientData;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
import org.keycloak.models.mongo.keycloak.credentials.PasswordCredentialHandler;
import org.keycloak.models.mongo.keycloak.credentials.TOTPCredentialHandler;
import org.keycloak.models.mongo.keycloak.data.ApplicationData;
import org.keycloak.models.mongo.keycloak.data.OAuthClientData;
import org.keycloak.models.mongo.keycloak.data.RealmData;
import org.keycloak.models.mongo.keycloak.data.RequiredCredentialData;
import org.keycloak.models.mongo.keycloak.data.RoleData;
import org.keycloak.models.mongo.keycloak.data.SocialLinkData;
import org.keycloak.models.mongo.keycloak.data.UserData;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.picketlink.idm.credential.Credentials;
import org.picketlink.idm.model.sample.User;
import java.io.IOException;
import java.io.StringWriter;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -596,20 +595,6 @@ public class RealmAdapter implements RealmModel {
return result;
}
@Override
public boolean isRealmAdmin(UserModel agent) {
List<String> realmAdmins = realm.getRealmAdmins();
String userId = ((UserAdapter)agent).getUser().getId();
return realmAdmins.contains(userId);
}
@Override
public void addRealmAdmin(UserModel agent) {
UserData userData = ((UserAdapter)agent).getUser();
noSQL.pushItemToList(realm, "realmAdmins", userData.getId());
}
@Override
public RoleModel getRoleById(String id) {
RoleData role = noSQL.loadObject(RoleData.class, id);
@ -859,4 +844,24 @@ public class RealmAdapter implements RealmModel {
}
return userModels;
}
@Override
public Map<String, String> getSmtpConfig() {
throw new RuntimeException("Not implemented");
}
@Override
public void setSmtpConfig(Map<String, String> smtpConfig) {
throw new RuntimeException("Not implemented");
}
@Override
public Map<String, String> getSocialConfig() {
throw new RuntimeException("Not implemented");
}
@Override
public void setSocialConfig(Map<String, String> socialConfig) {
throw new RuntimeException("Not implemented");
}
}

View file

@ -1,15 +1,15 @@
package org.keycloak.models.mongo.keycloak.adapters;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.keycloak.data.UserData;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.keycloak.data.UserData;
/**
* Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based impl)
*
@ -149,4 +149,44 @@ public class UserAdapter implements UserModel {
user.setTotp(totp);
noSQL.saveObject(user);
}
@Override
public Set<String> getWebOrigins() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void setWebOrigins(Set<String> webOrigins) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void addWebOrigin(String webOrigin) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void removeWebOrigin(String webOrigin) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Set<String> getRedirectUris() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void setRedirectUris(Set<String> redirectUris) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void addRedirectUri(String redirectUri) {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void removeRedirectUri(String redirectUri) {
//To change body of implemented methods use File | Settings | File Templates.
}
}

View file

@ -1,9 +1,5 @@
package org.keycloak.models.mongo.keycloak.credentials;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.keycloak.data.UserData;
@ -12,6 +8,10 @@ import org.picketlink.idm.credential.Credentials;
import org.picketlink.idm.credential.encoder.PasswordEncoder;
import org.picketlink.idm.credential.encoder.SHAPasswordEncoder;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
/**
* Defacto forked from {@link org.picketlink.idm.credential.handler.PasswordCredentialHandler}
*

View file

@ -1,8 +1,5 @@
package org.keycloak.models.mongo.keycloak.credentials;
import java.util.Date;
import java.util.Map;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.keycloak.data.UserData;
@ -10,11 +7,11 @@ import org.keycloak.models.mongo.keycloak.data.credentials.OTPData;
import org.picketlink.idm.credential.Credentials;
import org.picketlink.idm.credential.util.TimeBasedOTP;
import java.util.Date;
import java.util.Map;
import static org.picketlink.common.util.StringUtil.isNullOrEmpty;
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_ALGORITHM;
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_DELAY_WINDOW;
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_INTERVAL_SECONDS;
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_NUMBER_DIGITS;
import static org.picketlink.idm.credential.util.TimeBasedOTP.*;
/**
* Defacto forked from {@link org.picketlink.idm.credential.handler.TOTPCredentialHandler}

View file

@ -1,7 +1,5 @@
package org.keycloak.models.mongo.keycloak.data;
import java.util.List;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.api.NoSQLCollection;
import org.keycloak.models.mongo.api.NoSQLField;
@ -9,6 +7,8 @@ import org.keycloak.models.mongo.api.NoSQLId;
import org.keycloak.models.mongo.api.NoSQLObject;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,7 +1,5 @@
package org.keycloak.models.mongo.keycloak.data;
import java.util.List;
import org.jboss.logging.Logger;
import org.keycloak.models.mongo.api.NoSQL;
import org.keycloak.models.mongo.api.NoSQLCollection;
@ -10,6 +8,8 @@ import org.keycloak.models.mongo.api.NoSQLId;
import org.keycloak.models.mongo.api.NoSQLObject;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,7 +1,5 @@
package org.keycloak.models.mongo.keycloak.data;
import java.util.List;
import org.jboss.logging.Logger;
import org.keycloak.models.UserModel;
import org.keycloak.models.mongo.api.AbstractAttributedNoSQLObject;
@ -12,6 +10,8 @@ import org.keycloak.models.mongo.api.NoSQLId;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.keycloak.data.credentials.PasswordData;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,11 +1,11 @@
package org.keycloak.models.mongo.keycloak.data.credentials;
import java.util.Date;
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
import org.keycloak.models.mongo.api.NoSQLCollection;
import org.keycloak.models.mongo.api.NoSQLField;
import java.util.Date;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,11 +1,11 @@
package org.keycloak.models.mongo.keycloak.data.credentials;
import java.util.Date;
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
import org.keycloak.models.mongo.api.NoSQLCollection;
import org.keycloak.models.mongo.api.NoSQLField;
import java.util.Date;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,10 +1,10 @@
package org.keycloak.models.mongo.test;
import java.util.List;
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
import org.keycloak.models.mongo.api.NoSQLField;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,10 +1,5 @@
package org.keycloak.models.mongo.test;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import org.junit.After;
@ -15,6 +10,11 @@ import org.keycloak.models.mongo.api.NoSQLObject;
import org.keycloak.models.mongo.api.query.NoSQLQuery;
import org.keycloak.models.mongo.impl.MongoDBImpl;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -1,12 +1,12 @@
package org.keycloak.models.mongo.test;
import java.util.List;
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
import org.keycloak.models.mongo.api.NoSQLCollection;
import org.keycloak.models.mongo.api.NoSQLField;
import org.keycloak.models.mongo.api.NoSQLId;
import java.util.List;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/

View file

@ -31,14 +31,4 @@ public class OAuthClientAdapter implements OAuthClientModel {
return new UserAdapter(delegate.getOauthAgent(), idm);
}
@Override
public String getBaseUrl() {
return delegate.getBaseUrl();
}
@Override
public void setBaseUrl(String base) {
delegate.setBaseUrl(base);
relationshipManager.update(delegate);
}
}

View file

@ -5,7 +5,6 @@ import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.picketlink.mappings.RealmData;
import org.keycloak.models.picketlink.relationships.RealmAdminRelationship;
import org.keycloak.models.picketlink.relationships.RealmListingRelationship;
import org.keycloak.models.utils.KeycloakSessionUtils;
import org.picketlink.idm.PartitionManager;
@ -15,7 +14,6 @@ import org.picketlink.idm.query.RelationshipQuery;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>

View file

@ -0,0 +1,77 @@
package org.keycloak.models.picketlink;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ModelProvider;
import org.keycloak.models.picketlink.mappings.ApplicationEntity;
import org.keycloak.models.picketlink.mappings.RealmEntity;
import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.config.IdentityConfigurationBuilder;
import org.picketlink.idm.internal.DefaultPartitionManager;
import org.picketlink.idm.jpa.internal.JPAContextInitializer;
import org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class PicketlinkModelProvider implements ModelProvider {
@Override
public KeycloakSessionFactory createFactory() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("picketlink-keycloak-identity-store");
return new PicketlinkKeycloakSessionFactory(emf, buildPartitionManager());
}
public static PartitionManager buildPartitionManager() {
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
builder
.named("KEYCLOAK_JPA_CONFIG")
.stores()
.jpa()
.mappedEntity(
AttributedTypeEntity.class,
AccountTypeEntity.class,
RoleTypeEntity.class,
GroupTypeEntity.class,
IdentityTypeEntity.class,
RelationshipTypeEntity.class,
RelationshipIdentityTypeEntity.class,
PartitionTypeEntity.class,
PasswordCredentialTypeEntity.class,
DigestCredentialTypeEntity.class,
X509CredentialTypeEntity.class,
OTPCredentialTypeEntity.class,
AttributeTypeEntity.class,
RealmEntity.class,
ApplicationEntity.class
)
.supportGlobalRelationship(org.picketlink.idm.model.Relationship.class)
.addContextInitializer(new JPAContextInitializer(null) {
@Override
public EntityManager getEntityManager() {
return PicketlinkKeycloakSession.currentEntityManager.get();
}
})
.supportAllFeatures();
DefaultPartitionManager partitionManager = new DefaultPartitionManager(builder.buildAll());
return partitionManager;
}
}

View file

@ -2,11 +2,25 @@ package org.keycloak.models.picketlink;
import org.bouncycastle.openssl.PEMWriter;
import org.keycloak.PemUtils;
import org.keycloak.models.*;
import org.keycloak.models.picketlink.mappings.RealmData;
import org.keycloak.models.ApplicationModel;
import org.keycloak.models.IdGenerator;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.picketlink.mappings.ApplicationData;
import org.keycloak.models.picketlink.relationships.*;
import org.keycloak.models.picketlink.mappings.RealmData;
import org.keycloak.models.picketlink.relationships.ApplicationRelationship;
import org.keycloak.models.picketlink.relationships.OAuthClientRelationship;
import org.keycloak.models.picketlink.relationships.OAuthClientRequiredCredentialRelationship;
import org.keycloak.models.picketlink.relationships.RequiredApplicationCredentialRelationship;
import org.keycloak.models.picketlink.relationships.RequiredCredentialRelationship;
import org.keycloak.models.picketlink.relationships.ScopeRelationship;
import org.keycloak.models.picketlink.relationships.SocialLinkRelationship;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.RelationshipManager;
@ -601,7 +615,6 @@ public class RealmAdapter implements RealmModel {
idm.add(resourceUser);
applicationData.setResourceUser(resourceUser);
applicationData.setResourceName(name);
applicationData.setResourceUser(resourceUser);
partitionManager.add(applicationData);
ApplicationRelationship resourceRelationship = new ApplicationRelationship();
resourceRelationship.setRealm(realm.getName());
@ -875,23 +888,23 @@ public class RealmAdapter implements RealmModel {
}
@Override
public HashMap<String, String> getSmtpConfig() {
public Map<String, String> getSmtpConfig() {
return realm.getSmtpConfig();
}
@Override
public void setSmtpConfig(HashMap<String, String> smtpConfig) {
public void setSmtpConfig(Map<String, String> smtpConfig) {
realm.setSmtpConfig(smtpConfig);
updateRealm();
}
@Override
public HashMap<String, String> getSocialConfig() {
public Map<String, String> getSocialConfig() {
return realm.getSocialConfig();
}
@Override
public void setSocialConfig(HashMap<String, String> socialConfig) {
public void setSocialConfig(Map<String, String> socialConfig) {
realm.setSocialConfig(socialConfig);
updateRealm();
}

View file

@ -1,17 +1,16 @@
package org.keycloak.models.picketlink;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.keycloak.models.UserModel;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.sample.User;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $

View file

@ -3,8 +3,7 @@ package org.keycloak.models.picketlink.mappings;
import org.picketlink.idm.model.AbstractPartition;
import org.picketlink.idm.model.annotation.AttributeProperty;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -26,8 +25,8 @@ public class RealmData extends AbstractPartition {
private String publicKeyPem;
private String privateKeyPem;
private String[] defaultRoles;
private HashMap<String, String> smtpConfig;
private HashMap<String, String> socialConfig;
private Map<String, String> smtpConfig;
private Map<String, String> socialConfig;
public RealmData() {
super(null);
@ -170,20 +169,20 @@ public class RealmData extends AbstractPartition {
}
@AttributeProperty
public HashMap<String, String> getSmtpConfig() {
public Map<String, String> getSmtpConfig() {
return smtpConfig;
}
public void setSmtpConfig(HashMap<String, String> smtpConfig) {
public void setSmtpConfig(Map<String, String> smtpConfig) {
this.smtpConfig = smtpConfig;
}
@AttributeProperty
public HashMap<String, String> getSocialConfig() {
public Map<String, String> getSocialConfig() {
return socialConfig;
}
public void setSocialConfig(HashMap<String, String> socialConfig) {
public void setSocialConfig(Map<String, String> socialConfig) {
this.socialConfig = socialConfig;
}
}

View file

@ -5,7 +5,11 @@ import org.picketlink.idm.jpa.annotations.OwnerReference;
import org.picketlink.idm.jpa.annotations.entity.IdentityManaged;
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.OneToOne;
import java.io.Serializable;
import java.util.HashMap;

View file

@ -3,9 +3,7 @@ package org.keycloak.models.picketlink.relationships;
import org.picketlink.idm.model.AbstractAttributedType;
import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.model.sample.User;
import org.picketlink.idm.query.AttributeParameter;
import org.picketlink.idm.query.RelationshipQueryParameter;
/**
* Picketlink doesn't allow you to query for all partitions, thus this stupid relationship...

View file

@ -37,6 +37,6 @@
<module>api</module>
<module>picketlink</module>
<module>jpa</module>
<!--<module>mongo</module>-->
<module>mongo</module>
</modules>
</project>

View file

@ -9,7 +9,7 @@
<packaging>pom</packaging>
<properties>
<resteasy.version>3.0.4.Final</resteasy.version>
<resteasy.version>3.0.5.Final</resteasy.version>
<undertow.version>1.0.0.Beta12</undertow.version>
<picketlink.version>2.5.0.Beta6</picketlink.version>
<mongo.driver.version>2.11.2</mongo.driver.version>

View file

@ -33,6 +33,12 @@
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-picketlink</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<!--<dependency>

View file

@ -21,21 +21,20 @@
*/
package org.keycloak.services;
import java.net.URI;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.spi.ServiceRegistry;
import javax.ws.rs.core.MultivaluedMap;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.resources.flows.FormFlows;
import org.keycloak.social.SocialProvider;
import javax.imageio.spi.ServiceRegistry;
import javax.ws.rs.core.MultivaluedMap;
import java.net.URI;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
*/
@ -95,7 +94,7 @@ public interface FormService {
this.message = message;
socialProviders = new LinkedList<SocialProvider>();
HashMap<String, String> socialConfig = realm.getSocialConfig();
Map<String, String> socialConfig = realm.getSocialConfig();
if (socialConfig != null) {
for (Iterator<SocialProvider> itr = ServiceRegistry.lookupProviders(org.keycloak.social.SocialProvider.class); itr.hasNext(); ) {
SocialProvider p = itr.next();

View file

@ -21,28 +21,25 @@
*/
package org.keycloak.services.email;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.managers.AccessCodeEntry;
import org.keycloak.services.resources.flows.Urls;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.logging.Logger;
import org.keycloak.services.managers.AccessCodeEntry;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.services.resources.AccountService;
import org.keycloak.services.resources.flows.Urls;
import java.net.URI;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>

View file

@ -5,7 +5,12 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakTransaction;
import javax.servlet.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
/**

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