10.6.2. Inside of the SRP algorithm

The appeal of the SRP algorithm is that is allows for mutual authentication of client and server using simple text passwords without a secure communication channel. You might be wondering how this is done. If you want the complete details and theory behind the algorithm, refer to the SRP references mentioned in a note earlier. There are six steps that are performed to complete authentication:
  1. The client side SRPLoginModule retrieves the SRPServerInterface instance for the remote authentication server from the naming service.
  2. The client side SRPLoginModule next requests the SRP parameters associated with the username attempting the login. There are a number of parameters involved in the SRP algorithm that must be chosen when the user password is first transformed into the verifier form used by the SRP algorithm. Rather than hard-coding the parameters (which could be done with minimal security risk), the JBossSX implementation allows a user to retrieve this information as part of the exchange protocol. The getSRPParameters(username) call retrieves the SRP parameters for the given username.
  3. The client side SRPLoginModule begins an SRP session by creating an SRPClientSession object using the login username, clear-text password, and SRP parameters obtained from step 2. The client then creates a random number A that will be used to build the private SRP session key. The client then initializes the server side of the SRP session by invoking the SRPServerInterface.init method and passes in the username and client generated random number A. The server returns its own random number B. This step corresponds to the exchange of public keys.
  4. The client side SRPLoginModule obtains the private SRP session key that has been generated as a result of the previous messages exchanges. This is saved as a private credential in the login Subject. The server challenge response M2 from step 4 is verified by invoking the SRPClientSession.verify method. If this succeeds, mutual authentication of the client to server, and server to client have been completed. The client side SRPLoginModule next creates a challenge M1 to the server by invoking SRPClientSession.response method passing the server random number B as an argument. This challenge is sent to the server via the SRPServerInterface.verify method and server's response is saved as M2. This step corresponds to an exchange of challenges. At this point the server has verified that the user is who they say they are.
  5. The client side SRPLoginModule saves the login username and M1 challenge into the LoginModule sharedState map. This is used as the Principal name and credentials by the standard JBoss ClientLoginModule. The M1 challenge is used in place of the password as proof of identity on any method invocations on J2EE components. The M1 challenge is a cryptographically strong hash associated with the SRP session. Its interception via a third partly cannot be used to obtain the user's password.
  6. At the end of this authentication protocol, the SRPServerSession has been placed into the SRPService authentication cache for subsequent use by the SRPCacheLoginModule.
Although SRP has many interesting properties, it is still an evolving component in the JBossSX framework and has some limitations of which you should be aware. Issues of note include the following:
  • Because of how JBoss detaches the method transport protocol from the component container where authentication is performed, an unauthorized user could snoop the SRP M1 challenge and effectively use the challenge to make requests as the associated username. Custom interceptors that encrypt the challenge using the SRP session key can be used to prevent this issue.
  • The SRPService maintains a cache of SRP sessions that time out after a configurable period. Once they time out, any subsequent J2EE component access will fail because there is currently no mechanism for transparently renegotiating the SRP authentication credentials. You must either set the authentication cache timeout very long (up to 2,147,483,647 seconds, or approximately 68 years), or handle re-authentication in your code on failure.
  • By default there can only be one SRP session for a given username. Because the negotiated SRP session produces a private session key that can be used for encryption/decryption between the client and server, the session is effectively a stateful one. JBoss supports for multiple SRP sessions per user, but you cannot encrypt data with one session key and then decrypt it with another.
To use end-to-end SRP authentication for J2EE component calls, you need to configure the security domain under which the components are secured to use the org.jboss.security.srp.jaas.SRPCacheLoginModule. The SRPCacheLoginModule has a single configuration option named cacheJndiName that sets the JNDI location of the SRP authentication CachePolicy instance. This must correspond to the AuthenticationCacheJndiName attribute value of the SRPService MBean. The SRPCacheLoginModule authenticates user credentials by obtaining the client challenge from the SRPServerSession object in the authentication cache and comparing this to the challenge passed as the user credentials. Figure 10.16, “A sequence diagram illustrating the interaction of the SRPCacheLoginModule with the SRP session cache.” illustrates the operation of the SRPCacheLoginModule.login method implementation.
A sequence diagram illustrating the interaction of the SRPCacheLoginModule with the SRP session cache.

Figure 10.16. A sequence diagram illustrating the interaction of the SRPCacheLoginModule with the SRP session cache.

10.6.2.1. An SRP example

We have covered quite a bit of material on SRP and now its time to demonstrate SRP in practice with an example. The example demonstrates client side authentication of the user via SRP as well as subsequent secured access to a simple EJB using the SRP session challenge as the user credential. The test code deploys an EJB JAR that includes a SAR for the configuration of the server side login module configuration and SRP services. As in the previous examples we will dynamically install the server side login module configuration using the SecurityConfig MBean. In this example we also use a custom implementation of the SRPVerifierStore interface that uses an in memory store that is seeded from a Java properties file rather than a serialized object store as used by the SRPVerifierStoreService. This custom service is org.jboss.book.security.ex3.service.PropertiesVerifierStore. The following shows the contents of the JAR that contains the example EJB and SRP services.
[examples]$ jar tf output/security/security-ex3.jar 
META-INF/MANIFEST.MF
META-INF/ejb-jar.xml
META-INF/jboss.xml
org/jboss/book/security/ex3/Echo.class
org/jboss/book/security/ex3/EchoBean.class
org/jboss/book/security/ex3/EchoHome.class
roles.properties
users.properties
security-ex3.sar
The key SRP related items in this example are the SRP MBean services configuration, and the SRP login module configurations. The jboss-service.xml descriptor of the security-ex3.sar is given in Example 10.16, “The security-ex3.sar jboss-service.xml descriptor for the SRP services”, while Example 10.17, “The client side standard JAAS configuration” and Example 10.18, “The server side XMLLoginConfig configuration” give the example client side and server side login module configurations.

Example 10.16. The security-ex3.sar jboss-service.xml descriptor for the SRP services

<server>
    <!-- The custom JAAS login configuration that installs
         a Configuration capable of dynamically updating the
         config settings -->

    <mbean code="org.jboss.book.security.service.SecurityConfig" 
           name="jboss.docs.security:service=LoginConfig-EX3">
        <attribute name="AuthConfig">META-INF/login-config.xml</attribute>
        <attribute name="SecurityConfigName">jboss.security:name=SecurityConfig</attribute>
    </mbean>

    <!-- The SRP service that provides the SRP RMI server and server side
         authentication cache -->
    <mbean code="org.jboss.security.srp.SRPService" 
           name="jboss.docs.security:service=SRPService">
        <attribute name="VerifierSourceJndiName">srp-test/security-ex3</attribute>
        <attribute name="JndiName">srp-test/SRPServerInterface</attribute>
        <attribute name="AuthenticationCacheJndiName">srp-test/AuthenticationCache</attribute>
        <attribute name="ServerPort">0</attribute>
        <depends>jboss.docs.security:service=PropertiesVerifierStore</depends>
    </mbean>

    <!-- The SRP store handler service that provides the user password verifier
         information -->
    <mbean code="org.jboss.security.ex3.service.PropertiesVerifierStore"
           name="jboss.docs.security:service=PropertiesVerifierStore">
        <attribute name="JndiName">srp-test/security-ex3</attribute>
    </mbean>
</server>

Example 10.17. The client side standard JAAS configuration

srp {
    org.jboss.security.srp.jaas.SRPLoginModule required
    srpServerJndiName="srp-test/SRPServerInterface"
    ;
                    
    org.jboss.security.ClientLoginModule required
    password-stacking="useFirstPass"
    ;
};

Example 10.18. The server side XMLLoginConfig configuration

<application-policy name="security-ex3">
    <authentication>
        <login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule"
                      flag = "required">
            <module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option>
        </login-module>
        <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
                      flag = "required">
            <module-option name="password-stacking">useFirstPass</module-option>
        </login-module>
    </authentication>
</application-policy>
The example services are the ServiceConfig and the PropertiesVerifierStore and SRPService MBeans. Note that the JndiName attribute of the PropertiesVerifierStore is equal to the VerifierSourceJndiName attribute of the SRPService, and that the SRPService depends on the PropertiesVerifierStore. This is required because the SRPService needs an implementation of the SRPVerifierStore interface for accessing user password verification information.
The client side login module configuration makes use of the SRPLoginModule with a srpServerJndiName option value that corresponds to the JBoss server component SRPService JndiName attribute value(srp-test/SRPServerInterface). Also needed is the ClientLoginModule configured with the password-stacking="useFirstPass" value to propagate the user authentication credentials generated by the SRPLoginModule to the EJB invocation layer.
There are two issues to note about the server side login module configuration. First, note the cacheJndiName=srp-test/AuthenticationCache configuration option tells the SRPCacheLoginModule the location of the CachePolicy that contains the SRPServerSession for users who have authenticated against the SRPService. This value corresponds to the SRPServiceAuthenticationCacheJndiName attribute value. Second, the configuration includes a UsersRolesLoginModule with the password-stacking=useFirstPass configuration option. It is required to use a second login module with the SRPCacheLoginModule because SRP is only an authentication technology. A second login module needs to be configured that accepts the authentication credentials validated by the SRPCacheLoginModule to set the principal's roles that determines the principal's permissions. The UsersRolesLoginModule is augmenting the SRP authentication with properties file based authorization. The user's roles are coming the roles.properties file included in the EJB JAR.
Now, run the example 3 client by executing the following command from the book examples directory:
[examples]$ ant -Dchap=security -Dex=3 run-example
...
run-example3:
     [echo] Waiting for 5 seconds for deploy...
     [java] Logging in using the 'srp' configuration
     [java] Created Echo
     [java] Echo.echo()#1 = This is call 1
     [java] Echo.echo()#2 = This is call 2
In the examples/logs directory you will find a file called ex3-trace.log. This is a detailed trace of the client side of the SRP algorithm. The traces show step-by-step the construction of the public keys, challenges, session key and verification.
Note that the client has taken a long time to run relative to the other simple examples. The reason for this is the construction of the client's public key. This involves the creation of a cryptographically strong random number, and this process takes quite a bit of time the first time it occurs. If you were to log out and log in again within the same VM, the process would be much faster. Also note that Echo.echo()#2 fails with an authentication exception. The client code sleeps for 15 seconds after making the first call to demonstrate the behavior of the SRPService cache expiration. The SRPService cache policy timeout has been set to a mere 10 seconds to force this issue. As stated earlier, you need to make the cache timeout very long, or handle re-authentication on failure.