Red Hat Training

A Red Hat training course is available for Red Hat Fuse

5.2. BASIC Authentication with JAAS

Overview

The HTTP BASIC authentication protocol is a simple username/password authentication mechanism that is integrated into HTTP and is supported by most Web browsers. To enable BASIC authentication in Jetty, you use the Jetty security API, which enables BASIC authentication by associating a security handler with the Jetty endpoint.
Jetty also enables you to plug in a JAAS login module to perform the credentials check. Using this feature, it is possible to integrate credentials checking with any JAAS realm provided by the Red Hat JBoss Fuse OSGi container. In the example shown here, the Jetty authentication is integrated with the default JAAS realm, karaf.

Prerequisites

This example builds on the project created in Section 5.1, “Enabling SSL/TLS Security”. You must complete the steps in the Jetty SSL/TLS example before proceeding with this tutorial.
Note
In any case, it is highly recommended that you always enable SSL/TLS in combination with BASIC authentication, in order to protect against password snooping.

Authentication steps

To configure HTTP BASIC authentication for a Camel Jetty endpoint deployed in the OSGi container, perform the following steps:

Add the Jetty security handler configuration

In the jetty-security project, edit the jetty-spring.xml file from the src/main/resources/META-INF/spring directory. To configure the Jetty security handler with BASIC authentication, add the following bean definitions:
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    ...
    <!--  -->
    <bean id="loginService" class="org.eclipse.jetty.plus.jaas.JAASLoginService">
        <property name="name" value="karaf"/>
        <property name="loginModuleName" value="karaf"/>
        <property name="roleClassNames">
            <list>
                <value>org.apache.karaf.jaas.boot.principal.RolePrincipal</value>
            </list>
        </property>
    </bean>

    <bean id="identityService" class="org.eclipse.jetty.security.DefaultIdentityService"/>

    <bean id="constraint" class="org.eclipse.jetty.util.security.Constraint">
        <property name="name" value="BASIC"/>
        <property name="roles" value="admin"/>
        <property name="authenticate" value="true"/>
    </bean>

    <bean id="constraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
        <property name="constraint" ref="constraint"/>
        <property name="pathSpec" value="/*"/>
    </bean>

    <bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
        <property name="authenticator">
            <bean class="org.eclipse.jetty.security.authentication.BasicAuthenticator"/>
        </property>
        <property name="constraintMappings">
            <list>
                <ref bean="constraintMapping"/>
            </list>
        </property>
        <property name="loginService" ref="loginService"/>
        <property name="strict" value="false"/>
        <property name="identityService" ref="identityService"/>
    </bean>
    ...
</beans>
Two aspects of Jetty authentication are configured by the preceding bean definitions:
  • HTTP BASIC authentication—the constraint bean enables HTTP BASIC authentication on the Jetty security handler.
  • JAAS login service—the loginService bean specifies that the requisite authentication data is extracted from a JAAS realm. The loginModuleName property specifies that the Jetty login service uses the karaf JAAS realm, which is the OSGi container's default JAAS realm (see Section 1.1, “OSGi Container Security”).

Modify Camel Jetty endpoint

After creating the Jetty securityHandler bean, you must modify the Jetty endpoint URI in the Apache Camel route, so that it hooks into the security handler. To add the security handler to the Jetty endpoint, set the handlers option equal to the security handler's bean ID, as shown in the following example:
<beans ...>
    <camelContext trace="true" xmlns="http://camel.apache.org/schema/spring">
        <route>
            <from uri="jetty:https://0.0.0.0:8282/services?handlers=securityHandler&amp;matchOnUriPrefix=true"/>
            <transform>
                <constant>&lt;html>&lt;body>Hello from Fuse ESB server&lt;/body>&lt;/html></constant>
            </transform>
        </route>
    </camelContext>
</beans>
Note
URI options must be separated by the &amp; entity, instead of the plain & character, in the context of an XML file.

Add required package imports to POM

Edit the jetty-security project's POM file, jetty-security/pom.xml. Near the start of the POM file, define the jetty-version property as follows:
<project ... >
  ...
  <properties>
    ...
 <jetty-version>7.2.2.v20101205</jetty-version>
  </properties>
  ...
</project>
Further down the POM file, in the configuration of the Maven bundle plug-in, modify the bundle instructions to import additional Java packages, as follows:
<project ... >
  ...
  <build>
    ...
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Bundle-SymbolicName>
              ${project.artifactId}
            </Bundle-SymbolicName>
            <Import-Package>
                javax.security.auth,
                javax.security.auth.callback,
                javax.security.auth.login,
                javax.security.auth.spi,
                org.apache.karaf.jaas.modules,
                org.apache.karaf.jaas.boot.principal,
                org.eclipse.jetty.plus.jaas;version=${jetty-version},
                org.eclipse.jetty.security;version=${jetty-version},
                *
            </Import-Package>
            <Private-Package>org.apache.camel.jaas</Private-Package>

          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
  ...
</project>
Note
These extra imports are required, because the Maven bundle plug-in is not capable of scanning Spring files to determine their package dependencies automatically.

Build the bundle

Use Maven to build the bundle. Open a command prompt, switch the current directory to ProjectDir/jetty-security, and enter the following command:
mvn install

Install the required features

If you have not already done so, start up the Apache ServiceMix console (and container instance) by entering the following command in a new command prompt:
servicemix
Install the jetty and camel-jetty features, by entering the following console commands:
karaf@root> features:install jetty
karaf@root> features:install camel-jetty

Deploy the bundle

To deploy and activate the bundle, enter the following console command:
JBossFuse:karaf@root> osgi:install -s mvn:org.jbossfuse.example/jetty-security

Test the bundle

To test the Jetty service, open your favorite Web browser and navigate to the following URL:
https://localhost:8282/services
Note
Don't forget to use https: instead of http: in the URL!
If you closed your browser since running the Jetty SSL/TLS demonstration (thus re-initializing the security status of your browser), your browser will initially present you with a warning about the untrusted certificate. For example, the Firefox browser displays the following warning screen:

Figure 5.2. Untrusted Certificate Warning

Untrusted Certificate Warning
To proceed with contacting the Jetty service, click I Understand the Risks and then click Add Exception, which brings up the Add Security Exception dialog. In the Add Security Exception dialog, make sure that the Permanently store this exception option is unchecked and click Confirm Security Exception.
You will now be prompted to authenticate yourself with a username and password (this is the BASIC authentication step). Enter the username, smx, and the password, smx, and click Ok (the valid credentials you can use for this step are specified in the EsbInstallDir/etc/users.properties file). The browser window should now display the following text:
Hello from Fuse ESB server