diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java index f6ea2f5fcb95..7880c5bab20d 100755 --- a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java +++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLEndpoint.java @@ -24,6 +24,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionModel; +import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder; import org.keycloak.protocol.saml.SAML2LogoutResponseBuilder; import org.keycloak.protocol.saml.SAMLRequestParser; import org.keycloak.protocol.saml.SamlProtocol; @@ -247,16 +248,17 @@ protected Response logoutRequest(LogoutRequestType request, String relayState) { builder.logoutRequestID(request.getID()); builder.destination(config.getSingleLogoutServiceUrl()); builder.issuer(issuerURL); - builder.relayState(relayState); + JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder() + .relayState(relayState); if (config.isWantAuthnRequestsSigned()) { - builder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) + binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) .signDocument(); } try { if (config.isPostBindingResponse()) { - return builder.postBinding().response(); + return binding.postBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl()); } else { - return builder.redirectBinding().response(); + return binding.redirectBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl()); } } catch (ConfigurationException e) { throw new RuntimeException(e); diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java index 4517a943049b..a10fd50c1074 100755 --- a/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java +++ b/broker/saml/src/main/java/org/keycloak/broker/saml/SAMLIdentityProvider.java @@ -33,6 +33,7 @@ import org.keycloak.models.FederatedIdentityModel; import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionModel; +import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder; import org.keycloak.protocol.saml.SAML2AuthnRequestBuilder; import org.keycloak.protocol.saml.SAML2LogoutRequestBuilder; import org.keycloak.protocol.saml.SAML2NameIDPolicyBuilder; @@ -92,7 +93,8 @@ public Response performLogin(AuthenticationRequest request) { .issuer(issuerURL) .forceAuthn(getConfig().isForceAuthn()) .protocolBinding(protocolBinding) - .nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat)) + .nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat)); + JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder() .relayState(request.getState()); if (getConfig().isWantAuthnRequestsSigned()) { @@ -109,14 +111,14 @@ public Response performLogin(AuthenticationRequest request) { KeyPair keypair = new KeyPair(publicKey, privateKey); - authnRequestBuilder.signWith(keypair); - authnRequestBuilder.signDocument(); + binding.signWith(keypair); + binding.signDocument(); } if (getConfig().isPostBindingAuthnRequest()) { - return authnRequestBuilder.postBinding().request(); + return binding.postBinding(authnRequestBuilder.toDocument()).request(destinationUrl); } else { - return authnRequestBuilder.redirectBinding().request(); + return binding.redirectBinding(authnRequestBuilder.toDocument()).request(destinationUrl); } } catch (Exception e) { throw new IdentityBrokerException("Could not create authentication request.", e); @@ -153,9 +155,10 @@ public void backchannelLogout(UserSessionModel userSession, UriInfo uriInfo, Rea String singleLogoutServiceUrl = getConfig().getSingleLogoutServiceUrl(); if (singleLogoutServiceUrl == null || singleLogoutServiceUrl.trim().equals("") || !getConfig().isBackchannelSupported()) return; SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl); + JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm); try { int status = SimpleHttp.doPost(singleLogoutServiceUrl) - .param(GeneralConstants.SAML_REQUEST_KEY, logoutBuilder.postBinding().encoded()) + .param(GeneralConstants.SAML_REQUEST_KEY, binding.postBinding(logoutBuilder.buildDocument()).encoded()) .param(GeneralConstants.RELAY_STATE, userSession.getId()).asStatus(); boolean success = status >=200 && status < 400; if (!success) { @@ -178,7 +181,8 @@ public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, Uri } else { try { SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl); - return logoutBuilder.postBinding().request(); + JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm); + return binding.postBinding(logoutBuilder.buildDocument()).request(singleLogoutServiceUrl); } catch (Exception e) { throw new RuntimeException(e); } @@ -192,13 +196,18 @@ protected SAML2LogoutRequestBuilder buildLogoutRequest(UserSessionModel userSess .issuer(getEntityId(uriInfo, realm)) .sessionIndex(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX)) .userPrincipal(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT), userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEFORMAT)) - .destination(singleLogoutServiceUrl) + .destination(singleLogoutServiceUrl); + return logoutBuilder; + } + + private JaxrsSAML2BindingBuilder buildLogoutBinding(UserSessionModel userSession, RealmModel realm) { + JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder() .relayState(userSession.getId()); if (getConfig().isWantAuthnRequestsSigned()) { - logoutBuilder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) + binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) .signDocument(); } - return logoutBuilder; + return binding; } @Override diff --git a/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml b/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml index 59ae243e0c9b..dba2c930aa43 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/assembly.xml @@ -14,6 +14,7 @@ org/bouncycastle/** net/iharder/base64/** org/keycloak/keycloak-core/** + org/keycloak/keycloak-adapter-spi/** org/keycloak/keycloak-adapter-core/** org/keycloak/keycloak-jboss-adapter-core/** org/keycloak/keycloak-as7-adapter/** diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/build.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/build.xml index 9ab6fabadefd..c3e0add80c40 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-modules/build.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/build.xml @@ -53,6 +53,11 @@ + + + + + diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml index d191be5acdb5..d65477b6c5b8 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml @@ -21,6 +21,14 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-tomcat-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml index 5e3e5c34f0db..c2975ba765b6 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml @@ -14,6 +14,7 @@ + diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml new file mode 100755 index 000000000000..6d0d9c34dc5d --- /dev/null +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-as7-adapter/main/module.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-as7-adapter/main/module.xml index 463ff4379275..05053c1f84ac 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-as7-adapter/main/module.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-as7-adapter/main/module.xml @@ -18,6 +18,7 @@ + diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml index beac07bac772..f1ee530cdadd 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml index bc489889c9ea..c906cc9d5462 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml b/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml index 0f6c46277195..5ea03d1e84ab 100755 --- a/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml +++ b/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/assembly.xml @@ -14,6 +14,7 @@ org/bouncycastle/** net/iharder/base64/** org/keycloak/keycloak-core/** + org/keycloak/keycloak-adapter-spi/** org/keycloak/keycloak-adapter-core/** org/keycloak/keycloak-jboss-adapter-core/** org/keycloak/keycloak-as7-adapter/** diff --git a/distribution/adapters/wf8-adapter/wf8-modules/build.xml b/distribution/adapters/wf8-adapter/wf8-modules/build.xml index 30e02540e61d..1601598f4ea9 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/build.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/build.xml @@ -49,6 +49,11 @@ + + + + + diff --git a/distribution/adapters/wf8-adapter/wf8-modules/pom.xml b/distribution/adapters/wf8-adapter/wf8-modules/pom.xml index f3e419018e63..5d64596b9358 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/pom.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/pom.xml @@ -21,6 +21,14 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-undertow-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml index 1be1486fe235..cfa8a0e8c9ea 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml @@ -13,6 +13,7 @@ + diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml new file mode 100755 index 000000000000..6d0d9c34dc5d --- /dev/null +++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml index beac07bac772..f1ee530cdadd 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml index 2d3876e266b7..1e92a95caa43 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml index 1772a22cfdc3..c3f1775464b6 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml @@ -18,6 +18,7 @@ + diff --git a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml index 2b0e5370243d..c0786cfe6992 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml @@ -19,6 +19,7 @@ + diff --git a/distribution/adapters/wf9-adapter/wf9-modules/build.xml b/distribution/adapters/wf9-adapter/wf9-modules/build.xml index 8c1d41a21b11..ce67858a69fd 100755 --- a/distribution/adapters/wf9-adapter/wf9-modules/build.xml +++ b/distribution/adapters/wf9-adapter/wf9-modules/build.xml @@ -49,6 +49,11 @@ + + + + + diff --git a/distribution/adapters/wf9-adapter/wf9-modules/pom.xml b/distribution/adapters/wf9-adapter/wf9-modules/pom.xml index ed0f8094d35a..00d7cbf34b43 100755 --- a/distribution/adapters/wf9-adapter/wf9-modules/pom.xml +++ b/distribution/adapters/wf9-adapter/wf9-modules/pom.xml @@ -21,6 +21,14 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-undertow-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml index 5e3e5c34f0db..6c25a03cd51c 100755 --- a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml +++ b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-core/main/module.xml @@ -13,6 +13,7 @@ + diff --git a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml new file mode 100755 index 000000000000..6d0d9c34dc5d --- /dev/null +++ b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-adapter-spi/main/module.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml index beac07bac772..f1ee530cdadd 100755 --- a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml +++ b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-jboss-adapter-core/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml index bc489889c9ea..c906cc9d5462 100755 --- a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml +++ b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-servlet-oauth-client/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml index 4b3a4c913709..4dd6f2d10247 100755 --- a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml +++ b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-undertow-adapter/main/module.xml @@ -18,6 +18,7 @@ + diff --git a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml index 3d65f2bb9273..853ca8d8e153 100755 --- a/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml +++ b/distribution/adapters/wf9-adapter/wf9-modules/src/main/resources/modules/org/keycloak/keycloak-wildfly-adapter/main/module.xml @@ -19,6 +19,7 @@ + diff --git a/distribution/feature-packs/adapter-feature-pack/pom.xml b/distribution/feature-packs/adapter-feature-pack/pom.xml old mode 100644 new mode 100755 index 60705fa68c85..01f2a5a892ba --- a/distribution/feature-packs/adapter-feature-pack/pom.xml +++ b/distribution/feature-packs/adapter-feature-pack/pom.xml @@ -44,6 +44,14 @@ org.keycloak keycloak-servlet-oauth-client + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-undertow-adapter-spi + org.keycloak keycloak-undertow-adapter diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-adapter-core/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-adapter-core/main/module.xml old mode 100644 new mode 100755 index 6407abcd191b..0c854b9992d1 --- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-adapter-core/main/module.xml +++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-adapter-core/main/module.xml @@ -13,6 +13,7 @@ + diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-adapter-spi/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-adapter-spi/main/module.xml new file mode 100755 index 000000000000..858acb1d211b --- /dev/null +++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-adapter-spi/main/module.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-jboss-adapter-core/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-jboss-adapter-core/main/module.xml old mode 100644 new mode 100755 index 243a5b90983f..c836034a0894 --- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-jboss-adapter-core/main/module.xml +++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-jboss-adapter-core/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-servlet-oauth-client/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-servlet-oauth-client/main/module.xml index 73fccad06c6e..fb39438ae000 100755 --- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-servlet-oauth-client/main/module.xml +++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-servlet-oauth-client/main/module.xml @@ -10,6 +10,7 @@ + diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-undertow-adapter/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-undertow-adapter/main/module.xml old mode 100644 new mode 100755 index 75ac27ea52a2..b813b7f79566 --- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-undertow-adapter/main/module.xml +++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-undertow-adapter/main/module.xml @@ -18,6 +18,7 @@ + diff --git a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-wildfly-adapter/main/module.xml b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-wildfly-adapter/main/module.xml index 88eaafafb404..46107668ddfb 100755 --- a/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-wildfly-adapter/main/module.xml +++ b/distribution/feature-packs/adapter-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-wildfly-adapter/main/module.xml @@ -19,6 +19,7 @@ + diff --git a/examples/multi-tenant/pom.xml b/examples/multi-tenant/pom.xml index c09f7922f338..de7a72e1ac66 100755 --- a/examples/multi-tenant/pom.xml +++ b/examples/multi-tenant/pom.xml @@ -39,6 +39,10 @@ org.keycloak keycloak-adapter-core + + org.keycloak + keycloak-adapter-spi + diff --git a/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/control/PathBasedKeycloakConfigResolver.java b/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/control/PathBasedKeycloakConfigResolver.java old mode 100644 new mode 100755 index 44f7e78a1dff..b7223005e9d7 --- a/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/control/PathBasedKeycloakConfigResolver.java +++ b/examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/control/PathBasedKeycloakConfigResolver.java @@ -17,14 +17,13 @@ package org.keycloak.example.multitenant.control; import java.io.InputStream; -import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import org.keycloak.adapters.HttpFacade; import org.keycloak.adapters.KeycloakConfigResolver; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.KeycloakDeploymentBuilder; +import org.keycloak.adapters.OIDCHttpFacade; /** * @@ -35,7 +34,7 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver { private final Map cache = new ConcurrentHashMap(); @Override - public KeycloakDeployment resolve(HttpFacade.Request request) { + public KeycloakDeployment resolve(OIDCHttpFacade.Request request) { String path = request.getURI(); int multitenantIndex = path.indexOf("multitenant/"); if (multitenantIndex == -1) { diff --git a/integration/adapter-core/pom.xml b/integration/adapter-core/pom.xml index 6a8e14b2502c..e96320a33d96 100755 --- a/integration/adapter-core/pom.xml +++ b/integration/adapter-core/pom.xml @@ -38,6 +38,11 @@ ${jboss.logging.version} provided + + org.keycloak + keycloak-adapter-spi + provided + org.keycloak keycloak-core diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java index 0a73404ad940..f4eced9da91c 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthenticatedActionsHandler.java @@ -23,9 +23,9 @@ public class AuthenticatedActionsHandler { private static final Logger log = Logger.getLogger(AuthenticatedActionsHandler.class); protected KeycloakDeployment deployment; - protected HttpFacade facade; + protected OIDCHttpFacade facade; - public AuthenticatedActionsHandler(KeycloakDeployment deployment, HttpFacade facade) { + public AuthenticatedActionsHandler(KeycloakDeployment deployment, OIDCHttpFacade facade) { this.deployment = deployment; this.facade = facade; } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java index f5e145f8ca50..73d58bcf948e 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java @@ -34,7 +34,7 @@ public static void setTokenCookie(KeycloakDeployment deployment, HttpFacade faca } public static KeycloakPrincipal getPrincipalFromCookie(KeycloakDeployment deployment, HttpFacade facade, AdapterTokenStore tokenStore) { - HttpFacade.Cookie cookie = facade.getRequest().getCookie(AdapterConstants.KEYCLOAK_ADAPTER_STATE_COOKIE); + OIDCHttpFacade.Cookie cookie = facade.getRequest().getCookie(AdapterConstants.KEYCLOAK_ADAPTER_STATE_COOKIE); if (cookie == null) { log.debug("Not found adapter state cookie in current request"); return null; diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java index d91b134eb0b8..fa33363e0f7a 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java @@ -14,7 +14,6 @@ import org.keycloak.util.UriUtils; import java.io.IOException; -import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; @@ -93,12 +92,12 @@ protected boolean isRequestSecure() { return facade.getRequest().isSecure(); } - protected HttpFacade.Cookie getCookie(String cookieName) { + protected OIDCHttpFacade.Cookie getCookie(String cookieName) { return facade.getRequest().getCookie(cookieName); } protected String getCookieValue(String cookieName) { - HttpFacade.Cookie cookie = getCookie(cookieName); + OIDCHttpFacade.Cookie cookie = getCookie(cookieName); if (cookie == null) return null; return cookie.getValue(); } @@ -198,7 +197,7 @@ public boolean challenge(HttpFacade exchange) { } protected AuthChallenge checkStateCookie() { - HttpFacade.Cookie stateCookie = getCookie(deployment.getStateCookieName()); + OIDCHttpFacade.Cookie stateCookie = getCookie(deployment.getStateCookieName()); if (stateCookie == null) { log.warn("No state cookie"); diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/OIDCHttpFacade.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/OIDCHttpFacade.java new file mode 100755 index 000000000000..5b1cadcf4b47 --- /dev/null +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/OIDCHttpFacade.java @@ -0,0 +1,14 @@ +package org.keycloak.adapters; + +import org.keycloak.KeycloakSecurityContext; + +/** + * Bridge between core adapter and HTTP Engine + * + * @author Bill Burke + * @version $Revision: 1 $ + */ +public interface OIDCHttpFacade extends HttpFacade { + + KeycloakSecurityContext getSecurityContext(); +} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java b/integration/adapter-spi/src/main/java/org/keycloak/adapters/AuthChallenge.java similarity index 100% rename from integration/adapter-core/src/main/java/org/keycloak/adapters/AuthChallenge.java rename to integration/adapter-spi/src/main/java/org/keycloak/adapters/AuthChallenge.java diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AuthOutcome.java b/integration/adapter-spi/src/main/java/org/keycloak/adapters/AuthOutcome.java similarity index 100% rename from integration/adapter-core/src/main/java/org/keycloak/adapters/AuthOutcome.java rename to integration/adapter-spi/src/main/java/org/keycloak/adapters/AuthOutcome.java diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java b/integration/adapter-spi/src/main/java/org/keycloak/adapters/HttpFacade.java similarity index 94% rename from integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java rename to integration/adapter-spi/src/main/java/org/keycloak/adapters/HttpFacade.java index 336fa54cb338..90c2dc714fb9 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpFacade.java +++ b/integration/adapter-spi/src/main/java/org/keycloak/adapters/HttpFacade.java @@ -1,55 +1,20 @@ package org.keycloak.adapters; -import org.keycloak.KeycloakSecurityContext; - import javax.security.cert.X509Certificate; import java.io.InputStream; import java.io.OutputStream; import java.util.List; /** - * Bridge between core adapter and HTTP Engine - * * @author Bill Burke * @version $Revision: 1 $ */ public interface HttpFacade { + Request getRequest(); - public class Cookie { - protected String name; - protected String value; - protected int version; - protected String domain; - protected String path; - - public Cookie(String name, String value, int version, String domain, String path) { - this.name = name; - this.value = value; - this.version = version; - this.domain = domain; - this.path = path; - } - - public String getName() { - return name; - } - - public String getValue() { - return value; - } - - public int getVersion() { - return version; - } - - public String getDomain() { - return domain; - } + Response getResponse(); - public String getPath() { - return path; - } - } + X509Certificate[] getCertificateChain(); interface Request { @@ -93,8 +58,39 @@ interface Response { void end(); } - KeycloakSecurityContext getSecurityContext(); - Request getRequest(); - Response getResponse(); - X509Certificate[] getCertificateChain(); + public class Cookie { + protected String name; + protected String value; + protected int version; + protected String domain; + protected String path; + + public Cookie(String name, String value, int version, String domain, String path) { + this.name = name; + this.value = value; + this.version = version; + this.domain = domain; + this.path = path; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + public int getVersion() { + return version; + } + + public String getDomain() { + return domain; + } + + public String getPath() { + return path; + } + } } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/UserSessionManagement.java b/integration/adapter-spi/src/main/java/org/keycloak/adapters/UserSessionManagement.java similarity index 100% rename from integration/adapter-core/src/main/java/org/keycloak/adapters/UserSessionManagement.java rename to integration/adapter-spi/src/main/java/org/keycloak/adapters/UserSessionManagement.java diff --git a/integration/as7-eap6/as7-adapter/pom.xml b/integration/as7-eap6/as7-adapter/pom.xml index f7a66c03f98f..ee4e44ccf9a5 100755 --- a/integration/as7-eap6/as7-adapter/pom.xml +++ b/integration/as7-eap6/as7-adapter/pom.xml @@ -18,6 +18,10 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/installed/pom.xml b/integration/installed/pom.xml index f9e07b4f607b..5dc4b6069089 100755 --- a/integration/installed/pom.xml +++ b/integration/installed/pom.xml @@ -18,6 +18,10 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/jaxrs-oauth-client/pom.xml b/integration/jaxrs-oauth-client/pom.xml index a9769f59aca1..4147b1887925 100755 --- a/integration/jaxrs-oauth-client/pom.xml +++ b/integration/jaxrs-oauth-client/pom.xml @@ -31,6 +31,10 @@ keycloak-core provided + + org.keycloak + keycloak-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsHttpFacade.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsHttpFacade.java old mode 100644 new mode 100755 index f29935d9c4a3..2ff677f2f8ea --- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsHttpFacade.java +++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsHttpFacade.java @@ -11,13 +11,13 @@ import javax.ws.rs.core.SecurityContext; import org.keycloak.KeycloakSecurityContext; -import org.keycloak.adapters.HttpFacade; +import org.keycloak.adapters.OIDCHttpFacade; import org.keycloak.util.HostUtils; /** * @author Marek Posolda */ -public class JaxrsHttpFacade implements HttpFacade { +public class JaxrsHttpFacade implements OIDCHttpFacade { protected final ContainerRequestContext requestContext; protected final SecurityContext securityContext; @@ -31,7 +31,7 @@ public JaxrsHttpFacade(ContainerRequestContext containerRequestContext, Security this.securityContext = securityContext; } - protected class RequestFacade implements HttpFacade.Request { + protected class RequestFacade implements OIDCHttpFacade.Request { @Override public String getMethod() { @@ -90,7 +90,7 @@ public String getRemoteAddr() { } } - protected class ResponseFacade implements HttpFacade.Response { + protected class ResponseFacade implements OIDCHttpFacade.Response { private javax.ws.rs.core.Response.ResponseBuilder responseBuilder = javax.ws.rs.core.Response.status(204); diff --git a/integration/jboss-adapter-core/pom.xml b/integration/jboss-adapter-core/pom.xml index 0789bc0986b4..55424a9ad26f 100755 --- a/integration/jboss-adapter-core/pom.xml +++ b/integration/jboss-adapter-core/pom.xml @@ -24,6 +24,10 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/jetty/jetty-adapter-spi/pom.xml b/integration/jetty/jetty-adapter-spi/pom.xml new file mode 100755 index 000000000000..2737eef35d48 --- /dev/null +++ b/integration/jetty/jetty-adapter-spi/pom.xml @@ -0,0 +1,115 @@ + + + + keycloak-parent + org.keycloak + 1.5.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + + keycloak-jetty-adapter-spi + Keycloak Jetty Adapter SPI + + 8.1.16.v20140903 + + org.keycloak.adapters.jetty.core.* + + + org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional, + javax.servlet.*;version="[2.5,4)";resolution:=optional, + org.keycloak.*;version="${project.version}", + *;resolution:=optional + + + + + + + org.jboss.logging + jboss-logging + ${jboss.logging.version} + + + org.keycloak + keycloak-core + + + org.keycloak + keycloak-adapter-spi + + + org.eclipse.jetty + jetty-server + ${jetty9.version} + compile + + + + org.eclipse.jetty + jetty-util + ${jetty9.version} + compile + + + + org.eclipse.jetty + jetty-security + ${jetty9.version} + compile + + + + junit + junit + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + + + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + + + + + + diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java b/integration/jetty/jetty-adapter-spi/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java similarity index 96% rename from integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java rename to integration/jetty/jetty-adapter-spi/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java index c25629e58f70..8ffae79723ae 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java +++ b/integration/jetty/jetty-adapter-spi/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java @@ -1,6 +1,5 @@ package org.keycloak.adapters.jetty.core; -import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.HttpFacade; import org.keycloak.util.MultivaluedHashMap; import org.keycloak.util.UriUtils; @@ -25,6 +24,30 @@ public class JettyHttpFacade implements HttpFacade { protected ResponseFacade responseFacade = new ResponseFacade(); protected MultivaluedHashMap queryParameters; + public JettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) { + this.request = request; + this.response = response; + } + + @Override + public Request getRequest() { + return requestFacade; + } + + @Override + public Response getResponse() { + return responseFacade; + } + + @Override + public X509Certificate[] getCertificateChain() { + throw new IllegalStateException("Not supported yet"); + } + + public boolean isEnded() { + return responseFacade.isEnded(); + } + protected class RequestFacade implements Request { @Override public String getURI() { @@ -159,33 +182,4 @@ public boolean isEnded() { return ended; } } - - public JettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) { - this.request = request; - this.response = response; - } - - @Override - public Request getRequest() { - return requestFacade; - } - - @Override - public Response getResponse() { - return responseFacade; - } - - @Override - public KeycloakSecurityContext getSecurityContext() { - return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); - } - - @Override - public X509Certificate[] getCertificateChain() { - throw new IllegalStateException("Not supported yet"); - } - - public boolean isEnded() { - return responseFacade.isEnded(); - } } diff --git a/integration/jetty/jetty-core/pom.xml b/integration/jetty/jetty-core/pom.xml index 9caa98899e77..b69d3ccbb91b 100755 --- a/integration/jetty/jetty-core/pom.xml +++ b/integration/jetty/jetty-core/pom.xml @@ -35,6 +35,14 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-jetty-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java index bde5ad0acfee..c11f30a092e7 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java @@ -92,7 +92,7 @@ public void logoutCurrent(Request request) { AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getAttribute(AdapterDeploymentContext.class.getName()); KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName()); if (ksc != null) { - JettyHttpFacade facade = new JettyHttpFacade(request, null); + JettyHttpFacade facade = new OIDCJettyHttpFacade(request, null); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (ksc instanceof RefreshableKeycloakSecurityContext) { ((RefreshableKeycloakSecurityContext) ksc).logout(deployment); @@ -229,7 +229,7 @@ public Authentication validateRequest(ServletRequest req, ServletResponse res, b log.trace("*** authenticate"); } Request request = resolveRequest(req); - JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse) res); + OIDCJettyHttpFacade facade = new OIDCJettyHttpFacade(request, (HttpServletResponse) res); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (deployment == null || !deployment.isConfigured()) { log.debug("*** deployment isn't configured return false"); diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/OIDCJettyHttpFacade.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/OIDCJettyHttpFacade.java new file mode 100755 index 000000000000..3f6bd0b1e507 --- /dev/null +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/OIDCJettyHttpFacade.java @@ -0,0 +1,23 @@ +package org.keycloak.adapters.jetty.core; + +import org.keycloak.KeycloakSecurityContext; +import org.keycloak.adapters.OIDCHttpFacade; + +import javax.servlet.http.HttpServletResponse; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class OIDCJettyHttpFacade extends JettyHttpFacade implements OIDCHttpFacade { + + public OIDCJettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) { + super(request, response); + } + + @Override + public KeycloakSecurityContext getSecurityContext() { + return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); + } + +} diff --git a/integration/jetty/pom.xml b/integration/jetty/pom.xml index 2cb71df316ec..5230c8cd934f 100755 --- a/integration/jetty/pom.xml +++ b/integration/jetty/pom.xml @@ -14,6 +14,7 @@ pom + jetty-adapter-spi jetty-core jetty8.1 jetty9.2 diff --git a/integration/pom.xml b/integration/pom.xml index 413dfedee849..81a2028f0a97 100755 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -14,6 +14,7 @@ pom + adapter-spi adapter-core jaxrs-oauth-client servlet-oauth-client @@ -21,6 +22,7 @@ tomcat as7-eap6 jetty + undertow-adapter-spi undertow wildfly js diff --git a/integration/servlet-oauth-client/pom.xml b/integration/servlet-oauth-client/pom.xml index b5c869ffbe21..6ac5b2b38453 100755 --- a/integration/servlet-oauth-client/pom.xml +++ b/integration/servlet-oauth-client/pom.xml @@ -24,6 +24,10 @@ keycloak-core provided + + org.keycloak + keycloak-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java index 72501acbf958..e2afb94df20e 100755 --- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java +++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java @@ -3,15 +3,13 @@ import org.keycloak.KeycloakSecurityContext; import org.keycloak.OAuth2Constants; import org.keycloak.adapters.AdapterDeploymentContext; -import org.keycloak.adapters.HttpFacade; import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.OIDCHttpFacade; import org.keycloak.adapters.ServerRequest; -import org.keycloak.enums.RelativeUrlsUsed; import org.keycloak.jose.jws.JWSInput; import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.IDToken; import org.keycloak.util.KeycloakUriBuilder; -import org.keycloak.util.UriUtils; import javax.security.cert.X509Certificate; import javax.servlet.http.Cookie; @@ -167,7 +165,7 @@ private KeycloakDeployment resolveDeployment(KeycloakDeployment baseDeployment, } - public static class ServletFacade implements HttpFacade { + public static class ServletFacade implements OIDCHttpFacade { private final HttpServletRequest servletRequest; diff --git a/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java b/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java old mode 100644 new mode 100755 index c5834c27dc90..6a37addfce28 --- a/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java +++ b/integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java @@ -1,8 +1,8 @@ package org.keycloak.adapters.springboot; -import org.keycloak.adapters.HttpFacade; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.KeycloakDeploymentBuilder; +import org.keycloak.adapters.OIDCHttpFacade; import org.keycloak.representations.adapters.config.AdapterConfig; public class KeycloakSpringBootConfigResolver implements org.keycloak.adapters.KeycloakConfigResolver { @@ -12,7 +12,7 @@ public class KeycloakSpringBootConfigResolver implements org.keycloak.adapters.K private static AdapterConfig adapterConfig; @Override - public KeycloakDeployment resolve(HttpFacade.Request request) { + public KeycloakDeployment resolve(OIDCHttpFacade.Request request) { if (keycloakDeployment != null) { return keycloakDeployment; } diff --git a/integration/spring-security/pom.xml b/integration/spring-security/pom.xml index c5055e55eafa..49f25f4d5bc0 100755 --- a/integration/spring-security/pom.xml +++ b/integration/spring-security/pom.xml @@ -26,6 +26,10 @@ keycloak-core ${project.version} + + org.keycloak + keycloak-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/SimpleHttpFacade.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/SimpleHttpFacade.java old mode 100644 new mode 100755 index 8c7a5b0c3b35..b8d780079b0d --- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/SimpleHttpFacade.java +++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/SimpleHttpFacade.java @@ -1,9 +1,7 @@ package org.keycloak.adapters.springsecurity.facade; import org.keycloak.KeycloakSecurityContext; -import org.keycloak.adapters.HttpFacade; -import org.keycloak.adapters.springsecurity.facade.WrappedHttpServletRequest; -import org.keycloak.adapters.springsecurity.facade.WrappedHttpServletResponse; +import org.keycloak.adapters.OIDCHttpFacade; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.Assert; @@ -13,12 +11,12 @@ import javax.servlet.http.HttpServletResponse; /** - * Simple {@link HttpFacade} wrapping an {@link HttpServletRequest} and {@link HttpServletResponse}. + * Simple {@link org.keycloak.adapters.OIDCHttpFacade} wrapping an {@link HttpServletRequest} and {@link HttpServletResponse}. * * @author Scott Rossillo * @version $Revision: 1 $ */ -public class SimpleHttpFacade implements HttpFacade { +public class SimpleHttpFacade implements OIDCHttpFacade { private final HttpServletRequest request; private final HttpServletResponse response; diff --git a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/package-info.java b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/package-info.java old mode 100644 new mode 100755 index 586dcbadc65a..50d06684b58c --- a/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/package-info.java +++ b/integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/package-info.java @@ -1,4 +1,4 @@ /** - * Provides an {@link org.keycloak.adapters.HttpFacade} implementation. + * Provides an {@link org.keycloak.adapters.OIDCHttpFacade} implementation. */ package org.keycloak.adapters.springsecurity.facade; \ No newline at end of file diff --git a/integration/tomcat/pom.xml b/integration/tomcat/pom.xml index 1ec282f5aeec..7e912923c0df 100755 --- a/integration/tomcat/pom.xml +++ b/integration/tomcat/pom.xml @@ -14,6 +14,7 @@ pom + tomcat-adapter-spi tomcat-core tomcat6 tomcat7 diff --git a/integration/tomcat/tomcat-adapter-spi/pom.xml b/integration/tomcat/tomcat-adapter-spi/pom.xml new file mode 100755 index 000000000000..d8f074fe58a5 --- /dev/null +++ b/integration/tomcat/tomcat-adapter-spi/pom.xml @@ -0,0 +1,69 @@ + + + + keycloak-parent + org.keycloak + 1.5.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + + keycloak-tomcat-adapter-spi + Keycloak Tomcat Adapter SPI + + + + 6.0.41 + + + + + + org.jboss.logging + jboss-logging + ${jboss.logging.version} + + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-core + + + + org.apache.tomcat + catalina + ${tomcat.version} + compile + + + + junit + junit + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + + + + + + diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java b/integration/tomcat/tomcat-adapter-spi/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java similarity index 94% rename from integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java rename to integration/tomcat/tomcat-adapter-spi/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java index ef8a41e9dc47..a72ad5d4d3f7 100755 --- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java +++ b/integration/tomcat/tomcat-adapter-spi/src/main/java/org/keycloak/adapters/tomcat/CatalinaHttpFacade.java @@ -1,6 +1,5 @@ package org.keycloak.adapters.tomcat; -import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.HttpFacade; import org.keycloak.util.MultivaluedHashMap; import org.keycloak.util.ServerCookie; @@ -26,6 +25,30 @@ public class CatalinaHttpFacade implements HttpFacade { protected ResponseFacade responseFacade = new ResponseFacade(); protected MultivaluedHashMap queryParameters; + public CatalinaHttpFacade(HttpServletResponse response, org.apache.catalina.connector.Request request) { + this.response = response; + this.request = request; + } + + @Override + public Request getRequest() { + return requestFacade; + } + + @Override + public Response getResponse() { + return responseFacade; + } + + @Override + public X509Certificate[] getCertificateChain() { + throw new IllegalStateException("Not supported yet"); + } + + public boolean isEnded() { + return responseFacade.isEnded(); + } + protected class RequestFacade implements Request { @Override public String getURI() { @@ -157,33 +180,4 @@ public boolean isEnded() { return ended; } } - - public CatalinaHttpFacade(org.apache.catalina.connector.Request request, HttpServletResponse response) { - this.request = request; - this.response = response; - } - - @Override - public Request getRequest() { - return requestFacade; - } - - @Override - public Response getResponse() { - return responseFacade; - } - - @Override - public KeycloakSecurityContext getSecurityContext() { - return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); - } - - @Override - public X509Certificate[] getCertificateChain() { - throw new IllegalStateException("Not supported yet"); - } - - public boolean isEnded() { - return responseFacade.isEnded(); - } } diff --git a/integration/tomcat/tomcat-core/pom.xml b/integration/tomcat/tomcat-core/pom.xml index d57cec9c66c6..3f9566665547 100755 --- a/integration/tomcat/tomcat-core/pom.xml +++ b/integration/tomcat/tomcat-core/pom.xml @@ -28,6 +28,14 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-tomcat-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java index 80663c888dff..3347978eb6d5 100755 --- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java +++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AbstractKeycloakAuthenticatorValve.java @@ -5,13 +5,9 @@ import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; import org.apache.catalina.Manager; -import org.apache.catalina.authenticator.Constants; import org.apache.catalina.authenticator.FormAuthenticator; -import org.apache.catalina.authenticator.SavedRequest; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; -import org.apache.catalina.deploy.LoginConfig; -import org.apache.tomcat.util.buf.ByteChunk; import org.keycloak.KeycloakSecurityContext; import org.keycloak.constants.AdapterConstants; import org.keycloak.adapters.AdapterDeploymentContext; @@ -28,15 +24,12 @@ import javax.servlet.ServletContext; import javax.servlet.ServletException; -import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.util.Enumeration; -import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; import org.keycloak.adapters.KeycloakConfigResolver; @@ -71,7 +64,7 @@ public void lifecycleEvent(LifecycleEvent event) { protected void logoutInternal(Request request) { KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); if (ksc != null) { - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, null); + CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, null); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (ksc instanceof RefreshableKeycloakSecurityContext) { ((RefreshableKeycloakSecurityContext) ksc).logout(deployment); @@ -164,7 +157,7 @@ private static InputStream getConfigInputStream(Context context) { @Override public void invoke(Request request, Response response) throws IOException, ServletException { try { - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); + CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response); Manager sessionManager = request.getContext().getManager(); CatalinaUserSessionManagementWrapper sessionManagementWrapper = new CatalinaUserSessionManagementWrapper(userSessionManagement, sessionManager); PreAuthActionsHandler handler = new PreAuthActionsHandler(sessionManagementWrapper, deploymentContext, facade); @@ -181,7 +174,7 @@ public void invoke(Request request, Response response) throws IOException, Servl protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException; protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException { - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); + CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (deployment == null || !deployment.isConfigured()) { return false; diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java index 8728f36daf3b..6b42b85b47b4 100755 --- a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java +++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/AuthenticatedActionsValve.java @@ -39,10 +39,10 @@ public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Val @Override public void invoke(Request request, Response response) throws IOException, ServletException { log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI()); - CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response); + CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (deployment != null && deployment.isConfigured()) { - AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new CatalinaHttpFacade(request, response)); + AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new OIDCCatalinaHttpFacade(request, response)); if (handler.handledRequest()) { return; } diff --git a/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/OIDCCatalinaHttpFacade.java b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/OIDCCatalinaHttpFacade.java new file mode 100755 index 000000000000..b77337e81451 --- /dev/null +++ b/integration/tomcat/tomcat-core/src/main/java/org/keycloak/adapters/tomcat/OIDCCatalinaHttpFacade.java @@ -0,0 +1,23 @@ +package org.keycloak.adapters.tomcat; + +import org.keycloak.KeycloakSecurityContext; +import org.keycloak.adapters.OIDCHttpFacade; + +import javax.servlet.http.HttpServletResponse; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class OIDCCatalinaHttpFacade extends CatalinaHttpFacade implements OIDCHttpFacade{ + + public OIDCCatalinaHttpFacade(org.apache.catalina.connector.Request request, HttpServletResponse response) { + super(response, request); + } + + @Override + public KeycloakSecurityContext getSecurityContext() { + return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName()); + } + +} diff --git a/integration/undertow-adapter-spi/pom.xml b/integration/undertow-adapter-spi/pom.xml new file mode 100755 index 000000000000..120f754bb1ff --- /dev/null +++ b/integration/undertow-adapter-spi/pom.xml @@ -0,0 +1,65 @@ + + + + keycloak-parent + org.keycloak + 1.5.0.Final-SNAPSHOT + ../../pom.xml + + 4.0.0 + + keycloak-undertow-adapter-spi + Keycloak Undertow Integration + + + + + org.jboss.logging + jboss-logging + ${jboss.logging.version} + provided + + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-core + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + provided + + + io.undertow + undertow-servlet + provided + + + io.undertow + undertow-core + provided + + + junit + junit + test + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java b/integration/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java similarity index 84% rename from integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java rename to integration/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java index c864760e9a25..d2c4b442e670 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java +++ b/integration/undertow-adapter-spi/src/main/java/org/keycloak/adapters/undertow/UndertowHttpFacade.java @@ -1,27 +1,9 @@ -/* - * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors - * as indicated by the @author tags. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ package org.keycloak.adapters.undertow; import io.undertow.server.HttpServerExchange; import io.undertow.server.handlers.CookieImpl; -import io.undertow.util.AttachmentKey; import io.undertow.util.Headers; import io.undertow.util.HttpString; -import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.HttpFacade; import org.keycloak.util.KeycloakUriBuilder; @@ -39,13 +21,36 @@ * @author Bill Burke * @version $Revision: 1 $ */ -public class UndertowHttpFacade implements HttpFacade { - public static final AttachmentKey KEYCLOAK_SECURITY_CONTEXT_KEY = AttachmentKey.create(KeycloakSecurityContext.class); - +public abstract class UndertowHttpFacade implements HttpFacade { protected HttpServerExchange exchange; protected RequestFacade requestFacade = new RequestFacade(); protected ResponseFacade responseFacade = new ResponseFacade(); + public UndertowHttpFacade(HttpServerExchange exchange) { + this.exchange = exchange; + } + + @Override + public Request getRequest() { + return requestFacade; + } + + @Override + public Response getResponse() { + return responseFacade; + } + + @Override + public X509Certificate[] getCertificateChain() { + X509Certificate[] chain = new X509Certificate[0]; + try { + chain = exchange.getConnection().getSslSessionInfo().getPeerCertificateChain(); + } catch (Exception ignore) { + + } + return chain; + } + protected class RequestFacade implements Request { @Override public String getURI() { @@ -178,34 +183,4 @@ public void end() { exchange.endExchange(); } } - - public UndertowHttpFacade(HttpServerExchange exchange) { - this.exchange = exchange; - } - - @Override - public Request getRequest() { - return requestFacade; - } - - @Override - public Response getResponse() { - return responseFacade; - } - - @Override - public KeycloakSecurityContext getSecurityContext() { - return exchange.getAttachment(KEYCLOAK_SECURITY_CONTEXT_KEY); - } - - @Override - public X509Certificate[] getCertificateChain() { - X509Certificate[] chain = new X509Certificate[0]; - try { - chain = exchange.getConnection().getSslSessionInfo().getPeerCertificateChain(); - } catch (Exception ignore) { - - } - return chain; - } } diff --git a/integration/undertow/pom.xml b/integration/undertow/pom.xml index d25d7ed3b42e..92ed9657380b 100755 --- a/integration/undertow/pom.xml +++ b/integration/undertow/pom.xml @@ -24,6 +24,14 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + + + org.keycloak + keycloak-undertow-adapter-spi + org.keycloak keycloak-adapter-core diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java index 892343b82a36..71382ff891fa 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowKeycloakAuthMech.java @@ -21,18 +21,14 @@ import io.undertow.security.api.SecurityContext; import io.undertow.security.api.SecurityNotification; import io.undertow.server.HttpServerExchange; -import io.undertow.server.session.Session; import io.undertow.util.AttachmentKey; import io.undertow.util.Headers; -import io.undertow.util.Sessions; import io.undertow.util.StatusCodes; -import org.keycloak.KeycloakPrincipal; import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.AdapterTokenStore; import org.keycloak.adapters.AuthChallenge; import org.keycloak.adapters.AuthOutcome; -import org.keycloak.adapters.CookieTokenStore; import org.keycloak.adapters.HttpFacade; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.RefreshableKeycloakSecurityContext; @@ -64,7 +60,7 @@ public ChallengeResult sendChallenge(HttpServerExchange exchange, SecurityContex Integer code = servePage(exchange, errorPage); return new ChallengeResult(true, code); } - UndertowHttpFacade facade = new UndertowHttpFacade(exchange); + UndertowHttpFacade facade = new OIDCUndertowHttpFacade(exchange); if (challenge.challenge(facade)) { return new ChallengeResult(true, exchange.getResponseCode()); } @@ -93,9 +89,9 @@ public void handleNotification(SecurityNotification notification) { if (notification.getEventType() != SecurityNotification.EventType.LOGGED_OUT) return; HttpServerExchange exchange = notification.getExchange(); - UndertowHttpFacade facade = new UndertowHttpFacade(exchange); + UndertowHttpFacade facade = new OIDCUndertowHttpFacade(exchange); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); - KeycloakSecurityContext ksc = exchange.getAttachment(UndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY); + KeycloakSecurityContext ksc = exchange.getAttachment(OIDCUndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY); if (ksc != null && ksc instanceof RefreshableKeycloakSecurityContext) { ((RefreshableKeycloakSecurityContext) ksc).logout(deployment); } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java index f0e467b0c2e3..84c5fddd1871 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AbstractUndertowRequestAuthenticator.java @@ -48,7 +48,7 @@ public AbstractUndertowRequestAuthenticator(HttpFacade facade, KeycloakDeploymen } protected void propagateKeycloakContext(KeycloakUndertowAccount account) { - exchange.putAttachment(UndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY, account.getKeycloakSecurityContext()); + exchange.putAttachment(OIDCUndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY, account.getKeycloakSecurityContext()); } @Override diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OIDCUndertowHttpFacade.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OIDCUndertowHttpFacade.java new file mode 100755 index 000000000000..90633996215f --- /dev/null +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OIDCUndertowHttpFacade.java @@ -0,0 +1,40 @@ +/* + * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @author tags. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.keycloak.adapters.undertow; + +import io.undertow.server.HttpServerExchange; +import io.undertow.util.AttachmentKey; +import org.keycloak.KeycloakSecurityContext; +import org.keycloak.adapters.OIDCHttpFacade; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class OIDCUndertowHttpFacade extends UndertowHttpFacade implements OIDCHttpFacade { + public static final AttachmentKey KEYCLOAK_SECURITY_CONTEXT_KEY = AttachmentKey.create(KeycloakSecurityContext.class); + + public OIDCUndertowHttpFacade(HttpServerExchange exchange) { + super(exchange); + } + + @Override + public KeycloakSecurityContext getSecurityContext() { + return exchange.getAttachment(KEYCLOAK_SECURITY_CONTEXT_KEY); + } + +} diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java index f4b6ef3fb9fd..bfa2cb346ba6 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java @@ -16,7 +16,6 @@ */ package org.keycloak.adapters.undertow; -import io.undertow.security.api.AuthenticationMechanism; import io.undertow.security.api.SecurityContext; import io.undertow.server.HttpServerExchange; import io.undertow.servlet.api.ConfidentialPortManager; @@ -25,7 +24,6 @@ import org.jboss.logging.Logger; import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.AdapterTokenStore; -import org.keycloak.adapters.AuthChallenge; import org.keycloak.adapters.HttpFacade; import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.NodesRegistrationManagement; @@ -81,7 +79,7 @@ protected Integer servePage(HttpServerExchange exchange, String location) { @Override public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) { - UndertowHttpFacade facade = new UndertowHttpFacade(exchange); + UndertowHttpFacade facade = new OIDCUndertowHttpFacade(exchange); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (!deployment.isConfigured()) { return AuthenticationMechanismOutcome.NOT_ATTEMPTED; diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java index 61e66c42c315..362cdb06e2be 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java @@ -61,7 +61,7 @@ protected ServletPreAuthActionsHandler(AdapterDeploymentContext deploymentContex @Override public void handleRequest(HttpServerExchange exchange) throws Exception { - UndertowHttpFacade facade = new UndertowHttpFacade(exchange); + UndertowHttpFacade facade = new OIDCUndertowHttpFacade(exchange); final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, servletRequestContext.getDeployment().getSessionManager()); PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deploymentContext, facade); diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java index a21272e02ed9..4e7590f08555 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java @@ -57,7 +57,7 @@ public UndertowAuthenticatedActionsHandler(AdapterDeploymentContext deploymentCo @Override public void handleRequest(HttpServerExchange exchange) throws Exception { - UndertowHttpFacade facade = new UndertowHttpFacade(exchange); + OIDCUndertowHttpFacade facade = new OIDCUndertowHttpFacade(exchange); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (deployment != null && deployment.isConfigured()) { AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, facade); diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java index b55067b1d4b1..85b75813e1f6 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticationMechanism.java @@ -25,7 +25,7 @@ public UndertowAuthenticationMechanism(AdapterDeploymentContext deploymentContex @Override public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) { - UndertowHttpFacade facade = new UndertowHttpFacade(exchange); + UndertowHttpFacade facade = new OIDCUndertowHttpFacade(exchange); KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade); if (!deployment.isConfigured()) { return AuthenticationMechanismOutcome.NOT_ATTEMPTED; diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java index a68f39f9d9d5..77194e1dc027 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowPreAuthActionsHandler.java @@ -47,7 +47,7 @@ public UndertowPreAuthActionsHandler(AdapterDeploymentContext deploymentContext, @Override public void handleRequest(HttpServerExchange exchange) throws Exception { - UndertowHttpFacade facade = new UndertowHttpFacade(exchange); + UndertowHttpFacade facade = new OIDCUndertowHttpFacade(exchange); SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, sessionManager); PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deploymentContext, facade); if (handler.handleRequest()) return; diff --git a/integration/wildfly/wildfly-adapter/pom.xml b/integration/wildfly/wildfly-adapter/pom.xml index 6517e857cc44..101b398d6dbb 100755 --- a/integration/wildfly/wildfly-adapter/pom.xml +++ b/integration/wildfly/wildfly-adapter/pom.xml @@ -24,10 +24,18 @@ org.keycloak keycloak-core + + org.keycloak + keycloak-adapter-spi + org.keycloak keycloak-adapter-core + + org.keycloak + keycloak-undertow-adapter-spi + org.keycloak keycloak-undertow-adapter diff --git a/pom.xml b/pom.xml index c9e3f76ff8b5..a35d56f56273 100755 --- a/pom.xml +++ b/pom.xml @@ -765,6 +765,11 @@ keycloak-email-freemarker ${project.version} + + org.keycloak + keycloak-adapter-spi + ${project.version} + org.keycloak keycloak-adapter-core @@ -795,6 +800,11 @@ keycloak-jboss-adapter-core ${project.version} + + org.keycloak + keycloak-jetty-adapter-spi + ${project.version} + org.keycloak keycloak-jetty-core @@ -865,6 +875,11 @@ keycloak-spring-boot-adapter ${project.version} + + org.keycloak + keycloak-tomcat-adapter-spi + ${project.version} + org.keycloak keycloak-tomcat-core-adapter @@ -885,6 +900,11 @@ keycloak-tomcat8-adapter ${project.version} + + org.keycloak + keycloak-undertow-adapter-spi + ${project.version} + org.keycloak keycloak-undertow-adapter diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/BaseSAML2BindingBuilder.java similarity index 77% rename from saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java rename to saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/BaseSAML2BindingBuilder.java index c377206f5015..efb8e40d4769 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder2.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/BaseSAML2BindingBuilder.java @@ -11,16 +11,13 @@ import org.keycloak.saml.processing.core.util.XMLEncryptionUtil; import org.keycloak.saml.processing.web.util.PostBindingUtil; import org.keycloak.saml.processing.web.util.RedirectBindingUtil; +import org.keycloak.util.KeycloakUriBuilder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; -import javax.ws.rs.core.CacheControl; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.namespace.QName; import java.io.IOException; @@ -31,15 +28,15 @@ import java.security.Signature; import java.security.cert.X509Certificate; -import static org.keycloak.util.HtmlUtils.escapeAttribute; import static org.keycloak.saml.common.util.StringUtil.isNotNull; +import static org.keycloak.util.HtmlUtils.escapeAttribute; /** * @author Bill Burke * @version $Revision: 1 $ */ -public class SAML2BindingBuilder2 { - protected static final Logger logger = Logger.getLogger(SAML2BindingBuilder2.class); +public class BaseSAML2BindingBuilder { + protected static final Logger logger = Logger.getLogger(BaseSAML2BindingBuilder.class); protected KeyPair signingKeyPair; protected X509Certificate signingCertificate; @@ -116,17 +113,19 @@ public T relayState(String relayState) { return (T)this; } - public class PostBindingBuilder { + public static class BasePostBindingBuilder { protected Document document; + protected BaseSAML2BindingBuilder builder; - public PostBindingBuilder(Document document) throws ProcessingException { - if (encrypt) encryptDocument(document); + public BasePostBindingBuilder(BaseSAML2BindingBuilder builder, Document document) throws ProcessingException { + this.builder = builder; + if (builder.encrypt) builder.encryptDocument(document); this.document = document; - if (signAssertions) { - signAssertion(document); + if (builder.signAssertions) { + builder.signAssertion(document); } - if (sign) { - signDocument(document); + if (builder.sign) { + builder.signDocument(document); } } @@ -137,24 +136,28 @@ public String encoded() throws ProcessingException, ConfigurationException, IOEx public Document getDocument() { return document; } - - public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException { - return buildResponse(document, actionUrl, true); + public String getHtmlResponse(String actionUrl) throws ProcessingException, ConfigurationException, IOException { + String str = builder.buildHtmlPostResponse(document, actionUrl, false); + return str; } - public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException { - return buildResponse(document, actionUrl, false); + public String getHtmlRequest(String actionUrl) throws ProcessingException, ConfigurationException, IOException { + String str = builder.buildHtmlPostResponse(document, actionUrl, true); + return str; } + } - public class RedirectBindingBuilder { + public static class BaseRedirectBindingBuilder { protected Document document; + protected BaseSAML2BindingBuilder builder; - public RedirectBindingBuilder(Document document) throws ProcessingException { - if (encrypt) encryptDocument(document); + public BaseRedirectBindingBuilder(BaseSAML2BindingBuilder builder, Document document) throws ProcessingException { + this.builder = builder; + if (builder.encrypt) builder.encryptDocument(document); this.document = document; - if (signAssertions) { - signAssertion(document); + if (builder.signAssertions) { + builder.signAssertion(document); } } @@ -168,26 +171,8 @@ public URI responseUri(String redirectUri, boolean asRequest) throws Configurati samlParameterName = GeneralConstants.SAML_REQUEST_KEY; } - return generateRedirectUri(samlParameterName, redirectUri, document); - } - public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException { - return response(redirectUri, false); - } - - public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException { - return response(redirect, true); - } - - private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { - URI uri = responseUri(redirectUri, asRequest); - if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString()); - CacheControl cacheControl = new CacheControl(); - cacheControl.setNoCache(true); - return Response.status(302).location(uri) - .header("Pragma", "no-cache") - .header("Cache-Control", "no-cache, no-store").build(); + return builder.generateRedirectUri(samlParameterName, redirectUri, document); } - } @@ -272,16 +257,6 @@ protected void signAssertion(Document samlDocument) throws ProcessingException { } - protected Response buildResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { - String str = buildHtmlPostResponse(responseDoc, actionUrl, asRequest); - - CacheControl cacheControl = new CacheControl(); - cacheControl.setNoCache(true); - return Response.ok(str, MediaType.TEXT_HTML_TYPE) - .header("Pragma", "no-cache") - .header("Cache-Control", "no-cache, no-store").build(); - } - protected String buildHtmlPostResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { byte[] responseBytes = org.keycloak.saml.common.util.DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8"); String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes)); @@ -301,7 +276,7 @@ protected String buildHtml(String samlResponse, String actionUrl, boolean asRequ builder.append(""); builder.append(""); - builder.append("HTTP Post Binding Response (Response)"); + builder.append("SAML HTTP Post Binding"); builder.append(""); builder.append(""); @@ -332,7 +307,7 @@ protected String base64Encoded(Document document) throws ConfigurationException, protected URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException { - UriBuilder builder = UriBuilder.fromUri(redirectUri) + KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(redirectUri) .replaceQuery(null) .queryParam(samlParameterName, base64Encoded(document)); if (relayState != null) { @@ -358,13 +333,4 @@ protected URI generateRedirectUri(String samlParameterName, String redirectUri, return builder.build(); } - public RedirectBindingBuilder redirectBinding(Document document) throws ProcessingException { - return new RedirectBindingBuilder(document); - } - - public PostBindingBuilder postBinding(Document document) throws ProcessingException { - return new PostBindingBuilder(document); - } - - -} + } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java new file mode 100755 index 000000000000..fc2b5e954ab5 --- /dev/null +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/JaxrsSAML2BindingBuilder.java @@ -0,0 +1,77 @@ +package org.keycloak.protocol.saml; + +import org.keycloak.saml.common.exceptions.ConfigurationException; +import org.keycloak.saml.common.exceptions.ProcessingException; +import org.w3c.dom.Document; + +import javax.ws.rs.core.CacheControl; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.net.URI; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class JaxrsSAML2BindingBuilder extends BaseSAML2BindingBuilder { + public static class PostBindingBuilder extends BasePostBindingBuilder { + public PostBindingBuilder(JaxrsSAML2BindingBuilder builder, Document document) throws ProcessingException { + super(builder, document); + } + public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException { + return buildResponse(document, actionUrl, true); + } + public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException { + return buildResponse(document, actionUrl, false); + } + protected Response buildResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { + String str = builder.buildHtmlPostResponse(responseDoc, actionUrl, asRequest); + + CacheControl cacheControl = new CacheControl(); + cacheControl.setNoCache(true); + return Response.ok(str, MediaType.TEXT_HTML_TYPE) + .header("Pragma", "no-cache") + .header("Cache-Control", "no-cache, no-store").build(); + } + + + } + + public static class RedirectBindingBuilder extends BaseRedirectBindingBuilder { + public RedirectBindingBuilder(JaxrsSAML2BindingBuilder builder, Document document) throws ProcessingException { + super(builder, document); + } + + public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException { + return response(redirectUri, false); + } + + public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException { + return response(redirect, true); + } + + private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { + URI uri = responseUri(redirectUri, asRequest); + if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString()); + CacheControl cacheControl = new CacheControl(); + cacheControl.setNoCache(true); + return Response.status(302).location(uri) + .header("Pragma", "no-cache") + .header("Cache-Control", "no-cache, no-store").build(); + } + + } + + public RedirectBindingBuilder redirectBinding(Document document) throws ProcessingException { + return new RedirectBindingBuilder(this, document); + } + + public PostBindingBuilder postBinding(Document document) throws ProcessingException { + return new PostBindingBuilder(this, document); + } + + + + +} diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2AuthnRequestBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2AuthnRequestBuilder.java index 353ef43482d1..8dd3436f994e 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2AuthnRequestBuilder.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2AuthnRequestBuilder.java @@ -30,9 +30,21 @@ /** * @author pedroigor */ -public class SAML2AuthnRequestBuilder extends SAML2BindingBuilder { +public class SAML2AuthnRequestBuilder { private final AuthnRequestType authnRequestType; + protected String destination; + protected String issuer; + + public SAML2AuthnRequestBuilder destination(String destination) { + this.destination = destination; + return this; + } + + public SAML2AuthnRequestBuilder issuer(String issuer) { + this.issuer = issuer; + return this; + } public SAML2AuthnRequestBuilder() { try { @@ -62,23 +74,7 @@ public SAML2AuthnRequestBuilder protocolBinding(String protocolBinding) { return this; } - public RedirectBindingBuilder redirectBinding() { - try { - return new RedirectBindingBuilder(toDocument()); - } catch (Exception e) { - throw new RuntimeException("Could not build authn request for post binding.", e); - } - } - - public PostBindingBuilder postBinding() { - try { - return new PostBindingBuilder(toDocument()); - } catch (Exception e) { - throw new RuntimeException("Could not build authn request for post binding.", e); - } - } - - private Document toDocument() { + public Document toDocument() { try { AuthnRequestType authnRequestType = this.authnRequestType; diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java deleted file mode 100755 index d2f354592d6d..000000000000 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2BindingBuilder.java +++ /dev/null @@ -1,389 +0,0 @@ -package org.keycloak.protocol.saml; - -import org.jboss.logging.Logger; -import org.keycloak.saml.common.constants.GeneralConstants; -import org.keycloak.saml.common.constants.JBossSAMLConstants; -import org.keycloak.saml.common.constants.JBossSAMLURIConstants; -import org.keycloak.saml.common.exceptions.ConfigurationException; -import org.keycloak.saml.common.exceptions.ProcessingException; -import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature; -import org.keycloak.saml.processing.core.saml.v2.util.DocumentUtil; -import org.keycloak.saml.processing.core.util.XMLEncryptionUtil; -import org.keycloak.saml.processing.web.util.PostBindingUtil; -import org.keycloak.saml.processing.web.util.RedirectBindingUtil; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; -import javax.ws.rs.core.CacheControl; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.namespace.QName; -import java.io.IOException; -import java.net.URI; -import java.security.KeyPair; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.Signature; -import java.security.cert.X509Certificate; - -import static org.keycloak.util.HtmlUtils.escapeAttribute; -import static org.keycloak.saml.common.util.StringUtil.isNotNull; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class SAML2BindingBuilder { - protected static final Logger logger = Logger.getLogger(SAML2BindingBuilder.class); - public static final String RELAY_STATE = "RelayState"; - - protected KeyPair signingKeyPair; - protected X509Certificate signingCertificate; - protected boolean sign; - protected boolean signAssertions; - protected SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA1; - protected String relayState; - protected String destination; - protected String issuer; - protected int encryptionKeySize = 128; - protected PublicKey encryptionPublicKey; - protected String encryptionAlgorithm = "AES"; - protected boolean encrypt; - protected String canonicalizationMethodType = CanonicalizationMethod.EXCLUSIVE; - - public T canonicalizationMethod(String method) { - this.canonicalizationMethodType = method; - return (T)this; - } - - public T signDocument() { - this.sign = true; - return (T)this; - } - - public T signAssertions() { - this.signAssertions = true; - return (T)this; - } - - public T signWith(KeyPair keyPair) { - this.signingKeyPair = keyPair; - return (T)this; - } - - public T signWith(PrivateKey privateKey, PublicKey publicKey) { - this.signingKeyPair = new KeyPair(publicKey, privateKey); - return (T)this; - } - - public T signWith(KeyPair keyPair, X509Certificate cert) { - this.signingKeyPair = keyPair; - this.signingCertificate = cert; - return (T)this; - } - - public T signWith(PrivateKey privateKey, PublicKey publicKey, X509Certificate cert) { - this.signingKeyPair = new KeyPair(publicKey, privateKey); - this.signingCertificate = cert; - return (T)this; - } - - public T signatureAlgorithm(SignatureAlgorithm alg) { - this.signatureAlgorithm = alg; - return (T)this; - } - - public T encrypt(PublicKey publicKey) { - encrypt = true; - encryptionPublicKey = publicKey; - return (T)this; - } - - public T encryptionAlgorithm(String alg) { - this.encryptionAlgorithm = alg; - return (T)this; - } - - public T encryptionKeySize(int size) { - this.encryptionKeySize = size; - return (T)this; - } - - public T destination(String destination) { - this.destination = destination; - return (T)this; - } - - public T issuer(String issuer) { - this.issuer = issuer; - return (T)this; - } - - public T relayState(String relayState) { - this.relayState = relayState; - return (T)this; - } - - public class PostBindingBuilder { - protected Document document; - - public PostBindingBuilder(Document document) throws ProcessingException { - this.document = document; - if (signAssertions) { - signAssertion(document); - } - if (sign) { - signDocument(document); - } - } - - public String encoded() throws ProcessingException, ConfigurationException, IOException { - byte[] responseBytes = DocumentUtil.getDocumentAsString(document).getBytes("UTF-8"); - return PostBindingUtil.base64Encode(new String(responseBytes)); - } - public Document getDocument() { - return document; - } - - public Response request() throws ConfigurationException, ProcessingException, IOException { - return buildResponse(document, destination, true); - } - public Response request(String actionUrl) throws ConfigurationException, ProcessingException, IOException { - return buildResponse(document, actionUrl, true); - } - public Response response() throws ConfigurationException, ProcessingException, IOException { - return buildResponse(document, destination, false); - } - public Response response(String actionUrl) throws ConfigurationException, ProcessingException, IOException { - return buildResponse(document, actionUrl, false); - } - } - - - public class RedirectBindingBuilder { - protected Document document; - - public RedirectBindingBuilder(Document document) throws ProcessingException { - this.document = document; - if (signAssertions) { - signAssertion(document); - } - } - - public Document getDocument() { - return document; - } - public URI responseUri(String redirectUri, boolean asRequest) throws ConfigurationException, ProcessingException, IOException { - String samlParameterName = GeneralConstants.SAML_RESPONSE_KEY; - - if (asRequest) { - samlParameterName = GeneralConstants.SAML_REQUEST_KEY; - } - - return generateRedirectUri(samlParameterName, redirectUri, document); - } - public Response response() throws ProcessingException, ConfigurationException, IOException { - return response(destination, false); - } - public Response response(String redirectUri) throws ProcessingException, ConfigurationException, IOException { - return response(redirectUri, false); - } - - public Response request(String redirect) throws ProcessingException, ConfigurationException, IOException { - return response(redirect, true); - } - public Response request() throws ProcessingException, ConfigurationException, IOException { - return response(destination, true); - } - - private Response response(String redirectUri, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { - URI uri = responseUri(redirectUri, asRequest); - if (logger.isDebugEnabled()) logger.trace("redirect-binding uri: " + uri.toString()); - CacheControl cacheControl = new CacheControl(); - cacheControl.setNoCache(true); - return Response.status(302).location(uri) - .header("Pragma", "no-cache") - .header("Cache-Control", "no-cache, no-store").build(); - } - - } - - - - private String getSAMLNSPrefix(Document samlResponseDocument) { - Node assertionElement = samlResponseDocument.getDocumentElement() - .getElementsByTagNameNS(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get()).item(0); - - if (assertionElement == null) { - throw new IllegalStateException("Unable to find assertion in saml response document"); - } - - return assertionElement.getPrefix(); - } - - protected void encryptDocument(Document samlDocument) throws ProcessingException { - String samlNSPrefix = getSAMLNSPrefix(samlDocument); - - try { - QName encryptedAssertionElementQName = new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), - JBossSAMLConstants.ENCRYPTED_ASSERTION.get(), samlNSPrefix); - - byte[] secret = SamlProtocolUtils.createRandomSecret(encryptionKeySize / 8); - SecretKey secretKey = new SecretKeySpec(secret, encryptionAlgorithm); - - // encrypt the Assertion element and replace it with a EncryptedAssertion element. - XMLEncryptionUtil.encryptElement(new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), - JBossSAMLConstants.ASSERTION.get(), samlNSPrefix), samlDocument, encryptionPublicKey, - secretKey, encryptionKeySize, encryptedAssertionElementQName, true); - } catch (Exception e) { - throw new ProcessingException("failed to encrypt", e); - } - - } - - protected void signDocument(Document samlDocument) throws ProcessingException { - String signatureMethod = signatureAlgorithm.getXmlSignatureMethod(); - String signatureDigestMethod = signatureAlgorithm.getXmlSignatureDigestMethod(); - SAML2Signature samlSignature = new SAML2Signature(); - - if (signatureMethod != null) { - samlSignature.setSignatureMethod(signatureMethod); - } - - if (signatureDigestMethod != null) { - samlSignature.setDigestMethod(signatureDigestMethod); - } - - Node nextSibling = samlSignature.getNextSiblingOfIssuer(samlDocument); - - samlSignature.setNextSibling(nextSibling); - - if (signingCertificate != null) { - samlSignature.setX509Certificate(signingCertificate); - } - - samlSignature.signSAMLDocument(samlDocument, signingKeyPair, canonicalizationMethodType); - } - - protected void signAssertion(Document samlDocument) throws ProcessingException { - Element originalAssertionElement = org.keycloak.saml.common.util.DocumentUtil.getChildElement(samlDocument.getDocumentElement(), new QName(JBossSAMLURIConstants.ASSERTION_NSURI.get(), JBossSAMLConstants.ASSERTION.get())); - if (originalAssertionElement == null) return; - Node clonedAssertionElement = originalAssertionElement.cloneNode(true); - Document temporaryDocument; - - try { - temporaryDocument = org.keycloak.saml.common.util.DocumentUtil.createDocument(); - } catch (ConfigurationException e) { - throw new ProcessingException(e); - } - - temporaryDocument.adoptNode(clonedAssertionElement); - temporaryDocument.appendChild(clonedAssertionElement); - - signDocument(temporaryDocument); - - samlDocument.adoptNode(clonedAssertionElement); - - Element parentNode = (Element) originalAssertionElement.getParentNode(); - - parentNode.replaceChild(clonedAssertionElement, originalAssertionElement); - } - - - protected Response buildResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { - String str = buildHtmlPostResponse(responseDoc, actionUrl, asRequest); - - CacheControl cacheControl = new CacheControl(); - cacheControl.setNoCache(true); - return Response.ok(str, MediaType.TEXT_HTML_TYPE) - .header("Pragma", "no-cache") - .header("Cache-Control", "no-cache, no-store").build(); - } - - protected String buildHtmlPostResponse(Document responseDoc, String actionUrl, boolean asRequest) throws ProcessingException, ConfigurationException, IOException { - byte[] responseBytes = org.keycloak.saml.common.util.DocumentUtil.getDocumentAsString(responseDoc).getBytes("UTF-8"); - String samlResponse = PostBindingUtil.base64Encode(new String(responseBytes)); - - return buildHtml(samlResponse, actionUrl, asRequest); - } - - protected String buildHtml(String samlResponse, String actionUrl, boolean asRequest) { - if (destination == null) { - throw SAML2LoginResponseBuilder.logger.nullValueError("Destination is null"); - } - - StringBuilder builder = new StringBuilder(); - - String key = GeneralConstants.SAML_RESPONSE_KEY; - - if (asRequest) { - key = GeneralConstants.SAML_REQUEST_KEY; - } - - builder.append(""); - builder.append(""); - - builder.append("HTTP Post Binding Response (Response)"); - builder.append(""); - builder.append(""); - - builder.append("
"); - builder.append(""); - - if (isNotNull(relayState)) { - builder.append(""); - } - - builder.append(""); - - builder.append("
"); - - return builder.toString(); - } - - protected String base64Encoded(Document document) throws ConfigurationException, ProcessingException, IOException { - String documentAsString = DocumentUtil.getDocumentAsString(document); - logger.debugv("saml docment: {0}", documentAsString); - byte[] responseBytes = documentAsString.getBytes("UTF-8"); - - return RedirectBindingUtil.deflateBase64URLEncode(responseBytes); - } - - - protected URI generateRedirectUri(String samlParameterName, String redirectUri, Document document) throws ConfigurationException, ProcessingException, IOException { - UriBuilder builder = UriBuilder.fromUri(redirectUri) - .replaceQuery(null) - .queryParam(samlParameterName, base64Encoded(document)); - if (relayState != null) { - builder.queryParam(RELAY_STATE, relayState); - } - - if (sign) { - builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, signatureAlgorithm.getJavaSignatureAlgorithm()); - URI uri = builder.build(); - String rawQuery = uri.getRawQuery(); - Signature signature = signatureAlgorithm.createSignature(); - byte[] sig = new byte[0]; - try { - signature.initSign(signingKeyPair.getPrivate()); - signature.update(rawQuery.getBytes("UTF-8")); - sig = signature.sign(); - } catch (Exception e) { - throw new ProcessingException(e); - } - String encodedSig = RedirectBindingUtil.base64URLEncode(sig); - builder.queryParam(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, encodedSig); - } - return builder.build(); - } - - -} diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java index 750f70c3350c..3ea444042392 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2ErrorResponseBuilder.java @@ -16,25 +16,25 @@ * @author Bill Burke * @version $Revision: 1 $ */ -public class SAML2ErrorResponseBuilder extends SAML2BindingBuilder { +public class SAML2ErrorResponseBuilder { protected String status; + protected String destination; + protected String issuer; public SAML2ErrorResponseBuilder status(String status) { this.status = status; return this; } - public RedirectBindingBuilder redirectBinding() throws ConfigurationException, ProcessingException { - Document samlResponseDocument = buildDocument(); - return new RedirectBindingBuilder(samlResponseDocument); - + public SAML2ErrorResponseBuilder destination(String destination) { + this.destination = destination; + return this; } - public PostBindingBuilder postBinding() throws ConfigurationException, ProcessingException { - Document samlResponseDocument = buildDocument(); - return new PostBindingBuilder(samlResponseDocument); - + public SAML2ErrorResponseBuilder issuer(String issuer) { + this.issuer = issuer; + return this; } @@ -61,7 +61,6 @@ public Document buildDocument() throws ProcessingException { responseType.setStatus(JBossSAMLAuthnResponseFactory.createStatusTypeForResponder(status)); responseType.setDestination(destination); - if (encrypt) encryptDocument(samlResponse); return samlResponse; } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java index c59f56c76e5d..982927e10757 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutRequestBuilder.java @@ -15,11 +15,23 @@ * @author Bill Burke * @version $Revision: 1 $ */ -public class SAML2LogoutRequestBuilder extends SAML2BindingBuilder { +public class SAML2LogoutRequestBuilder { protected String userPrincipal; protected String userPrincipalFormat; protected String sessionIndex; protected long assertionExpiration; + protected String destination; + protected String issuer; + + public SAML2LogoutRequestBuilder destination(String destination) { + this.destination = destination; + return this; + } + + public SAML2LogoutRequestBuilder issuer(String issuer) { + this.issuer = issuer; + return this; + } /** * Length of time in seconds the assertion is valid for @@ -45,20 +57,8 @@ public SAML2LogoutRequestBuilder sessionIndex(String index) { return this; } - public RedirectBindingBuilder redirectBinding() throws ConfigurationException, ProcessingException, ParsingException { - Document samlResponseDocument = buildDocument(); - return new RedirectBindingBuilder(samlResponseDocument); - - } - - public PostBindingBuilder postBinding() throws ConfigurationException, ProcessingException, ParsingException { - Document samlResponseDocument = buildDocument(); - return new PostBindingBuilder(samlResponseDocument); - - } public Document buildDocument() throws ProcessingException, ConfigurationException, ParsingException { Document document = new SAML2Request().convert(createLogoutRequest()); - if (encrypt) encryptDocument(document); return document; } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java index 2d65716b30cf..43aa1c96251d 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SAML2LogoutResponseBuilder.java @@ -19,25 +19,25 @@ * @author Bill Burke * @version $Revision: 1 $ */ -public class SAML2LogoutResponseBuilder extends SAML2BindingBuilder { +public class SAML2LogoutResponseBuilder { protected String logoutRequestID; + protected String destination; + protected String issuer; public SAML2LogoutResponseBuilder logoutRequestID(String logoutRequestID) { this.logoutRequestID = logoutRequestID; return this; } - public RedirectBindingBuilder redirectBinding() throws ConfigurationException, ProcessingException { - Document samlResponseDocument = buildDocument(); - return new RedirectBindingBuilder(samlResponseDocument); - + public SAML2LogoutResponseBuilder destination(String destination) { + this.destination = destination; + return this; } - public PostBindingBuilder postBinding() throws ConfigurationException, ProcessingException { - Document samlResponseDocument = buildDocument(); - return new PostBindingBuilder(samlResponseDocument); - + public SAML2LogoutResponseBuilder issuer(String issuer) { + this.issuer = issuer; + return this; } @@ -67,7 +67,6 @@ public Document buildDocument() throws ProcessingException { } catch (ParsingException e) { throw new ProcessingException(e); } - if (encrypt) encryptDocument(samlResponse); return samlResponse; } diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java index e4e8f6ecc7fa..42952304c739 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlProtocol.java @@ -166,15 +166,17 @@ protected String getResponseIssuer(RealmModel realm) { protected Response getErrorResponse(ClientSessionModel clientSession, String status) { SAML2ErrorResponseBuilder builder = new SAML2ErrorResponseBuilder() - .relayState(clientSession.getNote(GeneralConstants.RELAY_STATE)) .destination(clientSession.getRedirectUri()) .issuer(getResponseIssuer(realm)) .status(status); try { + JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder() + .relayState(clientSession.getNote(GeneralConstants.RELAY_STATE)); + Document document = builder.buildDocument(); if (isPostBinding(clientSession)) { - return builder.postBinding().response(); + return binding.postBinding(document).response(clientSession.getRedirectUri()); } else { - return builder.redirectBinding().response(); + return binding.redirectBinding(document).response(clientSession.getRedirectUri()); } } catch (Exception e) { return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE); @@ -336,7 +338,7 @@ public Response authenticated(UserSessionModel userSession, ClientSessionCode ac return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE); } - SAML2BindingBuilder2 bindingBuilder = new SAML2BindingBuilder2(); + JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(); bindingBuilder.relayState(relayState); if (requiresRealmSignature(client)) { @@ -486,12 +488,14 @@ public Response frontchannelLogout(UserSessionModel userSession, ClientSessionMo if (isLogoutPostBindingForClient(clientSession)) { String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING); SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client); - return logoutBuilder.postBinding().request(bindingUri); + JaxrsSAML2BindingBuilder binding = createBindingBuilder(client); + return binding.postBinding(logoutBuilder.buildDocument()).request(bindingUri); } else { logger.debug("frontchannel redirect binding"); String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_REDIRECT_BINDING); SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(bindingUri, clientSession, client); - return logoutBuilder.redirectBinding().request(bindingUri); + JaxrsSAML2BindingBuilder binding = createBindingBuilder(client); + return binding.redirectBinding(logoutBuilder.buildDocument()).request(bindingUri); } } catch (ConfigurationException e) { throw new RuntimeException(e); @@ -519,24 +523,25 @@ public Response finishLogout(UserSessionModel userSession) { builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID)); builder.destination(logoutBindingUri); builder.issuer(getResponseIssuer(realm)); - builder.relayState(logoutRelayState); + JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(); + binding.relayState(logoutRelayState); String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM); if (signingAlgorithm != null) { SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm); String canonicalization = userSession.getNote(SAML_LOGOUT_CANONICALIZATION); if (canonicalization != null) { - builder.canonicalizationMethod(canonicalization); + binding.canonicalizationMethod(canonicalization); } - builder.signatureAlgorithm(algorithm) + binding.signatureAlgorithm(algorithm) .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) .signDocument(); } try { if (isLogoutPostBindingForInitiator(userSession)) { - return builder.postBinding().response(logoutBindingUri); + return binding.postBinding(builder.buildDocument()).response(logoutBindingUri); } else { - return builder.redirectBinding().response(logoutBindingUri); + return binding.redirectBinding(builder.buildDocument()).response(logoutBindingUri); } } catch (ConfigurationException e) { throw new RuntimeException(e); @@ -562,7 +567,8 @@ public void backchannelLogout(UserSessionModel userSession, ClientSessionModel c String logoutRequestString = null; try { - logoutRequestString = logoutBuilder.postBinding().encoded(); + JaxrsSAML2BindingBuilder binding = createBindingBuilder(client); + logoutRequestString = binding.postBinding(logoutBuilder.buildDocument()).encoded(); } catch (Exception e) { logger.warn("failed to send saml logout", e); return; @@ -612,24 +618,17 @@ protected SAML2LogoutRequestBuilder createLogoutRequest(String logoutUrl, Client .issuer(getResponseIssuer(realm)) .userPrincipal(clientSession.getNote(SAML_NAME_ID), clientSession.getNote(SAML_NAME_ID_FORMAT)) .destination(logoutUrl); + return logoutBuilder; + } + + private JaxrsSAML2BindingBuilder createBindingBuilder(ClientModel client) { + JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(); if (requiresRealmSignature(client)) { - logoutBuilder.signatureAlgorithm(getSignatureAlgorithm(client)) - .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) - .signDocument(); - } - /* - if (requiresEncryption(client)) { - PublicKey publicKey = null; - try { - publicKey = PemUtils.decodePublicKey(client.getAttribute(ClientModel.PUBLIC_KEY)); - } catch (Exception e) { - logger.error("failed", e); - return; - } - logoutBuilder.encrypt(publicKey); + binding.signatureAlgorithm(getSignatureAlgorithm(client)) + .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) + .signDocument(); } - */ - return logoutBuilder; + return binding; } @Override diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java index 38304e6b30d1..96b240ae9018 100755 --- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java +++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/SamlService.java @@ -389,19 +389,20 @@ protected Response logoutRequest(LogoutRequestType logoutRequest, ClientModel cl builder.logoutRequestID(logoutRequest.getID()); builder.destination(logoutBindingUri); builder.issuer(RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString()); - builder.relayState(logoutRelayState); + JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder() + .relayState(logoutRelayState); if (SamlProtocol.requiresRealmSignature(client)) { SignatureAlgorithm algorithm = SamlProtocol.getSignatureAlgorithm(client); - builder.signatureAlgorithm(algorithm) + binding.signatureAlgorithm(algorithm) .signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate()) .signDocument(); } try { if (SamlProtocol.SAML_POST_BINDING.equals(logoutBinding)) { - return builder.postBinding().response(logoutBindingUri); + return binding.postBinding(builder.buildDocument()).response(logoutBindingUri); } else { - return builder.redirectBinding().response(logoutBindingUri); + return binding.redirectBinding(builder.buildDocument()).response(logoutBindingUri); } } catch (Exception e) { throw new RuntimeException(e);