Logon Service

Documentation home

 

Description. 1

Implementation. 2

Testing. 3

Example. 4

Supplied Implementation. 6

Invoking the Logon Service. 7

 

See also: Runtime Authentication, Roles and Credentials

 

 

Description

The Logon Service is a System Service (a special type of Integration Service) supplied with the system that can be customized to meet your requirements for authenticating users. The Logon Service is responsible for checking that a user is valid (e.g. by checking a userid/password) and then setting the userid as authenticated. Optionally, additional information - roles and credentials – can be associated with the user.

 

A Logon Service can be used for any or all of the following:

 

·         Checking userid/password combinations against a database

·         Looking up a userid in an Ldap Registry (such as Active Directory)

·         Obtaining user roles

·         Obtaining user credentials such as email, department, manager etc

 

Information about the user is supplied by the caller and is passed into the Logon Service in the Request document. This might contain a userid/password combination entered by the user, a userid extracted from the application server (e.g. for Windows domain single sign-on), some sort of user token extracted from the Http request header etc. Or any combination of these.

 

The Logon Service can be invoked automatically when a new session connects or it can be invoked programmatically at any time e.g. when a user attempts to access a restricted service:

 

 

Implementation

The Logon Service is a supplied system service named LOGON_SERVICE that is located from the designer tree System --> Internal Web Services --> System Services.

 

When the service is invoked, the script configured for the Logon Service’s integration event is executed. This script processes the information passed in the Request document, performs whatever processing is required, then builds a Response document that contains an authenticated userid, and optionally role and credential information for the user. 

 

The format of the input and output documents for the service are defined in the LOGON_REQUEST System Services Resource and cannot be changed. The input format is defined by the Request document and consists of up to three parameters where each parameter has a value and source type:

 

 

The format of the output is defined by the Response document, and must be populated by the script:

 

 

USERID: this must be set by the implementing script. This userid is then accepted by the system as authenticated and is used for the duration of the user’s session.

CUSTOMROLES: this is an optional table of custom roles that will be added to the user’s security definition.

EBASEROLES: this is an optional table of Ebase roles that will be added to the user’s security definition. Note that when using Ebase Workflow, at least one Ebase role should be configured to provide the user with security authorizations required by the workflow system.

CREDENTIALS: this is an optional table of credentials that will be added to the user’s security definition.

ERRORCODE: set this to a value other than 00000 to indicate that the logon has failed.

ERRORDESCRIPTION: set this in conjunction with ERRORCODE to indicate the reason why the logon has been rejected.

 

Testing

The LOGON_SERVICE service can be tested by clicking the test icon  on the toolbar of the System Service Editor. The test dialog shown below is then displayed. Fill in test values in the request document and click the Submit button.

 

 

 

 

Example

This Javascript script is configured to run on the System Service event of the Logon Service. It expects to receive a userid and password and will validate these against Active Directory and also extract role and credential information. This example uses methods on the API LdapServices class. Note that the XILdap.properties file must be configured to provide connection properties before these methods can be used.

 

importPackage(com.ebasetech.xi.api);

importPackage(com.ebasetech.xi.services);

 

var user = fields.PARAM1_VALUE.value;

var password = fields.PARAM2_VALUE.value;

 

// Authenticate the user against Active Directory

if (LdapServices.authenticate(user, password))

{

      // All OK, so set the userid

      fields.USERID.value = user;

      // then read role and credential info from Active Directory

      extractUserData(user); 

}

else

{

      fail("ERROR", "Authentication Failed");

}

 

function extractUserData(user)

{

      // Get all attributes for the user

      var attrs = LdapServices.getUserAttributes(user);

      // Extract roles

      extractRoles(attrs);

      // Extract credentials

      extractCredentials(attrs);

}

 

/**

 * Extract role names from Active Directory memberOf attributes for the user. For example, the following attribute:

 *   "CN=Ebase Finance,OU=Ebase Groups,OU=Security Groups,OU=Ebase Users and Groups,DC=ebasetech,DC=com"

 * becomes role name "Ebase_Finance".

 */

function extractRoles(attrs)

{

      var members = attrs.memberOf;

      if (members)

      {

            for each (var member in members)

            {

                  var names = member.split(",");

                  if (names && names.length > 0)

                  {

                        var first = names[0];

                        var attrWords = first.split("=");

                        if (attrWords && attrWords.length == 2)

                        {

                              var key = attrWords[0];

                              var value = attrWords[1];

                              if (key == "CN")

                              {

                                    // replace any spaces with underscores

                                    var groupName = value.replace(/\ /g, "_");

                                    tables.CUSTOMROLES.insertRow();

                                    tables.CUSTOMROLES.ROLEID.value = groupName;   

                              }

                        }

                  }

            }

      tables.CUSTOMROLES.updateTable();

      }

}

 

/**

 * Extract credentials from Active Directory e.g. the "mail" property is added as credential "email" etc.

 */

function extractCredentials(attrs)

{

      var credentials = [ ["mail", "email"], ["displayName", "name"], ["telephoneNumber", "phone"] ];

      for each (var credential in credentials)

      {

            var registryName = credential[0];

            var credentialName = credential[1];

            var attrArray = attrs[registryName];

            if (attrArray && attrArray.length > 0)

            {

                  tables.CREDENTIALS.insertRow();

                  tables.CREDENTIALS.ID.value = credentialName;

                  tables.CREDENTIALS.VALUE.value = attrArray[0];

            }

      }

      tables.CREDENTIALS.updateTable();

}

 

function fail(code, description)

{

      fields.USERID.value = null;

      fields.ERRORCODE.value = code;

      fields.ERRORDESCRIPTION.value = description;

}

 

Supplied Implementation

In the shipped product, XI Security properties are configured to provide the userid supplied by the application server.

 

Authentication is performed by one of the following 2 scripts, depending on version of Ebase:

 

1.    JS_LOGON_SERVICE_LOGIC  javascript script – is used starting from Ebase V4.5.2.

This allows for the userid being provided by the application server, and extracts user roles and credentials from Active Directory.

Calls functions defined in script JS_LOGON_SERVICE_FUNCTIONS.

 

importPackage(com.ebasetech.xi.api);

importPackage(com.ebasetech.xi.services);

 

var useridSource = fields.PARAM1_SOURCE.value;

var userid = fields.PARAM1_VALUE.value;

var pwd = fields.PARAM2_VALUE.value;

 

fields.USERID.value = null;

 

// 1. Check for no userid provided, send user to JSP signon panel

if ( !userid )

{

      fail("JSP", "Blank userid: PARAM1_VALUE is null");

}

 

// 2. Check for userid provided by application server, probably via integration with Active Directory.

// Accept the user id and setup security roles - one role for each AD group.

// Extract any user attributes from AD and add these as credentials.

// Also include the internal workflow role to allow ALL workflow operations by this user

else if ( isUseridFromApplicationServer(useridSource, userid) )

{

      populateRolesFromADGroups(userid);

      populateAttributesFromAD(userid);

      populateRolesForWorkFlow();

}

 

// 3. Check for input is from JSP signon panel

else if ( isJSPSignon(useridSource) )

{

  // authenticate userid against Ebase internal security system and populate internal security roles

  if ( authenticateInternalUser(userid, pwd) )

  {

      getInternalRoles(userid);

  }

  else

  {

      // if authentication fails, set error code to 'JSP' to indicate try again (up to configured maximum attempts)

      fail("JSP", "Invalid userid/password combination...");

  }

}

 

// If we reach this point, we have a valid user, so set this in the response document to indicate successful signon

fields.USERID.value = userid;

 

// Uncomment this while testing - it Writes contents of EBASEROLES, CUSTOMROLES and CREDENTIALS tables to the application server log

// printRolesAndCredentials(userid);

 

 

2.      LOGON_SERVICE_LOGIC FPL script.  Is used in Ebase V4.5.1 and earlier.

This authenticates a supplied user/password combination against the supplied Ebase security system and adds any defined roles.

 

if [PARAM1_SOURCE = 'JSP']

  // authenticate userid (PARAM1_VALUE) and password (PARAM2_VALUE) against Ebase internal security system

  if [ javamethod('com.ebasetech.ufs.security.authentication.EbaseUserManager.authenticateEbaseUser', PARAM1_VALUE, PARAM2_VALUE) ]

     

      // authentication successful, so..

      // 1. set the user id in the response

      set USERID = PARAM1_VALUE;

   

      // 2. fetch the Ebase security roles from the database and transfer them to the response

      set EBASE_INTERNAL_ROLES-USERID = USERID;

      fetchtable EBASE_INTERNAL_ROLES;

      copytable EBASE_INTERNAL_ROLES to EBASEROLES;

      updatetable EBASEROLES;

  else

// authentication failed: return with error

      set ERRORCODE = '1';

      set ERRORDESCRIPTION = 'Invalid userid/password combination';

  endif

endif

 

Invoking the Logon Service

The Logon Service can be invoked in two ways:

 

1.      Automatically – when a user first connects, using XILogonExit

 

2.      On demand – using SecurityManager.logon()

 

Users can be authenticated at any time by calling the SecurityManager.logon() method – this is only available to API scripting languages such as Javascript. Use of this method makes it possible to mix authenticated and unauthenticated users in the same system, authenticating users at the point where they need to access a protected service.

 

The following example shows a logon function where form fields USER and PASSWORD contain the userid and password, and the parameter source type for both is arbitrarily set to “Script” (which might be checked by the Logon Service).  The function returns true if the logon is successful, and generates and error message and returns false if it fails. When the Logon Service returns an error code or fails to set a userid in the response document, a LogonException is thrown and this exception contains the error code and error description returned by the Logon Service.

 

function logon()

{

  try

  {

    system.securityManager.logon([ ["Script", fields.USER.value], ["Script", fields.PASSWORD.value] ] );

    return true;

  }

  catch (e)

  {

    event.owner.addErrorMessage(e.javaException.message, false);

    event.owner.addErrorMessage("code: " + e.javaException.errorCode + ", description: "  + e.javaException.errorDescription);

    return false;

  }

}