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.jaas.JAASLoginService">
        <property name="name" value="Your Services Realm"/>
        <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="Administrator"/>
        <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="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. The roles property (of String[] type) is used to define which roles have access to the Jetty container. In this example, this property is set to Administrator, so only users with the Administrator role can access this Jetty container.
  • 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. 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.groupId}.${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.jaas,
                org.eclipse.jetty.security,
                *
            </Import-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 clean install -Dmaven.test.skip=true

Install the required features

If you have not already done so, start up the JBoss Fuse container by entering the following command in a new command prompt:
./bin/fuse
If not already installed, install the camel-jetty feature using the following console command:
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/1.0-SNAPSHOT

Test the bundle

To test the Jetty service, enter the following curl command at a comand-line prompt:
curl https://0.0.0.0:8282/services -k --user Username:Password
Note
Don't forget to use https: instead of http: in the URL!
The --user option is needed to specify the BASIC authentication credentials. For the Username and Password values, specify valid JAAS credentials (the valid credentials you can use for this step are specified in the EsbInstallDir/etc/users.properties file). You should now receive the following HTTP reply message:
<html><body>Hello from Fuse ESB server</body></html>