Show TOC Start of Content Area

Procedure documentation Implementing the Login Module  Locate the document in its SAP Library structure

Use

In this step you implement the login module source code.

Procedure

Double click on the MyLoginModuleClass name. Implement the Java class:

...

       1.      Define the class package:

Syntax

package com.sap.example;

       2.      Import the classes and packages required for the compilation of the class:

Example

import java.util.Map;

import java.io.IOException;

 

import javax.security.auth.login.LoginException;

import javax.security.auth.Subject;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.UnsupportedCallbackException;

 

import com.sap.engine.interfaces.security.auth.AbstractLoginModule;

import com.sap.engine.lib.security.http.HttpGetterCallback;

import com.sap.engine.lib.security.http.HttpCallback;

import com.sap.engine.lib.security.LoginExceptionDetails;

import com.sap.engine.lib.security.Principal;

       3.      In the class extend the AbstractLoginModule class:

Syntax

public class MyLoginModuleClass extends AbstractLoginModule {

...

       4.      Define the variables for the tutorials example. These are used only for the tutorial:

// Define the variables that will be used later on

// in this example

private CallbackHandler callbackHandler = null;

private Subject subject = null;

private Map sharedState = null;

private Map options = null;

 

// This is the name of the user you have created on

// the J2EE Engine so you can test the login module

private String userName = null;

 

private boolean successful;

private boolean nameSet;

 

       5.      To initialize the login module with the relevant authentication and state information, create the initialize() method:

Syntax

/**

    * The method initialize the login module with the

    * relevant authentication and state information.

    */

   public void initialize(

      Subject subject,

      CallbackHandler callbackHandler,

      Map sharedState,

      Map options) {

      ...

                            a.      In the initialize() method, define the following obligatory source code:

Syntax

super.initialize(subject, callbackHandler, sharedState, options);

                            b.      Also initialize the values of the variables for the login module.

Example

// Initializing the values of the variables

this.callbackHandler = callbackHandler;

this.subject = subject;

this.sharedState = sharedState;

this.options = options;

this.successful = false;

this.nameSet = false;

       6.      Implement the login() method:

/**

  * Retrieves the user credentials and checks them. This is

  * the first part of the authentication process.

  */

public boolean login() throws LoginException {

   ...

                            a.      In the method, retrieve the user’s credentials using a callback handler.

Syntax

// Retrieve the user credentials using the callback

// handler.

// In this case we get the user name from the HTTP

// request parameters.

 

Callback[] callbacks = new Callback[1];

callbacks[0] = new HttpGetterCallback();

 

/* The type and the name specify which part of the HTTP request

 * should be retrieved. For Web container authentication, the

 * supported types are defined in the interface

 * com.sap.engine.lib.security.http.HttpCallback.

 * For programmatical authentication with custom callback

 * handler the supported types depend on the callback handler used.

 */

((HttpGetterCallback) callbacks[0]).setType(

   HttpCallback.REQUEST_PARAMETER);

   ((HttpGetterCallback) callbacks[0]).setName("user_name");

 

try {

   callbackHandler.handle(callbacks);

} catch (UnsupportedCallbackException e) {

   return false;

} catch (IOException e) {

   throwUserLoginException(e, LoginExceptionDetails.IO_EXCEPTION);

}

//Returns an array of all request parameters with name "user_name".

String[] requestParameters =

   (String[]) ((HttpGetterCallback) callbacks[0]).getValue();

if ((requestParameters != null) && requestParameters.length > 0) {

   userName = requestParameters[0];

}

if (userName == null) {

   throwNewLoginException("No user name provided.");

}

                            b.      When you know the user name, update the user information using data from the persistence. This operation must be done before the user credentials checks. The login() method also checks the user name. That means that if a user does not exist in the active user store, the method throws a java.lang.SecurityException:

Example

/* When you know the user name, you should update the user information

 * using data from the persistence. The operation must

 * be done before the user credentials checks. This method also

 * checks the user name so that if a user with that name does not

 * exist in the active user store, a

 * java.lang.SecurityException is thrown.

 */

try {

   refreshUserInfo(userName);

} catch (SecurityException e) {

   throwUserLoginException(e);

}

                            c.      Perform a check of the user’s credentials

Example

/* Checks if the given user name starts with the specified

 * prefix in the login module options. If no prefix is specified,

 * then all users are trusted.

 */

String prefix = (String) options.get("user_name_prefix");

if ((prefix != null) && !userName.startsWith(prefix)) {

   throwNewLoginException("The user is not trusted.");

}

                            d.      Only one and exactly one login module from the stack must put the user name in the shared state. This user name is considered to represent the authenticated user. For example if the login is successful, method getRemoteUser() of the HTTP request will retrieve exactly this name:

Example

/* This is done if the authentication of the login module is    

 * successful.

 * Only one and exactly one login module from the stack must put

 * the user name in the shared state. This user name represents

 * the authenticated user.

 * For example, if the login attempt is successful, method

 * getRemoteUser() of

 * the HTTP request will retrieve exactly this name.

 */

 

if (sharedState.get(AbstractLoginModule.NAME) == null) {

   sharedState.put(AbstractLoginModule.NAME, userName);

   nameSet = true;

}

 

successful = true;

return true;

In the example, we also set the variable successful to true and return the value true for the login module.

       7.      Implement the commit() method.

In this method you commit the log on. This is the second part of the authentication process. If a user’s name has been stored by the login() method, then this user name is added to the subject of a new principal.

Syntax

/**

 * Commit the login. This is the second part of the authentication

 * process.

 * If a user name has been stored by the login() method,

 * the user name is added to the subject as a new principal.

 */

public boolean commit() throws LoginException {

...

                            a.      The principals that are added to the subject should implement com.sap.engine.lib.security.Principal:

Example

if (successful) {

 

   /* The principals that are added to the subject should

    * implement java.security.Principal. You can use the class

    * com.sap.engine.lib.security.Principal for this purpose.

    */

   Principal principal = new Principal(userName);

   subject.getPrincipals().add(principal);

 

   /* If the login is successful, then the principal corresponding

    * to the <userName> (the same user name that has been added

    * to the shared state) must be added in the shared state too.

    * This principal is considered to be the main principal

    * representing the user.

    * For example, this principal will be retrieved from method

    * getUserPrincipal() of the HTTP request.

    */

 

   if (nameSet) {

      sharedState.put(AbstractLoginModule.PRINCIPAL, principal);

   }

} else {

   userName = null;

}

return true;

       8.      Implement the abort() method. This method is used for aborting the authentication process:

Example

/**

 * Abort the authentication process.

 */

public boolean abort() throws LoginException {

 

  if (successful) {

    userName = null;

    successful = false;

  }

 

   return true;

}

       9.      Implement the logout() method: The method logs out the user; it also removes the principals and destroys or removes the credentials that were associated with the user during the commit phase.

Example

/**

 * Log out the user. Also removes the principals and

 * destroys or removes the credentials that were associated 

 * with the user during the commit phase.

 */

public boolean logout() throws LoginException {

 

   // Remove principals and credentials from subject

   if (successful) {

      subject.getPrincipals(Principal.class).clear();

      successful = false;

   }

 

   return true;

}

Result

The login module class is implemented.

Example

For an example, see Example Login Module.

Next Step

Setting the Classpath and Compiling the Java Project

End of Content Area