diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java index 541012fddc..1a83571a86 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java @@ -285,6 +285,7 @@ public class AdapterDeploymentContext { scheme = "https"; } if (!request.getScheme().equals(scheme) && request.getPort() != -1) { + log.error("request scheme: " + request.getScheme() + " ssl required: " + deployment.isSslRequired()); throw new RuntimeException("Can't resolve relative url from adapter config."); } builder.scheme(scheme); diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java index 6c0c58fc6b..d9b6911d83 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java @@ -106,6 +106,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif @Override public void invoke(Request request, Response response) throws IOException, ServletException { try { + log.info("invoke"); CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deploymentContext, facade); if (handler.handleRequest()) { @@ -119,9 +120,11 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif @Override public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException { + log.info("*** authenticate"); CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (deployment == null || !deployment.isConfigured()) { + log.info("*** deployment isn't configured return false"); return false; } diff --git a/project-integrations/README.md b/project-integrations/README.md new file mode 100644 index 0000000000..f9299b2af6 --- /dev/null +++ b/project-integrations/README.md @@ -0,0 +1,5 @@ +Keycloak External Project Integrations +========== + +Everthing in this directory is examples related to integration with non-keycloak projects. Its a sandbox we use to test integrations with third-party projects + \ No newline at end of file diff --git a/project-integrations/aerogear-ups/README.md b/project-integrations/aerogear-ups/README.md new file mode 100755 index 0000000000..83732aa173 --- /dev/null +++ b/project-integrations/aerogear-ups/README.md @@ -0,0 +1,18 @@ +Self Bootstrapping Keycloak Server and Application +========================================================== + +This is an example of bundling a keycloak server war and application together so that keycloak is bootstrapped out of the +box. + +* There is a testrealm.json file that is used to bootstrap the realm in the auth-server/ project +* Notice that there is a context-param in auth-server/web.xml called keycloak.import.realm.resources. This sets up the import of the json file +* If you open up testrealm.json, notice that all urls are relative. Keycloak will now extrapolate the host and port based +on the request if the configured urls are just a path and don't have a schem, host, and port. +* In app, there is a BootstrapListener class. This obtains the config context of the adapter and initializes it. +* Notice that this class sets up a relative URL. Also notice that the application is a "public" client. This is so that +we don't have to query the database for the application's secret. Also notice that the realm key is not set. Keycloak adapter +will now query the auth server url for the public key of the realm. + +Problems: +* Biggest problem is SSL. You have to crack open web.xml to set up a confidential security constraint. You also have +to change the adapter config and the realm config to make SSL required. diff --git a/project-integrations/aerogear-ups/app/pom.xml b/project-integrations/aerogear-ups/app/pom.xml new file mode 100755 index 0000000000..31239638ae --- /dev/null +++ b/project-integrations/aerogear-ups/app/pom.xml @@ -0,0 +1,113 @@ + + + + keycloak-parent + org.keycloak + 1.0-beta-1-SNAPSHOT + ../../../pom.xml + + + 4.0.0 + ups-example-app + war + Keycloak Secured App EAP 6.x + + + + + org.bouncycastle + bcprov-jdk16 + + + org.keycloak + keycloak-core + ${project.version} + + + org.keycloak + keycloak-adapter-core + ${project.version} + + + org.keycloak + keycloak-jboss-adapter-core + ${project.version} + + + org.keycloak + keycloak-as7-adapter + ${project.version} + + + net.iharder + base64 + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + provided + + + + org.jboss.resteasy + resteasy-jaxrs + ${resteasy.version} + provided + + + org.jboss.resteasy + async-http-servlet-3.0 + ${resteasy.version} + provided + + + org.jboss.resteasy + jaxrs-api + ${resteasy.version} + provided + + + org.jboss.resteasy + resteasy-jackson-provider + ${resteasy.version} + provided + + + + + javax.enterprise + cdi-api + 1.1 + provided + + + + + + app + + + org.jboss.as.plugins + jboss-as-maven-plugin + 7.5.Final + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + diff --git a/project-integrations/aerogear-ups/app/src/main/java/org/keycloak/example/BootstrapListener.java b/project-integrations/aerogear-ups/app/src/main/java/org/keycloak/example/BootstrapListener.java new file mode 100755 index 0000000000..f7284b931e --- /dev/null +++ b/project-integrations/aerogear-ups/app/src/main/java/org/keycloak/example/BootstrapListener.java @@ -0,0 +1,31 @@ +package org.keycloak.example; + +import org.keycloak.adapters.AdapterDeploymentContext; +import org.keycloak.representations.adapters.config.AdapterConfig; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class BootstrapListener implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent sce) { + AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext)sce.getServletContext().getAttribute(AdapterDeploymentContext.class.getName()); + AdapterConfig config = new AdapterConfig(); + config.setRealm("demo"); + config.setResource("customer-portal"); + config.setAuthServerUrl("/auth"); + config.setSslNotRequired(true); + config.setPublicClient(true); + deploymentContext.updateDeployment(config); + + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + + } +} diff --git a/project-integrations/aerogear-ups/app/src/main/resources/META-INF/beans.xml b/project-integrations/aerogear-ups/app/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000..57025b5976 --- /dev/null +++ b/project-integrations/aerogear-ups/app/src/main/resources/META-INF/beans.xml @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100755 index 0000000000..8c92fe914f --- /dev/null +++ b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-web.xml b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-web.xml new file mode 100755 index 0000000000..2f94ba4bca --- /dev/null +++ b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/jboss-web.xml @@ -0,0 +1,5 @@ + + + org.keycloak.adapters.as7.KeycloakAuthenticatorValve + + \ No newline at end of file diff --git a/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/web.xml b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 0000000000..af91ffa36e --- /dev/null +++ b/project-integrations/aerogear-ups/app/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,54 @@ + + + + app + + + org.keycloak.example.BootstrapListener + + + + + + Customers + /customers/* + + + user + + + + + + Database + /rest/* + + + user + + + + + + BASIC + demo + + + + admin + + + user + + + + + + diff --git a/project-integrations/aerogear-ups/app/src/main/webapp/customers/view.jsp b/project-integrations/aerogear-ups/app/src/main/webapp/customers/view.jsp new file mode 100755 index 0000000000..be4d93c27e --- /dev/null +++ b/project-integrations/aerogear-ups/app/src/main/webapp/customers/view.jsp @@ -0,0 +1,47 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1" %> +<%@ page import="org.keycloak.example.services.CustomerDatabaseClient" %> +<%@ page import="org.keycloak.util.KeycloakUriBuilder" %> +<%@ page import="org.keycloak.representations.IDToken" %> + + + Customer View Page + + +<% + String logoutUri = KeycloakUriBuilder.fromUri("http://localhost:8080/auth/rest/realms/demo/tokens/logout") + .queryParam("redirect_uri", "http://localhost:8080/app").build().toString(); + String acctUri = "http://localhost:8080/auth/rest/realms/demo/account?referrer=customer-portal"; + IDToken idToken = CustomerDatabaseClient.getIDToken(request); +%> +

logout | manage acct

+Servlet User Principal <%=request.getUserPrincipal().getName()%> + made this request. +

Caller IDToken values (You can specify what is returned in IDToken in the customer-portal claims page in the admin console:

+

Username: <%=idToken.getPreferredUsername()%>

+

Email: <%=idToken.getEmail()%>

+

Full Name: <%=idToken.getName()%>

+

First: <%=idToken.getGivenName()%>

+

Last: <%=idToken.getFamilyName()%>

+

Customer Listing

+<% + java.util.List list = null; + try { + list = CustomerDatabaseClient.getCustomers(request); + } catch (CustomerDatabaseClient.Failure failure) { + out.println("There was a failure processing request. You either didn't configure Keycloak properly, or maybe" + + "you just forgot to secure the database service?"); + out.println("Status from database service invocation was: " + failure.getStatus()); + return; + } + for (String cust : list) { + out.print("

"); + out.print(cust); + out.println("

"); + + } +%> +

+ + \ No newline at end of file diff --git a/project-integrations/aerogear-ups/app/src/main/webapp/index.html b/project-integrations/aerogear-ups/app/src/main/webapp/index.html new file mode 100755 index 0000000000..681fa08a17 --- /dev/null +++ b/project-integrations/aerogear-ups/app/src/main/webapp/index.html @@ -0,0 +1,13 @@ + + + + + + +

Customer Portal

+ +

Customer Listing

+ + + \ No newline at end of file diff --git a/project-integrations/aerogear-ups/auth-server/pom.xml b/project-integrations/aerogear-ups/auth-server/pom.xml new file mode 100755 index 0000000000..e30625f80a --- /dev/null +++ b/project-integrations/aerogear-ups/auth-server/pom.xml @@ -0,0 +1,233 @@ + + + + keycloak-parent + org.keycloak + 1.0-beta-1-SNAPSHOT + ../../../pom.xml + + + 4.0.0 + ups-auth-server + war + UPS Auth Server + + + + + org.bouncycastle + bcprov-jdk16 + + + org.keycloak + keycloak-core + ${project.version} + + + net.iharder + base64 + + + org.keycloak + keycloak-core-jaxrs + ${project.version} + + + org.keycloak + keycloak-services + ${project.version} + + + com.google.zxing + javase + + + org.keycloak + keycloak-model-api + ${project.version} + + + org.keycloak + keycloak-model-jpa + ${project.version} + + + org.keycloak + keycloak-audit-api + ${project.version} + + + org.keycloak + keycloak-audit-jpa + ${project.version} + + + org.keycloak + keycloak-audit-jboss-logging + ${project.version} + + + + org.keycloak + keycloak-social-core + ${project.version} + + + org.json + json + + + org.keycloak + keycloak-social-github + ${project.version} + + + org.keycloak + keycloak-social-google + ${project.version} + + + org.keycloak + keycloak-social-twitter + ${project.version} + + + org.twitter4j + twitter4j-core + + + org.keycloak + keycloak-social-facebook + ${project.version} + + + + org.keycloak + keycloak-forms-common-freemarker + ${project.version} + + + org.freemarker + freemarker + + + org.keycloak + keycloak-forms-common-themes + ${project.version} + + + org.keycloak + keycloak-account-api + ${project.version} + + + org.keycloak + keycloak-account-freemarker + ${project.version} + + + org.keycloak + keycloak-login-api + ${project.version} + + + org.keycloak + keycloak-login-freemarker + ${project.version} + + + org.keycloak + keycloak-js-adapter + ${project.version} + + + + org.keycloak + keycloak-authentication-api + ${project.version} + + + org.keycloak + keycloak-authentication-model + ${project.version} + + + + org.keycloak + keycloak-timer-api + ${project.version} + + + org.keycloak + keycloak-timer-basic + ${project.version} + + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + provided + + + + org.jboss.resteasy + resteasy-jaxrs + ${resteasy.version} + provided + + + org.jboss.resteasy + resteasy-multipart-provider + ${resteasy.version} + provided + + + org.jboss.resteasy + async-http-servlet-3.0 + ${resteasy.version} + provided + + + org.jboss.resteasy + jaxrs-api + ${resteasy.version} + provided + + + org.jboss.resteasy + resteasy-jackson-provider + ${resteasy.version} + provided + + + + + + + auth-server + + + org.jboss.as.plugins + jboss-as-maven-plugin + 7.5.Final + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + diff --git a/project-integrations/aerogear-ups/auth-server/src/main/resources/META-INF/persistence.xml b/project-integrations/aerogear-ups/auth-server/src/main/resources/META-INF/persistence.xml new file mode 100755 index 0000000000..3eeed1f7f8 --- /dev/null +++ b/project-integrations/aerogear-ups/auth-server/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,40 @@ + + + java:jboss/datasources/ExampleDS + org.keycloak.models.jpa.entities.ApplicationEntity + org.keycloak.models.jpa.entities.CredentialEntity + org.keycloak.models.jpa.entities.OAuthClientEntity + org.keycloak.models.jpa.entities.RealmEntity + org.keycloak.models.jpa.entities.RequiredCredentialEntity + org.keycloak.models.jpa.entities.AuthenticationProviderEntity + org.keycloak.models.jpa.entities.ApplicationRoleEntity + org.keycloak.models.jpa.entities.RealmRoleEntity + org.keycloak.models.jpa.entities.SocialLinkEntity + org.keycloak.models.jpa.entities.AuthenticationLinkEntity + org.keycloak.models.jpa.entities.UserEntity + org.keycloak.models.jpa.entities.UsernameLoginFailureEntity + org.keycloak.models.jpa.entities.UserRoleMappingEntity + org.keycloak.models.jpa.entities.ScopeMappingEntity + + true + + + + + + + + java:jboss/datasources/ExampleDS + org.keycloak.audit.jpa.EventEntity + + true + + + + + + + diff --git a/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100755 index 0000000000..8c92fe914f --- /dev/null +++ b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/testrealm.json b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/testrealm.json new file mode 100755 index 0000000000..bc2d8f708a --- /dev/null +++ b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/testrealm.json @@ -0,0 +1,70 @@ +{ + "realm": "demo", + "enabled": true, + "accessTokenLifespan": 3000, + "accessCodeLifespan": 10, + "accessCodeLifespanUserAction": 6000, + "sslNotRequired": true, + "registrationAllowed": false, + "social": false, + "updateProfileOnInitialSocialLogin": false, + "requiredCredentials": [ "password" ], + "users" : [ + { + "username" : "bburke@redhat.com", + "enabled": true, + "email" : "bburke@redhat.com", + "firstName": "Bill", + "lastName": "Burke", + "credentials" : [ + { "type" : "password", + "value" : "password" } + ] + } + ], + "roles" : { + "realm" : [ + { + "name": "user", + "description": "User privileges" + }, + { + "name": "admin", + "description": "Administrator privileges" + } + ] + }, + "roleMappings": [ + { + "username": "bburke@redhat.com", + "roles": ["user"] + } + ], + "scopeMappings": [ + { + "client": "customer-portal", + "roles": ["user"] + } + ], + "applications": [ + { + "name": "customer-portal", + "enabled": true, + "publicClient": true, + "adminUrl": "/app", + "baseUrl": "/app", + "redirectUris": [ + "/app/*" + ] + } + ], + "applicationRoleMappings": { + "account": [ + { + "username": "bburke@redhat.com", + "roles": ["manage-account"] + } + ] + } + +} diff --git a/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/web.xml b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 0000000000..473994d4a7 --- /dev/null +++ b/project-integrations/aerogear-ups/auth-server/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,71 @@ + + + + auth + + + keycloak.import.realm.resources + /WEB-INF/testrealm.json + + + + Keycloak REST Interface + org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher + + javax.ws.rs.Application + org.keycloak.services.resources.KeycloakApplication + + + resteasy.servlet.mapping.prefix + / + + 1 + true + + + + org.keycloak.services.listeners.KeycloakSessionDestroyListener + + + + Keycloak Client Connection Filter + org.keycloak.services.filters.ClientConnectionFilter + + + + Keycloak Session Management + org.keycloak.services.filters.KeycloakSessionServletFilter + + + + Keycloak Session Management + /rest/* + + + + Keycloak Client Connection Filter + /rest/* + + + + Keycloak REST Interface + /* + + + + + + diff --git a/project-integrations/aerogear-ups/pom.xml b/project-integrations/aerogear-ups/pom.xml new file mode 100755 index 0000000000..2278cdd1de --- /dev/null +++ b/project-integrations/aerogear-ups/pom.xml @@ -0,0 +1,39 @@ + + + keycloak-parent + org.keycloak + 1.0-beta-1-SNAPSHOT + ../../pom.xml + + Aerogear UPS Parent + + 4.0.0 + + aerogear-ups-project-integrations-pom + pom + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.jboss.as.plugins + jboss-as-maven-plugin + 7.1.1.Final + + true + + + + + + auth-server + app + + diff --git a/project-integrations/pom.xml b/project-integrations/pom.xml new file mode 100755 index 0000000000..b76a3d642b --- /dev/null +++ b/project-integrations/pom.xml @@ -0,0 +1,38 @@ + + + keycloak-parent + org.keycloak + 1.0-beta-1-SNAPSHOT + ../pom.xml + + Third-party Integration Parent + + 4.0.0 + + keycloak-project-integrations-pom + pom + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.jboss.as.plugins + jboss-as-maven-plugin + 7.1.1.Final + + true + + + + + + aerogear-ups + + diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java index eae7360e01..3012507887 100755 --- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java +++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java @@ -20,8 +20,6 @@ import org.keycloak.provider.ProviderFactoryLoader; import org.keycloak.provider.ProviderSession; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.services.DefaultProviderSessionFactory; -import org.keycloak.picketlink.IdentityManagerProvider; -import org.keycloak.picketlink.IdentityManagerProviderFactory; import org.keycloak.provider.ProviderSessionFactory; import org.keycloak.services.managers.ApplianceBootstrap; import org.keycloak.services.managers.BruteForceProtector; @@ -132,7 +130,14 @@ public class KeycloakApplication extends Application { factory.registerLoader(AuditProvider.class, ProviderFactoryLoader.create(AuditProviderFactory.class), Config.getAuditProvider()); factory.registerLoader(AuditListener.class, ProviderFactoryLoader.create(AuditListenerFactory.class)); factory.registerLoader(TimerProvider.class, ProviderFactoryLoader.create(TimerProviderFactory.class), Config.getTimerProvider()); - factory.registerLoader(IdentityManagerProvider.class, ProviderFactoryLoader.create(IdentityManagerProviderFactory.class), Config.getIdentityManagerProvider()); + try { + Class identityManagerProvider = Class.forName("org.keycloak.picketlink.IdentityManagerProvider"); + Class identityManagerProviderFactory = Class.forName("org.keycloak.picketlink.IdentityManagerProviderFactory"); + factory.registerLoader(identityManagerProvider, ProviderFactoryLoader.create(identityManagerProviderFactory), Config.getIdentityManagerProvider()); + } catch (ClassNotFoundException e) { + log.warn("Picketlink libraries not installed for IdentityManagerProviderFactory"); + } + factory.registerLoader(AuthenticationProvider.class, ProviderFactoryLoader.create(AuthenticationProviderFactory.class)); factory.init();