Code Monkey home page Code Monkey logo

spnego-demo's Introduction

SPNEGO secured web application demo for JBoss EAP & WildFly

Demo application which shows, how to get Kerberos authentication working in WildFly and JBoss Enterprise Application Platform (EAP).

The out of the box SPNEGO authentication doesn't work in WildFly versions 8 and 9 because missing integration part with Undertow (new web server component). The issue (WFLY-2553) was resolved in WildFly 10. If you need to get SPNEGO working with WildFly 8.x/9.x, try to use either servlet filter approach or this custom authenticator for WildFly.

How does it work?

  • new dependency on org.jboss.security.negotiation AS module is defined in META-INF/jboss-deployment-structure.xml deployment descriptor file in the SPNEGO-enabled application

    <jboss-deployment-structure>
        <deployment>
            <dependencies>
                <module name="org.jboss.security.negotiation" />
            </dependencies>
        </deployment>
    </jboss-deployment-structure>
  • We have to define which security domain will be used for authentication to the application in WEB-INF/jboss-web.xml deployment descriptor:

    <jboss-web>
        <security-domain>SPNEGO</security-domain>
    </jboss-web>
    • In case of EAP 6.x and JBoss AS7 (i.e. the versions with Tomcat based web server), you have also to use custom authenticator valve. The valve class is present in the org.jboss.security.negotiation module, which we introduced as dependency in the first step.

      <jboss-web>
          <security-domain>SPNEGO</security-domain>
          <valve>
              <class-name>org.jboss.security.negotiation.NegotiationAuthenticator</class-name>
          </valve>
      </jboss-web>
  • The security domain in server configuration (standalone.xml) uses the SPNEGOLoginModule JAAS login module and it has name SPNEGO in this demo.

    <security-domain name="SPNEGO" cache-type="default">
        <authentication>
            <login-module code="SPNEGO" flag="required">
                <module-option name="serverSecurityDomain" value="host"/>
            </login-module>
        </authentication>
        <mapping>
            <mapping-module code="SimpleRoles" type="role">
                <module-option name="[email protected]" value="Admin"/>
                <module-option name="[email protected]" value="User"/>
            </mapping-module>
        </mapping>
    </security-domain>
  • The SPNEGO security domain references the second domain which is used for server authentication in the Kerberos realm. It uses Krb5LoginModule login module and its name is host.

    <security-domain name="host" cache-type="default">
        <authentication>
            <login-module code="Kerberos" flag="required">
                <module-option name="storeKey" value="true"/>
                <module-option name="refreshKrb5Config" value="true"/>
                <module-option name="useKeyTab" value="true"/>
                <module-option name="doNotPrompt" value="true"/>
                <module-option name="keyTab" value="/tmp/spnego-demo-testdir/http.keytab"/>
                <module-option name="principal" value="HTTP/[email protected]"/>
            </login-module>
        </authentication>
    </security-domain>

Prepare your environment

There are several steps, which should be completed to get the demo working.

Prepare your system

Install MIT kerberos utils, Java JDK version 6 or newer, git and Maven, unzip and wget.

Fedora:

sudo yum install wget unzip java-1.7.0-openjdk-devel krb5-workstation maven git

Ubuntu:

sudo apt-get install wget unzip openjdk-6-jdk krb5-user git maven

Prepare your browser

If you use the Firefox, go to about:config and set following entries there:

network.negotiate-auth.delegation-uris = localhost
network.negotiate-auth.trusted-uris = localhost

If you use Chromium, then start it with following command line arguments:

chromium-browser --auth-server-whitelist=localhost --auth-negotiate-delegate-whitelist=localhost

Prepare a folder for your tests

export SPNEGO_TEST_DIR=/tmp/spnego-demo-testdir
mkdir $SPNEGO_TEST_DIR

Prepare the Kerberos server

If you don't have some Kerberos server prepared already, you can use the testing kerberos-using-apacheds project:

cd $SPNEGO_TEST_DIR
git clone git://github.com/kwart/kerberos-using-apacheds.git
cd kerberos-using-apacheds
mvn clean package
cp test.ldif target/kerberos-using-apacheds.jar $SPNEGO_TEST_DIR

The test server has hardcoded following settings:

searchBaseDn = dc=jboss,dc=org
primaryRealm = JBOSS.ORG
kdcPrincipal = krbtgt/[email protected]

Start the server and import test data

The test server project is a runnable JAR file

cd $SPNEGO_TEST_DIR
java -jar kerberos-using-apacheds.jar test.ldif

Launching the test server also creates a krb5.conf kerberos configuration file in the current folder. We will use it later.

There are 3 important users which you will use later in the imported test.ldif file:

dn: uid=HTTP,ou=Users,dc=jboss,dc=org
userPassword: httppwd
krb5PrincipalName: HTTP/${hostname}@JBOSS.ORG

dn: uid=hnelson,ou=Users,dc=jboss,dc=org
userPassword: secret
krb5PrincipalName: [email protected]

dn: uid=jduke,ou=Users,dc=jboss,dc=org
userPassword: theduke
krb5PrincipalName: [email protected]

The HTTP user is the principal of your WildFly/EAP server. The other 2 users are test client principals. The ${hostname} is a placeholder which will be replaced with the value of system property kerberos.bind.address. It this property is not defined, then the localhost value is used.

Customize the client's krb5.conf

The previous step generated krb5.conf file. Backup your original configuration in /etc/krb5.conf and replace it with the generated one.

mv /etc/krb5.conf /etc/krb5.conf.orig
cp $SPNEGO_TEST_DIR/krb5.conf /etc/krb5.conf

Correct configuration in krb5.conf file is necessary for client authentication (kinit) and also for correct negotiation in a web browser.

Login to Kerberos as [email protected]

Refer to generated krb5.conf file and use kinit system tool to authenticate in Kerberos.

kinit [email protected] << EOT
secret
EOT

Prepare keytab file for the JBoss AS authentication in Kerberos

A keytab is a file containing pairs of Kerberos principals and encrypted keys derived from the Kerberos password. Keytab files can be used to log into Kerberos without being prompted for a password (e.g. authenticate without human interaction).

Use the CreateKeytab utility from the kerberos-using-apacheds project to generate the keytab for the HTTP/[email protected] principal:

cd $SPNEGO_TEST_DIR
java -classpath kerberos-using-apacheds.jar \
  org.jboss.test.kerberos.CreateKeytab \
  HTTP/[email protected] \
  httppwd \
  http.keytab

You can also use some system utility such as ktutil to generate your keytab file.

Prepare WildFly

Download the latest WildFly and install it.

Configure the server using JBoss CLI:

export JBOSS_HOME=/path/to/wildflyFolder

cat << EOT > $SPNEGO_TEST_DIR/cli-commands.txt
embed-server
/subsystem=security/security-domain=host:add(cache-type=default)
/subsystem=security/security-domain=host/authentication=classic:add(login-modules=[{"code"=>"Kerberos", "flag"=>"required", "module-options"=>[ ("debug"=>"true"),("storeKey"=>"true"),("refreshKrb5Config"=>"true"),("useKeyTab"=>"true"),("doNotPrompt"=>"true"),("keyTab"=>"$SPNEGO_TEST_DIR/http.keytab"),("principal"=>"HTTP/[email protected]")]}]) {allow-resource-service-restart=true}

/subsystem=security/security-domain=SPNEGO:add(cache-type=default)
/subsystem=security/security-domain=SPNEGO/authentication=classic:add(login-modules=[{"code"=>"SPNEGO", "flag"=>"required", "module-options"=>[("serverSecurityDomain"=>"host")]}]) {allow-resource-service-restart=true}
/subsystem=security/security-domain=SPNEGO/mapping=classic:add(mapping-modules=[{"code"=>"SimpleRoles", "type"=>"role", "module-options"=>[("[email protected]"=>"Admin"),("[email protected]"=>"User")]}]) {allow-resource-service-restart=true}

/system-property=java.security.krb5.conf:add(value="$SPNEGO_TEST_DIR/krb5.conf")
/system-property=java.security.krb5.debug:add(value=true)
/system-property=jboss.security.disable.secdomain.option:add(value=true)
EOT
"$JBOSS_HOME/jboss-cli.sh" --file=$SPNEGO_TEST_DIR/cli-commands.txt

Start the configured WildFly server:

$JBOSS_HOME/bin/standalone.sh

You've created host and SPNEGO security domains now. Also some kerberos authentication related system properties were added.

Prepare and deploy the demo application

Use this spnego-demo web application to test your settings.

cd $SPNEGO_TEST_DIR
git clone git://github.com/kwart/spnego-demo.git
cd spnego-demo
mvn clean package
cp target/spnego-demo.war $JBOSS_HOME/standalone/deployments 

Test the application

Open the application URL in your SPNEGO enabled browser

chromium-browser --auth-server-whitelist=localhost \
  --auth-negotiate-delegate-whitelist=localhost http://localhost:8080/spnego-demo/

There are 3 test pages included:

License

spnego-demo's People

Contributors

kwart avatar seanf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spnego-demo's Issues

[Krb5LoginModule] authentication failed null (68)

Hi,
i have setup this spnego-demo project, and has configured all the required configuration.

Still i get the authentication fail. Please advise.
Below is the error which i get in console.

15:40:24,693 INFO [stdout] (http-localhost-127.0.0.1-8080-3) Refreshing Kerberos configuration

15:40:26,935 INFO [stdout] (http-localhost-127.0.0.1-8080-3) [Krb5LoginModule] authentication failed
15:40:26,936 INFO [stdout] (http-localhost-127.0.0.1-8080-3) null (68)

15:40:26,946 ERROR [org.jboss.security.authentication.JBossCachedAuthenticationManager] (http-localhost-127.0.0.1-8080-3) Login failure: javax.security.auth.login.LoginException: null (68)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source) [rt.jar:1.7.0_79]
at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source) [rt.jar:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [rt.jar:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [rt.jar:1.7.0_79]
at java.lang.reflect.Method.invoke(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.invoke(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.access$000(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext$4.run(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext$4.run(Unknown Source) [rt.jar:1.7.0_79]
at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.invokePriv(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.login(Unknown Source) [rt.jar:1.7.0_79]
at org.jboss.security.negotiation.spnego.SPNEGOLoginModule.getServerSubject(SPNEGOLoginModule.java:282) [jboss-negotiation-spnego-2.2.0.SP1.jar:2.2.0.SP1]
at org.jboss.security.negotiation.spnego.SPNEGOLoginModule.spnegoLogin(SPNEGOLoginModule.java:235) [jboss-negotiation-spnego-2.2.0.SP1.jar:2.2.0.SP1]
at org.jboss.security.negotiation.spnego.SPNEGOLoginModule.innerLogin(SPNEGOLoginModule.java:194) [jboss-negotiation-spnego-2.2.0.SP1.jar:2.2.0.SP1]
at org.jboss.security.negotiation.spnego.SPNEGOLoginModule.login(SPNEGOLoginModule.java:137) [jboss-negotiation-spnego-2.2.0.SP1.jar:2.2.0.SP1]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_79]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) [rt.jar:1.7.0_79]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) [rt.jar:1.7.0_79]
at java.lang.reflect.Method.invoke(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.invoke(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.access$000(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext$4.run(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext$4.run(Unknown Source) [rt.jar:1.7.0_79]
at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.invokePriv(Unknown Source) [rt.jar:1.7.0_79]
at javax.security.auth.login.LoginContext.login(Unknown Source) [rt.jar:1.7.0_79]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(JBossCachedAuthenticationManager.java:449) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(JBossCachedAuthenticationManager.java:383) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.authenticate(JBossCachedAuthenticationManager.java:371) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(JBossCachedAuthenticationManager.java:160) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.as.web.security.JBossWebRealm.authenticate(JBossWebRealm.java:214) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.security.negotiation.NegotiationAuthenticator.authenticate(NegotiationAuthenticator.java:187) [jboss-negotiation-common-2.2.0.SP1.jar:2.2.0.SP1]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:455) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Unknown Source) [rt.jar:1.7.0_79]
Caused by: KrbException: null (68)
at sun.security.krb5.KrbAsRep.(Unknown Source) [rt.jar:1.7.0_79]
at sun.security.krb5.KrbAsReqBuilder.send(Unknown Source) [rt.jar:1.7.0_79]
at sun.security.krb5.KrbAsReqBuilder.action(Unknown Source) [rt.jar:1.7.0_79]
... 44 more
Caused by: KrbException: Identifier doesn't match expected value (906)
at sun.security.krb5.internal.KDCRep.init(Unknown Source) [rt.jar:1.7.0_79]
at sun.security.krb5.internal.ASRep.init(Unknown Source) [rt.jar:1.7.0_79]
at sun.security.krb5.internal.ASRep.(Unknown Source) [rt.jar:1.7.0_79]
... 47 more

javax.security.auth.login.LoginException: Continuation Required.

Hi, I'm trying to configure SPNEGO auth on a Jboss as 7 versus AD, but with no success. I've found this demo and I've decided to try this, following every step on the README, to figure out what I'm doing wrong in my other application, but after the kinit when I try to browse the user page I get an 401 response and the server raises this exception:

javax.security.auth.login.LoginException: Continuation Required.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.