JBoss Community Archive (Read Only)

GateIn Portal 3.6

SPNEGO

SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) is used to authenticate transparently through the web browser after the user has been authenticated when logging-in his session.

A typical use case is the following:

  1. User logs into his desktop (Such as a Windows machine).

  2. The desktop login is governed by Active Directory domain.

  3. User then uses his browser (IE/Firefox) to access a web application (that uses JBoss Negotiation) hosted on GateIn Portal.

  4. The Browser transfers the desktop sign on information to the web application.

  5. GateIn Portal uses background GSS messages with the Active Directory (or any Kerberos Server) to validate the Kerberos ticket from user.

  6. The User has seamless SSO into the web application.

GateIn Portal provides SPNEGO integration via GateIn Portal SSO library, which leverages JBoss Negotiation library for this purpose.

SPNEGO Server Configuration

In this section, there are some necessary steps for setting up the Kerberos server on Linux. This server will then be used for SPNEGO authentication against GateIn Portal.

If you do not have Linux but you are using the Windows and Active Directory domain, the information is not important for you and you may jump to the Portal configuration . Please note that Kerberos setup is also dependent on your Linux distribution, so steps can be slightly different in your environment.

  1. Correct the setup of network on the machine. For example, if you are using the "server.local.network" domain as your machine where Kerberos and GateIn Portal are located, add the line containing the machine's IP address to the /etc/hosts file.

    192.168.1.88  server.local.network

    It is not recommended to use loopback addresses.

  2. Install Kerberos with these packages: krb5-admin-server, krb5-kdc, krb5-config, krb5-user, krb5-clients, and krb5-rsh-server.

  3. Edit the Kerberos configuration file at /etc/krb5.conf, including:

    • Uncomment on these lines:

      default_tgs_enctypes = rc4-hmac
      default_tkt_enctypes = rc4-hmac
      permitted_enctypes = rc4-hmac
    • Add local.network as a default realm and it is also added to the list of realms and remove the remains of realms. The content looks like:

      [libdefaults]
          default_realm = LOCAL.NETWORK
      
      # The following krb5.conf variables are only for MIT Kerberos.
          krb4_config = /etc/krb.conf
          krb4_realms = /etc/krb.realms
          kdc_timesync = 1
          ccache_type = 4
          forwardable = true
          proxiable = true
      
      # The following encryption type specification will be used by MIT Kerberos
      # if uncommented.  In general, the defaults in the MIT Kerberos code are
      # correct and overriding these specifications only serves to disable new
      # encryption types as they are added, creating interoperability problems.
      #
      # Thie only time when you might need to uncomment these lines and change
      # the enctypes is if you have local software that will break on ticket
      # caches containing ticket encryption types it doesn't know about (such as
      # old versions of Sun Java).
      
          default_tgs_enctypes = rc4-hmac
          default_tkt_enctypes = rc4-hmac
          permitted_enctypes = rc4-hmac
      
      # The following libdefaults parameters are only for Heimdal Kerberos.
          v4_instance_resolve = false
          v4_name_convert = {
              host = {
                  rcmd = host
                  ftp = ftp
              }
              plain = {
                  something = something-else
              }
          }
          fcc-mit-ticketflags = true
      
      [realms]
          LOCAL.NETWORK = {
              kdc = server.local.network
              admin_server = server.local.network
          }
      
      [domain_realm]
          .local.network = LOCAL.NETWORK
          local.network = LOCAL.NETWORK
      
      [login]
          krb4_convert = true
          krb4_get_tickets = false
  4. Edit the KDC configuraton file at /etc/krb5kdc/kdc.conf that looks like.

    [kdcdefaults]
        kdc_ports = 750,88
    
    [realms]
        LOCAL.NETWORK = {
            database_name = /var/lib/krb5kdc/principal
            admin_keytab = FILE:/etc/krb5.keytab
            acl_file = /etc/krb5kdc/kadm5.acl
            key_stash_file = /etc/krb5kdc/stash
            kdc_ports = 750,88
            max_life = 10h 0m 0s
            max_renewable_life = 7d 0h 0m 0s
            master_key_type = rc4-hmac
            supported_enctypes = rc4-hmac:normal
            default_principal_flags = +preauth
        }
    
    [logging]
            kdc = FILE:/tmp/kdc.log
            admin_server = FILE:/tmp/kadmin.log
  5. Next, create a KDC database using the command:

    sudo krb5_newrealm
  6. Start the KDC and Kerberos admin servers using these commands:

    sudo /etc/init.d/krb5-kdc restart
    sudo /etc/init.d/krb5-admin-server restart
  7. Add Principals and create Keys.

    • Start an interactive 'kadmin' session and create the necessary Principals using the command:

      sudo kadmin.local
    • Add the GateIn Portal machine and keytab file that need to be authenticated using the commands:

      addprinc -randkey HTTP/server.local.network@LOCAL.NETWORK
      ktadd HTTP/server.local.network@LOCAL.NETWORK
    • Add the default GateIn Portal user accounts and enter the password for each created user that will be authenticated using the commands:

      addprinc john
      addprinc demo
      addprinc root
  8. Test your changed setup by command:

    kinit -A demo
    • If the setup works well, you are required to enter the password created for this user in previous step. Without -A, the kerberos ticket validation involved reverse DNS lookups, which can get very cumbersome to debug if your network's DNS setup is not great. This is a production level security feature, which is not necessary in this development setup. In production environment, it will be better to avoid -A option.

    • After successful login to Kerberos, you can see your Kerberos ticket when using the klist command.

    • If you want to logout and destroy your ticket, use the kdestroy command.

Browser configuration

After performing all configurations above, you need to enable the Negotiate authentication of Firefox in client machines so that clients could be authenticated by GateIn Portal as follows:

  1. Start Firefox, then enter the about:config command into the address field.

  2. Enter network.negotiate-auth and set the value as below:

    network.negotiate-auth.allow-proxies = true
    network.negotiate-auth.delegation-uris = .local.network
    network.negotiate-auth.gsslib (no-value)
    network.negotiate-auth.trusted-uris = .local.network
    network.negotiate-auth.using-native-gsslib = true

    Consult the documentation of your OS or web browser if using different browser than Firefox.

Portal configuration

SPNEGO setup works only with GateIn Portal deployed on JBoss AS 7 because it uses JBoss Negotiation library specific to JBoss. This library leverages custom Tomcat authenticator Valve and custom JAAS login module to provide SPNEGO and Kerberos integration.

  1. You will need to change SSO section in the file GATEIN_HOME/standalone/configuration/gatein/configuration.properties to be like this:

    # SSO
    gatein.sso.enabled=true
    gatein.sso.callback.enabled=false
    gatein.sso.skip.jsp.redirection=false
    gatein.sso.login.module.enabled=false
    gatein.sso.filter.login.sso.url=/@@portal.container.name@@/dologin
    gatein.sso.filter.logout.enabled=false
    gatein.sso.filter.initiatelogin.enabled=false
    gatein.sso.valve.enabled=true
    gatein.sso.valve.class=org.gatein.sso.spnego.GateInNegotiationAuthenticator

    Description of individual properties:

    • gatein.sso.enabled - General property used to inform GateIn Portal that click to Sign in will redirect user to URL ending with /portal/dologin . This is described in more details in Central Authentication Service (CAS)#Configuration properties details

    • gatein.sso.callback.enabled - This could be false as we don't need REST callback for SPNEGO integration

    • gatein.sso.skip.jsp.redirection - This should be false for SPNEGO, especially if you want fallback to FORM authentication to work properly (More details in Disable fallback to FORM authentication )

    • gatein.sso.login.module.enabled - This can be false as we need slightly different set of login modules for SPNEGO integration. More details below where will be detailed login modules configuration

    • gatein.sso.filter.login.sso.url - Click to Sign in should redirect us to URL /portal/dologin , which is secured URL (declared in security-constraint section of GATEIN_HOME/gatein/gatein.ear/portal.war/WEB-INF/web.xml file), which will allow GateInNegotiationAuthenticator valve to intercept this HTTP request

    • gatein.sso.filter.logout.enabled, gatein.sso.filter.initiatelogin.enabled - Logout filter and InitiateLoginFilter are not needed for SPNEGO integration

    • gatein.sso.valve.enabled - This option points that SPNEGO integration requires enabling of custom Tomcat valve, which is used to intercept HTTP request for secured URL (/portal/dologin). The SSODelegateValve is defined in file GATEIN_HOME/gatein/gatein.ear/portal.war/WEB-INF/jboss-web.xml and is used only if the option gatein.sso.valve.enabled is true. The purpose of SSODelegateValve is to delegate the real work to another valve declared in option gatein.sso.valve.class . The point is that you don't need to edit anything in file jboss-web.xml as everything can be configured via properties.

    • gatein.sso.valve.class - So for SPNEGO integration the delegate valve is org.gatein.sso.spnego.GateInNegotiationAuthenticator, which is used to establish identity of client by exchanging few handshakes with client's browser. The valve is able to obtain and parse SPNEGO token and resend it to JAAS layer, where login modules (especially SPNEGOLoginModule) are able to verify validity of wrapped Kerberos token and establish user identity at GateIn Portal layer.

  2. JAAS configuration - Configuration of login modules for SPNEGO integration is not trivial and so it's not simply configurable only via configuration.properties, but it require changing of JAAS stack. You will need to do those changes in file GATEIN_HOME/standalone/configuration/standalone.xml in configuration of security-domains:

    1. New configuration for security-domain host needs to be added:

      <security-domain name="host">
        <authentication>
          <login-module code="com.sun.security.auth.module.Krb5LoginModule" flag="required">
            <module-option name="storeKey" value="true" />
            <module-option name="useKeyTab" value="true" />
            <module-option name="principal" value="HTTP/server.local.network@LOCAL.NETWORK" />
            <module-option name="keyTab" value="/etc/krb5.keytab" />
            <module-option name="doNotPrompt" value="true" />
            <module-option name="debug" value="true" />
          </login-module>
        </authentication>
      </security-domain>

      It's used internally by JBoss negotiation to verify server principal from Kerberos keytab. Important options, which you may need to change are:
      - principal -- This points to HTTP server principal from your kerberos keytab. In SPNEGO Server Configuration we used Kerberos realm LOCAL.NETWORK and host server.local.network and so we added principal HTTP/server.local.network@LOCAL.NETWORK to our keytab.
      - keyTab -- This points to file with your Kerberos keytab. In Kerberos configuration we used location /etc/krb5.keytab . Please note that this file should be readable by user, under which is GateIn Portal executed .

      Generally Kerberos keytab files shouldn't be readable by normal OS users as they contain encrypted keys of server principals. Consult Kerberos documentation for more details

      - debug -- Enabling this option will add more STDOUT messages into GateIn Portal console and log file. It's good to have it enabled during setup, but in production it may be good to disable it to avoid huge server logs.

    2. Existing gatein-domain needs to be renamed to gatein-form-auth-domain

    3. New configuration for gatein-domain needs to be added:

      <security-domain name="gatein-domain" cache-type="default">
        <authentication>
          <login-module code="org.gatein.sso.spnego.SPNEGOLoginModule" flag="requisite">
            <module-option name="password-stacking" value="useFirstPass"/>
            <module-option name="serverSecurityDomain" value="host"/>
            <module-option name="removeRealmFromPrincipal" value="true"/>
            <module-option name="usernamePasswordDomain" value="gatein-form-auth-domain"/>
          </login-module>
          <login-module code="org.gatein.sso.agent.login.SPNEGORolesModule" flag="required">
            <module-option name="password-stacking" value="useFirstPass"/>
            <module-option name="portalContainerName" value="portal"/>
            <module-option name="realmName" value="gatein-domain"/>
          </login-module>
        </authentication>
      </security-domain>

      So with all 3 changes the configuration in standalone.xml file should be similar to this:

      <security-domain name="gatein-form-auth-domain" cache-type="default">
        <authentication>
          <login-module code="org.gatein.security.oauth.jaas.OAuthLoginModule" flag="required">
            <module-option name="portalContainerName" value="portal"/>
            <module-option name="realmName" value="gatein-domain"/>
          </login-module>
          <login-module code="org.gatein.sso.integration.SSODelegateLoginModule" flag="required">
            <module-option name="enabled" value="#{gatein.sso.login.module.enabled}" />
            <module-option name="delegateClassName" value="#{gatein.sso.login.module.class}" />
            <module-option name="portalContainerName" value="portal" />
            <module-option name="realmName" value="gatein-domain" />
            <module-option name="password-stacking" value="useFirstPass" />
          </login-module>
          <login-module code="org.exoplatform.services.security.j2ee.JBossAS7LoginModule" flag="required">
            <module-option name="portalContainerName" value="portal"/>
            <module-option name="realmName" value="gatein-domain"/>
          </login-module>
        </authentication>
      </security-domain>
      
      <security-domain name="host">
        <authentication>
          <login-module code="com.sun.security.auth.module.Krb5LoginModule" flag="required">
            <module-option name="storeKey" value="true" />
            <module-option name="useKeyTab" value="true" />
            <module-option name="principal" value="HTTP/server.local.network@LOCAL.NETWORK" />
            <module-option name="keyTab" value="/etc/krb5.keytab" />
            <module-option name="doNotPrompt" value="true" />
            <module-option name="debug" value="true" />
          </login-module>
        </authentication>
      </security-domain>
      
      <security-domain name="gatein-domain" cache-type="default">
        <authentication>
          <login-module code="org.gatein.sso.spnego.SPNEGOLoginModule" flag="requisite">
            <module-option name="password-stacking" value="useFirstPass"/>
            <module-option name="serverSecurityDomain" value="host"/>
            <module-option name="removeRealmFromPrincipal" value="true"/>
            <module-option name="usernamePasswordDomain" value="gatein-form-auth-domain"/>
          </login-module>
          <login-module code="org.gatein.sso.agent.login.SPNEGORolesModule" flag="required">
            <module-option name="password-stacking" value="useFirstPass"/>
            <module-option name="portalContainerName" value="portal"/>
            <module-option name="realmName" value="gatein-domain"/>
          </login-module>
        </authentication>
      </security-domain>
  3. So assuming that your kerberos realm is LOCAL.NETWORK and your kerberos KDC is on host server.local.network and you will run GateIn Portal on same host server.local.network, you will need to use this command to start your GateIn Portal (Don't forget again that it needs to be executed under user with read permission to kerberos keytab file as mentioned above):

    ./standalone.sh -Djava.security.krb5.realm=LOCAL.NETWORK -Djava.security.krb5.kdc=server.local.network -b server.local.network
  4. Testing SPNEGO - Log into Kerberos with the kinit -A demo command (on linux).
    You should be able to go to http://server.local.network:8080/portal and click the 'Sign In' link on the GateIn Portal. Then the "demo" user should be automatically logged into GateIn Portal.

  5. Testing FORM fallback - Let's destroy the kerberos ticket with command kdestroy. Then try to logout from GateIn Portal and login again. You will now be placed to GateIn Portal login screen because you do not have active Kerberos ticket. You can log in with predefined account and password "demo"/"gtn" . It works this way because you have SPNEGO integration enabled and integrated with your kerberos, but if user doesn't have active Kerberos ticket, it will fallback to default FORM based authentication, so user has possibility to fill his credentials classically via GateIn Portal login screen.

Disable fallback to FORM authentication

As mentioned in previous paragraph, the fallback to FORM authentication is automatically enabled. This means that user can authenticate either via SPNEGO handshake with his kerberos ticket or via providing his credentials in GateIn Portal login form, which will perform verification of credentials against Picketlink IDM database.

For some reason you may want to enforce authentication only via SPNEGO and disable possibility to authenticate with GateIn Portal login FORM. In this case you will need to edit configuration of SPNEGOLoginModule in GATEIN_HOME/standalone/configuration/standalone.xml and comment the usernamePasswordDomain option:

<login-module
    code="org.gatein.sso.spnego.SPNEGOLoginModule" flag="requisite">
    <module-option name="password-stacking" value="useFirstPass"/>
    <module-option name="serverSecurityDomain" value="host"/>
    <module-option name="removeRealmFromPrincipal" value="true"/>
<!--<module-option name="usernamePasswordDomain" value="gatein-form-auth-domain"/>-->
</login-module>

Tips & Tricks

  • Logging - Like for other SSO solutions, it may be good to enable trace logging for org.gatein.sso etc but in case of SPNEGO, it's good also to enable logging for org.jboss.security.negotiation, which is base package for JBoss Negotiation library. You can add these categories to JBOSS_HOME/standalone/configuration/standalone.xml :

    <logger category="org.gatein.sso">
      <level name="TRACE"/>
    </logger>
    <logger category="org.jboss.security.negotiation">
      <level name="TRACE"/>
    </logger>

    For Kerberos troubleshooting, you can enable increased logging to STDOUT by enable option debug of Krb5LoginModule as already described in section with login module configuration. Very helpful could be enabling system property for increased Kerberos logging by adding this to command line when running server:

    -Dsun.security.krb5.debug=true
  • Kerberos documentation

    • Kerberos FAQ: http://www.cmf.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html

    • Kerberos documentation for your linux distribution: Install package krb5-doc and enjoy documentation in directory /usr/share/doc/krb5-doc . There should be admin, install and user guide for Kerberos on your linux distribution.
      Note that Kerberos setup is OS specific and it's different for Windows with AD domain.

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-10 12:57:43 UTC, last content change 2013-05-10 12:55:43 UTC.