Camunda BPM Webapp with SSO in for Wildfly/JBoss AS7
Shell
Clone or download
Permalink
Failed to load latest commit information.
src/assembly
.gitignore
CONTRIBUTING.md
LICENSE
README.md
illustration.jpg
merge-master-into-branches.sh
pom.xml

README.md

Single Sign-on for Camunda BPM Webapp on Wildfly/JBoss AS7 (Container-based Authentication)

This project adds Single Sign On (SSO) support to the Camunda BPM Webapp, which contains Tasklist, Cockpit and Admin. Fortunately, application servers can do the actual authentication of a user before a request is forwarded to the application. The only thing that needs to be done inside the Camunda REST API, is to take the user id and optionally also the group ids provided by the container through the Servlet API and put them into the Servlet session of the REST API. Thats why we also call this Container-based Authentication.

As a particular example, this project shows how to do SSO with Kerberos/Active Directory and Wildfly. However, the Container-based Authentication Filter is only using the standard Servlet and Java Security APIs. Therefore it works exactly the same on all Servlet containers and with any authentication mechanism supported by the container. For example the fork for Single Sign-on on Weblogic uses the same Java code.

There are two variations of the Authentication Filter: One takes the user's groups from the Camunda IdentityService and requires the LDAP plugin or another identity provider. The other one takes the groups from the container and leverages, e.g. an LDAP support inside the container. However, it falls back to the Camunda IdentityService of the container doesn't provide groups.

The project also shows how to configure the Camund Webapp in a way that allows for smooth updates to future Camunda BPM versions. The config-processor-maven-plugin helps to gently modify the original deployment decriptors web.xml, jboss-web.xml and jboss-deployment-structure.xml provided inside Camunda binary packages.

Variations (Branches)

This Git repository contains different branches with slight variations of the implementation:

  • enterprise-edition: uses correct dependencies to build a Camunda Webapp that conatains the Enterprise Edition features
  • local-test-basic-auth: uses HTTP Basic Authentication for local testing without Kerberos/Active Directory server
  • local-test-basic-auth-ee: combines both of the above mentioned branches for local testing
  • local-test-basic-auth-groups: uses HTTP Basic Authentication for local testing of the filter that gets the user's groups from the container
  • keycloak: uses keycloak as identity provider

Documentation

Problem

The Camunda BPM Webapp has to be secured.

Business Requirements

  • Login once via a SSO mechanism
  • Security has to be implemented by standard JBoss configuration

Technical Requirements

  • Windows Active Directory (AD)
  • JBoss AS7 / Widlfly / EAP
  • AD User and Groups for integration in Camunda
  • Dedicated AD User for JBoss Service

Solution

  • Add Kerberos and AD Security-Negotiation to JBoss
  • Configure Camunda-Webapp

Acceptance tests

  • AD User can login into CamundaBPM
  • All GUIs and REST APIs are only accessible via AD Login

Get started

Configuration AD

Have a look at the tutorial How To Configure Browser-based SSO with Kerberos/SPNEGO and JBoss Application Server

A fully configured AD is needed, because the authentication needs users and groups. Therefore we use the test users eh, TestUser, Administrator and the test group TestGroup. They can be created with the AD standard tooling of a windows server.

  1. Create an AD User (Example: eh)
  2. Create an AD Group (Example: TestGroup)
  3. Execute on cmd Line with admin rights: Create the User Principal:
setspn -A HTTP/nbookeh2.novaDomain.local eh

Create the KeyTab file:

ktpass /out krb5.keytab /mapuser eh@NOVADOMAIN.LOCAL /princ HTTP/nbookeh2.novaDomain.local@NOVADOMAIN.LOCAL /pass 
    jessica_4321 /kvno 0 /crypto all`

JBoss Configuration

Therefore, we using JBoss AS7/EAP6 is a requirement. So it is needed to add a few configuration lines.

  1. Modify the standalone.xml and add your specific AD information!
<server xmlns="urn:jboss:domain:1.5">
...
    <system-properties>
        <property name="java.security.krb5.realm" value="NOVADOMAIN.LOCAL"/>
        <property name="java.security.krb5.kdc" value="192.168.0.1"/>
        <property name="java.security.auth.login.config" value="C:\login.conf"/>
        <property name="java.security.krb5.conf" value="C:\Windows\krb5.ini"/>
        <property name="sun.security.krb5.debug" value="true"/>
        <property name="jboss.security.disable.secdomain.option" value="true"/>
        <property name="javax.net.debug" value="true"/>
        <property name="java.security.debug" value="true"/>
    </system-properties>
...
    <profile>
    ...
        <subsystem xmlns="urn:jboss:domain:security:1.2">
        ...
            <security-domains>
                <security-domain name="myhost" cache-type="default">
                    <authentication>
                        <login-module code="Kerberos" flag="required">
                            <module-option name="storeKey" value="true"/>
                            <module-option name="useKeyTab" value="true"/>
                            <module-option name="principal" value="HTTP/nbookeh2.novaDomain.local@NOVADOMAIN.LOCAL"/>
                            <module-option name="keyTab" value="C:/krb5.keytab"/>
                            <module-option name="doNotPrompt" value="true"/>
                            <module-option name="refeshKrb5Config" value="false"/>
                            <module-option name="debug" value="true"/>
                        </login-module>
                    </authentication>
                </security-domain>
                <security-domain name="SPNEGO" cache-type="default">
                    <authentication>
                        <login-module code="SPNEGO" flag="requisite">
                            <module-option name="password-stacking" value="useFirstPass"/>
                            <module-option name="serverSecurityDomain" value="myhost"/>
                            <module-option name="removeRealmFromPrincipal" value="true"/>
                        </login-module>
                        <login-module code="AdvancedAdLdap" flag="requisite">
                            <module-option name="password-stacking" value="useFirstPass"/>
                            <module-option name="bindDN" value="cn=Administrator,cn=Users,dc=novaDomain,dc=local"/>
                            <module-option name="bindCredential" value="jessica_4321"/>
                            <module-option name="java.naming.provider.url" value="ldap://vmserver2015.novaDomain.local:389"/>
                            <module-option name="java.naming.referral" value="follow"/>
                            <module-option name="baseCtxDN" value="DC=novaDomain,DC=local"/>
                            <module-option name="baseFilter" value="(cn={0})"/>
                            <module-option name="roleAttributeID" value="memberOf"/>
                            <module-option name="allowEmptyPassword" value="false"/>
                        </login-module>
                    </authentication>
                </security-domain>
            </security-domains>
        </subsystem>
        ...
        <subsystem xmlns="urn:org.camunda.bpm.jboss:1.1">
            <process-engines>
                <process-engine name="default" default="true">
                    <plugins>
                        <plugin>
                            <class>
                                org.camunda.bpm.identity.impl.ldap.plugin.LdapIdentityProviderPlugin
                            </class>
                            <properties>
                                <property name="serverUrl">
                                   ldap://192.168.0.1:389
                                </property>
                                <property name="managerDn">
                                    cn=Administrator,cn=Users,dc=novaDomain,dc=local
                                </property>
                                <property name="managerPassword">
                                    jessica_4321
                                </property>
                                <property name="baseDn">
                                    dc=novaDomain,dc=local
                                </property>
                                <property name="userSearchBase">
                                    cn=Users
                                </property>
                                <property name="userSearchFilter">
                                   (objectCategory=person)
                                </property>
                                <property name="userIdAttribute">
                                   cn
                                </property>
                                <property name="userFirstnameAttribute">
                                    name
                                </property>
                                <property name="userLastnameAttribute">
                                    sn
                                </property>
                                <property name="userEmailAttribute">
                                    mail
                                </property>
                                <property name="userPasswordAttribute">
                                    userPassword
                                </property>
                                <property name="groupSearchBase">
                                    cn=Users
                                </property>
                                <property name="groupSearchFilter">
                                    (objectCategory=group)
                                </property>
                                <property name="groupIdAttribute">
                                    cn
                                </property>
                                <property name="groupNameAttribute">
                                    name
                                </property>
                                <property name="groupMemberAttribute">
                                    member
                                </property>
                            </properties>
                        </plugin>
                        <plugin>
                            <class>
                                org.camunda.bpm.engine.impl.plugin.AdministratorAuthorizationPlugin
                            </class>
                            <properties>
                                <property name="administratorUserName">
                                    eh
                                </property>
                            </properties>
                        </plugin>
                    </plugins>
                </process-engine>
            </process-engines>
            ...
        </subsystem>
        ...
    </profile>
    ...
</server>
  1. Create a login.conf and link it in the JBoss property configuration
com.sun.security.jgss.login {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true debug=true renewTGT=true;
};
com.sun.security.jgss.initiate {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true debug=true renewTGT=true;
};
com.sun.security.jgss.accept {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true debug=true renewTGT=true;
};

Camunda Webapp Configuration

For getting the authentication and authorization from AD, it is needed to modify the camunda webapp. There are 3 configuration steps and a copy step with an adapted security filter of camunda. In this changes, it is important to add the specific authorization group to the web.xml.

Configuration of Windows Kerberos

Kerberos now needs the connection information. This krb5.ini is the standard configuration file of a java kerberos client. It is needed to add the specific AD configuration information.

[appdefaults]
    validate=false
[domain_realm]
    novaDomain.local = "NOVADOMAIN.LOCAL"
    .novaDomain.local = "NOVADOMAIN.LOCAL"
[libdefaults]
    ticket_lifetime = 600
    default_tkt_enctypes = aes256-cts-hmac-sha1-96 aes256-cts aes128-cts des3-cbc-sha1 rc4-hmac des-cbc-md5 des-cbc-crc
    default_tgt_enctypes = aes256-cts-hmac-sha1-96 aes256-cts aes128-cts des3-cbc-sha1 rc4-hmac des-cbc-md5 des-cbc-crc
    default_tgs_enctypes = aes256-cts-hmac-sha1-96 aes256-cts aes128-cts des3-cbc-sha1 rc4-hmac des-cbc-md5 des-cbc-crc
    dns_lookup_kdc = "true"
    forwardable = true
    default_realm = "NOVADOMAIN.LOCAL"
[logging]
[realms]
    NOVADOMAIN.LOCAL = {
        admin_server = "192.168.0.1"
        kdc = "192.168.0.1"
        }

Modify JRE/JDK

The standard JRE/JDK only supports a standard encryption of 128 bit. For getting more security install the other policys. Install UnlimitedJCEPolicyJDK7.zip from oracle webpage into the jre/jdk installation dir.

External Documentation Links

Resources

Roadmap

todo

  • Contribution to Camunda

done

  • Security filter to map users and groups

Maintainer

License

Apache License, Version 2.0