Sling 9397/update removed saml config service (#69)

* removed optional transititve for Spring's org.relaxng.datatype from dom4j, which itself is not needed

* saml-handler: pom.xml / bnd usage cleanups

* Added method to validate subject confirmation

* plugin renamed from maven-sling-plugin to sling-maven-plugin

* clean up bugs and code smell

* added noticeStatement property

* merged upstream master

* Upgraded SAML2 Handler to OpenSAML V4. Java 11. Sling 12. Reviewed and optimized embedded OpenSAML dependencies and updated versions.

update docs

made encryption and signing an optional configuration

Backed out SLO for now and moved that to a different branch. Logout in this branch simply drops the credentials for this Service Provider and redirects the client to the URL configured

Added error handling runtime exception if the userID is not configured properly. JCR Group ID's now seem to slash in front so added condition to allow that. Updated realm-sling-export.json (for Keycloak demo) adding attribute mappers for client, http://localhost:8080

updated readme and added localhost test package

* Added custom runtime exception class for unhandled exceptions. Removed commented and unused code

* added license

* Removed attribution under license. Refactored JKS password to char[]. Reduced duplication Credentials classes. Removed Notice. Removed JCR test package from resources

* removed unused imports. added missing license

* started demo saml2 project

* updated comments

* To get repoinit working, moved configs from /apps/sling/saml/runmodes/config  to /apps/runmodes/configs

* fix 'catch multiple exceptions at once' code smell

* Started Example SAML2 project that will provide faster test setup providing JKS, service user, ACL's, dependencies, and SlingJunit tests

* space change

* fix pom error

* fix sonar bug and smells

* Fixed startup problem by setting startLevel to 19

* Refactor example setup and configuration project (saml-example)

* moved example realm to example project

* Export Package of oak-auth-external dependency simplifies setup

* update documentation

* Updated READMME Docs for clarifying processes for SSL and SAML credentials

* Refactored and removed saml2 config service

* fix bugs identified by sonarcloud

* added javadocs to Saml2UserMgtService, update usage in AuthenticationHandlerSAML2Impl

* Reduce complexity of extractCredentials in AuthenticationHandlerSAML2Impl. Change path to single value property since AuthenticationHandlerSAML2Config is used as a factory

* sonarcloud code smell fixes

* started junit tests for AuthenticationHandlerSAML2Impl

* Started PAX tests for saml-handler. IT tests seem inoperational in this commit

* WIP: continuing work to increase test converage

* continued struggling with test setup

* continuing work on pax tests

* cont'd with SAML2 tests after initializing OpenSAML in OsgiSamlTest.java

* added tests for issuer and nameIDpolicy

* added Endpoint unit tests

* Sling 9397/improve test coverage (#70)

* Started PAX tests for saml-handler. IT tests seem inoperational in this commit

* WIP: continuing work to increase test converage

* continued struggling with test setup

* continuing work on pax tests

* cont'd with SAML2 tests after initializing OpenSAML in OsgiSamlTest.java

* added tests for issuer and nameIDpolicy

* added Endpoint unit tests

* continuing progress on pax exam it tests

* continuing progress on pax exam it tests

* attempt to fix the paxexam test environment

1. export the org.apache.sling.auth.saml2 package
2. don't change the startlevel in the Activator
3. provide the required configuration for the
AuthenticationHandlerSAML2Impl service

* SLING-10193 Added test coverage for Saml2User.java and Saml2UserMgtService.java. Moved Saml2User.java into saml2 package so that it accesses by tests

* SLING-9397 Updated the example configs to reflect the new PID for configuting AuthenticationHandlerSAML2

* clean up

* SLING-9397 Added IT test coverage for Saml2UserMgtService

* add java coco to pom

* code coverage tool not working, commented out

* Added tests for Helpers

* trying to get jacoco to report IT test coverage

* fixed parent version

* SAML Handler manages user sync with Saml2UserSyncService so extending Jackrabbit ExternalUser is not needed

* continued doUserManagement testing

* Sling 10193/test coverage (#72)

* SAML Handler manages user sync with Saml2UserSyncService so extending Jackrabbit ExternalUser is not needed

* continued doUserManagement testing

* Added setup for Java Keystore tests, added tests for JksCredentials, KeyPairCredentials and VerifySignatureCredentials

* Refactor TokenStore.java and AuthenticationHandlerSAML2Impl.java to allow junit tests

* remove unimplemented constructor

* improve unit test coverage

* add one IT test and clean up

* updated pom.xml with dependency version ranges

* continued improving test coverage

* continued improving test coverage

* text coverage

* SLING-10193 set and remove JAAS config upon bundle activator start and stop

* improve testing for user management and sync

* Updated properties sync to use a mapping defined in the OSGI configs such that the name and relative path of the save property can be configured (instead of using the saml attribute's Friendly Name)

Co-authored-by: Robert Munteanu <rombert@apache.org>
Co-authored-by: Eric Norman <enorman@apache.org>
23 files changed
tree: a5bede5f76da935538a646c8b34c3163db0a7c77
  1. src/
  2. bnd.bnd
  3. LICENSE
  4. pom.xml
  5. README.md
README.md

Apache Sling SAML2 Handler (NOT FOR PRODUCTION)

This contribution to the Apache Sling project; provides a SAML2 Web Profile Service Provider Authentication.

Overview

https://en.wikipedia.org/wiki/SAML_2.0

  • The SAMLRequest uses HTTP Redirect Binding, and the contained Authn Request object instructs the IDP to use HTTP Post Binding.

Sling applications may authenticate users against an Identity Provider (idp) such as Keycloak Server or Shibboleth IDP.

Requirements

  • Java 11
  • Sling 11 or 12
  • An external SAML2 identity provider

User Management

User management is based on the OSGi bundle configuration and SAML2 Assertion

  • Upon successful authentication, a user is created
  • The user may be added to a JCR group membership under certain conditions:
    • This bundle has an OSGI config saml2groupMembershipAttr set with the value of the name of the SAML group membership attribute.
    • The users SAML assertion contains an attribute matching the configuration above
    • The value of the users group membership attribute is a name of an existing JCR group
  • syncAttrs can be used to synchronize user properties released by the IDP for profile properties such as given name, family name, email, and phone.

Localhost Setup

Procedure for localhost testing

Start and Configure an External Identity Provider

  1. Start a Keycloak Server docker run -p 8484:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin jboss/keycloak
  2. Login using http://localhost:8484/auth/admin/
    • username: admin, password: admin
  3. Configure a Realm
    • Click “Add Realm”
    • Select the file located at saml-example/src/main/resources/sling-realm-export.json Note. The preconfigured realm contains configuration for the client and the groups, but does not contain users.
  4. Add user(s)
    • Select Users under the “Sling” Realm
    • Set user attributes; specifically “userid”
    • Set user password
    • Set user groups; specifically join “pcms-authors”

Sling SAML2 Service Provider Setup

  1. Start Sling (Assuming a new instance of Sling 12-SNAPSHOT)
  2. Run mvn clean install -P autoInstallBundle from saml-handler project
    Note: saml-handler is the core bundle offering SAML2 Sign on
  3. Run mvn clean install -P autoInstallPackage from saml-example project
    Note: saml-example is example setup package containing: OSGI configurations, service-user and ACL's. This setup is detailed in the section below.

Configurations, Service User and ACL's

Note: the following are contained in localhostExample-1.zip

Provide a JAAS OSGI Config as shown below

  • jaas.controlFlag=Sufficient
  • jaas.ranking=110
  • jaas.realmName=jackrabbit.oak
  • jaas.classname=org.apache.sling.auth.saml2.sp.Saml2LoginModule

Provide a Service User Mapper OSGI Config

  • org.apache.sling.auth.saml2:Saml2UserMgtService=saml2-user-mgt

Set up the system user “saml2-user-mgt”

  • visit Composum Users as admin
  • Create service user “saml2-user-mgt”
  • Provide an ACL rule for granting jcr:all to this user on the /home path

Provide a SAML2 OSGI Configuration

Use Composum Users to create the group “pcms-authors” to test automatic group membership assignment

Notes:

  • Users home “/home/users/saml” will be created once the first user successfully authenticates.
  • After configuring the SAML2 authentication handler, the Sling Form login can still be accessed directly http://localhost:8080/system/sling/form/login?resource=%2F
  • See below technical notes for certificate, keys, signing and encryption

Test

Visit http://localhost:8080 and observe login takes place on the http://localhost:8484 Keycloak Server IDP

Enter credentials for the user you created, and observe user is granted access to the system.

Certificates, SSL, Signing and Encryption

This portion discusses encryption which can be very critical for the security of this solution.

Decide a location on the file system for the Keystores. For example, under the sling folder
$ mkdir sling/keys
$ cd sling/keys

Enable Jetty HTTPS

It's a good idea to configure SSL for Jetty providing https binding.

  1. Create KeyStore & generate a self-signed certificate (not for production).
    • Generate self-signed private key and public certificate
      • $ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
    • Review Certificate (Optional)
      • $ openssl x509 -text -noout -in certificate.pem
    • Combine key and certificate in a PKCS#12 (P12) bundle
      • $ openssl pkcs12 -inkey key.pem -in certificate.pem -export -out sslKeystore.p12
      • JKSPassord
  2. Configure SSL and https port binding for Jetty. The following are based on the example sslKeystore.p12 created above.
    • org.apache.felix.https.enable=B“true”
    • org.osgi.service.http.port.secure=I“8443”
    • org.apache.felix.https.keystore=“./sling/keys/sslKeystore.p12”
    • org.apache.felix.https.truststore=“./sling/keys/sslKeystore.p12”
    • org.apache.felix.https.keystore.password=“JKSPassord”
    • org.apache.felix.https.keystore.key.password=“JKSPassord”
    • org.apache.felix.https.truststore.password=“JKSPassord”

SAML Service Provider (SP) Keystore Detail and Example

Aside from the Jetty SSL credentials discussed above, there are two other credentials to consider for a SAML2 Service Provider (SP).

  • Service Provider (SP) Keypair
  • Identity Provider (IDP) Signing Certificate

Keystore Setup (Localhost) Example

The SP Keypair is used by the IDP and SP to encrypt and decrypt SAML2 responses. It should be unique for each service provider.
Note that the SP Keypair is also used to cryptographically sign SAML requests sent from the SP to the IDP.

  1. Generate a new keypair for the Service Provider (SP) from ./sling/keys
    • openssl req -newkey rsa:2048 -nodes -keyout samlSPkey.pem -x509 -days 365 -out samlSPcert.pem
    • openssl pkcs12 -inkey samlSPkey.pem -in samlSPcert.pem -export -out samlSPkeystore.p12
    • View details about the generated keypair
      • $ keytool -list -v -keystore samlSPkeystore.p12
    • Make note of the storepass, alias, filename, and key password. These will all be needed to configure SP encryption.
  2. Import the SP's pubic certificate (samlSPcert.pem) you made to the Keycloak Sling client
    • Turn on “Encrypt Assertions” and save. This will expose a new tab for SAML Keys.
    • From the “SAML Keys” tab import using the ‘Certificate PEM’ option.
    • Select the public certificate for the SP Keypair
  3. Import the Keycloak signing certificate
    • Select the Keys tab from the Sling realm
    • Under public keys, click and view Certificate.
    • Copy paste to a file signingCert.pem
    • Import the cert.pem to the keystore
      • $ keytool -import -file signingCert.pem -keystore samlKeystore.jks -alias idpsigningalias

Example OSGI Settings for SAML2 SP to use Keystore

config/org/apache/sling/auth/saml2/impl/SAML2ConfigServiceImpl.config
  • acsPath=“/sp/consumer”
  • entityID=“https://localhost:8443/
  • idpCertAlias=“idpsigningalias”
  • jksFileLocation=“./sling/keys/samlSPkeystore.p12”
  • jksStorePassword=“samlStorePassword”
  • path=[“https://localhost:8443/”]
  • saml2IDPDestination=“http://localhost:8484/auth/realms/sling/protocol/saml
  • saml2LogoutURL=“https://sling.apache.org/
  • saml2SPEnabled=B“true”
  • saml2SPEncryptAndSign=B“true”
  • saml2SessionAttr=“saml2AuthInfo”
  • saml2groupMembershipAttr=“urn:oid:2.16.840.1.113719.1.1.4.1.25”
  • saml2userHome=“/home/users/saml”
  • saml2userIDAttr=“urn:oid:0.9.2342.19200300.100.1.1”
  • service.pid=“org.apache.sling.auth.saml2.impl.SAML2ConfigServiceImpl”
  • service.ranking=I“42”
  • spKeysAlias=“1”
  • spKeysPassword=“samlStorePassword”
  • syncAttrs=[ “urn:oid:2.5.4.4”, “urn:oid:2.5.4.42”, “phone”, “urn:oid:1.2.840.113549.1.9.1”, ]

Attribution

This module was contributed to Apache Sling by Cris Rockwell and Regents of the University of Michigan.

License

Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you 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.