Caché Security Administration Guide
Using Delegated Authentication
[Back] [Next]
   
Server:docs2
Instance:LATEST
User:UnknownUser
 
-
Go to:
Search:    

Caché supports the use of user-defined authentication mechanisms. This is known as delegated authentication. Delegated authentication allows administrators to implement custom mechanisms to replace the authentication and role-management activities that are part of Caché security.

This chapter covers the following topics:
Overview of Delegated Authentication
To use delegated authentication, the steps are:
  1. Create the user-defined authentication code in the ZAUTHENTICATE routine. This can include the use of two-factor authentication. This routine can also perform basic setup for a user account, such as specifying roles and other user properties.
  2. Enable delegated authentication for the Caché instance on the Authentication Options page.
  3. Enable delegated authentication for the relevant services, applications, or both, as required.
  4. Optionally enable two-factor authentication for the Caché instance and, if required, for web applications and client/server applications.
For example, to use delegated authentication for an instance’s Management Portal, the steps are:
  1. Create the user-defined authentication code in ZAUTHENTICATE.
  2. Enable delegated authentication for the Caché instance as a whole.
  3. Enable delegated authentication for the set of /csp/sys* applications.
How Delegated Authentication Works
When a user attempts to log in and Caché invokes delegated authentication, the sequence of events is:
  1. When a service or application uses delegated authentication, a login attempt automatically results in a call to the ZAUTHENTICATE routine. The authentication code in this routine can be any user-defined Caché ObjectScript, class methods, or $ZF callout code.
  2. The next step depends on whether or not authentication succeeds and whether or not this is the first login using ZAUTHENTICATE:
  3. If two-factor authentication is enabled for the instance and the relevant services, then there is a check that the user’s PhoneNumber and PhoneProvider properties have been set. If these properties are set, then two-factor authentication proceeds; if they are not set, two-factor authentication cannot proceed and the user is not authenticated.
  4. A delegated user is listed as such in the Type column of the list of users on the Users page (System Administration > Security > Users). The user’s properties are displayed read-only in the Management Portal and are not editable from within Caché (since all the information comes from outside Caché).
    Note:
    A delegated user cannot also be a Caché password user.
Creating Delegated (User-Defined) Authentication Code
This section describes various aspects of creating your own ZAUTHENTICATE routine:
Authentication Code Fundamentals
A system-supplied template of ZAUTHENTICATE is available in the SAMPLES namespace in the routine ZAUTHENTICATE.mac for instances with Manager Utility Source Code installed. To install Manager Utility Source Code, select that option as part of a Custom install on the Setup Type page of the installation wizard.
To create your own ZAUTHENTICATE.mac:
  1. To use ZAUTHENTICATE.mac as a template, copy its contents and save them into a ZAUTHENTICATE.mac routine in the %SYS namespace.
  2. Review the comments in the system-supplied code for ZAUTHENTICATE. These provide important guidance about how to implement a custom version of the routine.
  3. Edit the routine by adding custom authentication code and any desired code to set user account characteristics.
Caution:
Because Caché places no constraints on the authentication code in ZAUTHENTICATE, the application programmer is responsible for ensuring that this code is sufficiently secure.
Signature
The signature of ZAUTHENTICATE is:
ZAUTHENTICATE(ServiceName, Namespace, Username, Password, Credentials, 
        Properties) PUBLIC {

    // authentication code
    // optional code to specify user account properties and roles
}
where:
When Caché calls ZAUTHENTICATE, it has values for these arguments and supplies them to the routine.
Authentication Code
The content of authentication code is application specific. If authentication succeeds, the routine should return the $$$OK macro; otherwise, it should return an error code. See the section Return Value and Error Messages for more information on return values.
Caution:
Because Caché does not and cannot place any constraints on the authentication code in ZAUTHENTICATE, the application programmer is responsible for ensuring that this code is sufficiently secure.
The GetCredentials Entry Point
ZAUTHENTICATE includes an GetCredentials entry point. This entry point is called whenever delegated authentication is enabled for a service, and is called before the user is prompted for a username and password. Instead of getting a username and password from the user, code in the function (created by the application developer) specifies the username and password. The username and password returned are then authenticated in the normal manner as if the user entered them. A possible use of this mechanism is to provide a username and password within the entry point and then, within authentication code, to $roles for the process.
The username and password returned from this entry point can be obtained by any mechanism that the application developer chooses. They can come from a global, an external DLL or LDAP call, or simply set within the routine. The application developer could even provide code to prompt for the username and password, such as in a terminal connection or with a custom CSP login page.
If the entry point returns an error status, then the error is logged in the audit log, and the user is denied access to the system; the one exception to this is if the error status $SYSTEM.Status.Error($$$GetCredentialsFailed) is returned, in which the normal username/password prompting proceeds.
In the following example of a GetCredentials entry point, the code performs different actions for different services:
Finally, the Error entry point performs clean-up as necessary.
The code is:
GetCredentials(ServiceName,Namespace,Username,Password,Credentials) Public {

  // For console sessions, authenticate as _SYSTEM.
  If ServiceName="%Service_Console" {
    Set Username="_SYSTEM"
    Set Password="SYS"
    Quit $SYSTEM.Status.OK()
  }

  // For the CSP samples application, authenticate as AdminUser.
  If $isobject($get(%request)) { 
    If %request.Application="/csp/samples/" {
      Set Username="AdminUser"
      Set Password="Test"
      Quit $System.Status.OK()
    }
  }

  // For bindings connections, use regular prompting.
  If ServiceName="%Service_Bindings" {
    Quit $SYSTEM.Status.Error($$$GetCredentialsFailed)
  }

  // For all other connections, deny access.
  Quit $SYSTEM.Status.Error($$$AccessDenied)
}
For more details, see the comments for this entry point in ZAUTHENTICATE.mac.
The SendTwoFactorToken Entry Point
ZAUTHENTICATE includes an SendTwoFactorToken entry point. This entry point is for use with two-factor authentication. If it is defined and the Caché instance has two-factor authentication enabled, then you can override the default system setting for the format of the message and token that the instance sends to the user’s mobile phone. This allows for messages that can vary by application even on the same Caché instance.
For more details and an example of how to use this entry point, see this entry point in the sample ZAUTHENTICATE.mac.
Setting Values for Roles and Other User Characteristics
If initial authentication succeeds, ZAUTHENTICATE can establish the roles and other characteristics for the authenticated user. For subsequent logins, ZAUTHENTICATE can update these elements of the user record.
For this to happen, code in ZAUTHENTICATE sets the values of the Properties array. (Properties is passed by reference to ZAUTHENTICATE.) Typically, the source for the values being set is a repository of user information that is available to ZAUTHENTICATE.
User Properties
The elements in the Properties array are:
Each of these elements is described in more detail in one of the following sections.
Note:
The value of each element in the properties array determines the value of its associated property for the user being authenticated. It is not possible to use only a subset of the properties or to manipulate their values after authentication.
Comment
If ZAUTHENTICATE sets the value of Properties("Comment"), then that string becomes the value of the user account’s Comment property in Caché. (This property is described in the section Properties of Users,” in the “Users” chapter.) If no value is passed back to the calling routine, then the value of Comment for the user account is a null string and the relevant field in the Management Portal then holds no content.
FullName
If ZAUTHENTICATE sets the value of Properties("FullName"), then that string becomes the value of the user account’s Full name property in Caché. (This property is described in the section Properties of Users,” in the “Users” chapter.) If no value is passed back to the calling routine, then the value of Full name for the user account is a null string and the relevant field in the Management Portal then holds no content.
NameSpace
If ZAUTHENTICATE sets the value of Properties("Namespace"), then that string becomes the value of the user account’s Startup Namespace property in Caché. (This property is described in the section Properties of Users,” in the “Users” chapter.) If no value is passed back to the calling routine, then the value of Startup Namespace for the user account is a null string and the relevant field in the Management Portal then holds no content.
Once connected to Caché, the value of Startup Namespace (hence, that of Properties("Namespace")) determines the initial namespace for any user authenticated for local access (such as for Console, Terminal, or Telnet). If Startup Namespace has no value (since Properties("Namespace") has no value), then the initial namespace for any user authenticated for local access is determined as follows:
  1. If the USER namespace exists, that is the initial namespace.
  2. If the USER namespace does not exist, the initial namespace is the %SYS namespace.
Note:
If the user does not have the appropriate privileges for the initial namespace, access is denied.
Password
If ZAUTHENTICATE sets the value of Properties("Password"), then that string becomes the value of the user account’s Password property in Caché. (This property is described in the section Properties of Users,” in the “Users” chapter.) If no value is passed back to the calling routine, then the value of Password for the user account is a null string and the relevant field in the Management Portal then holds no content.
Roles
If ZAUTHENTICATE sets the value of Properties("Roles"), then that string specifies the Roles to which a user is assigned; this value is a string containing a comma-delimited list of roles. If no value is passed back to the calling routine, then the value of Roles for the user account is a null string and the relevant field in the Management Portal then holds no content. Information about a user’s roles is available on the Roles tab of a user’s Edit User page.
If any roles returned in Properties("Roles") are not defined, then the user is not assigned to the role.
Hence, the logged-in user is assigned to roles as follows:
Routine
If ZAUTHENTICATE sets the value of Properties("Routine"), then that string becomes the value of the user account’s Startup Tag^Routine property in Caché. (This property is described in the section Properties of Users,” in the “Users” chapter.) If no value is passed back to the calling routine, then the value of Startup Tag^Routine for the user account is a null string and the relevant field in the Management Portal then holds no content.
If Properties("Routine") has a value, then this value specifies the routine to execute automatically following login on a terminal-type service (such as for Console, Terminal, or Telnet). If Properties("Routine") has no value, then login starts the Caché Terminal session in programmer mode.
Username
If the username property is returned by this function, then that username is written to the Caché database. This gives the user a chance to normalize what was entered by the user at the username prompt. Note that the normalized username must only differ by case. If the Username property is not passed back to the calling routine, then the username entered by the user at the username prompt will be used as the username written to the Caché security databases (that is, it is not normalized).
If ZAUTHENTICATE sets the value of Properties("Username"), then that string becomes the value of the user account’s Name property in Caché. (This property is described in the section Properties of Users, in the “Users” chapter.) This provides the application programmer with an opportunity to normalize content provided by the end-user at the login prompt.
If there is no explicit call that passes the value of Properties("Username") back to the calling routine, then there is no normalization and the value entered by the end-user at the prompt serves as the value of the user account’s Name property without any modification.
PhoneNumber and PhoneProvider
These are properties associated with two-factor authentication.
If ZAUTHENTICATE sets the value of Properties("PhoneNumber") and Properties("PhoneProvider"), then these then these are written to the Caché database for the user as the user’s mobile phone number and mobile phone service provider. If these are not passed back to the calling routine, then the phone number and service provider written to the Cache security database are a null string. Hence, to use two-factor authentication with delegated authentication, you must supply both of these.
The User Information Repository
ZAUTHENTICATE can refer to any kind of repository of user information, such as a global or an external file. It is up to the code in the routine to set any external properties in the Properties array so that the authenticated user can be created or updated with this information. For example, while a repository can include information such as roles and namespaces, ZAUTHENTICATE code must make that information available to Caché.
If information in the repository changes, this information is only propagated back into the Caché user information if there is code in ZAUTHENTICATE to perform this action. Also, if there is such code, changes to users’ roles must occur in the repository; if you change a user’s roles during a session, the change does not become effective until the next login, at which point the user’s roles are re-set by ZAUTHENTICATE.
Return Value and Error Messages
The routine returns one of the following values:
ZAUTHENTICATE can return system-defined or application-specific error messages. All these messages use the Error method of the %SYSTEM.Status class. This method is invoked as $SYSTEM.Status.Error and takes one or two arguments, depending on the error condition.
The available system-defined error messages are:
To generate a custom message, use the $SYSTEM.Status.Error() method, passing it the $$$GeneralError macro and specifying any custom text as the second argument. For example:
$SYSTEM.Status.Error($$$GeneralError,"Any text here")
Note that when an error message is returned to the caller, it is logged in the audit database (if LoginFailure event auditing is turned on). However, the only error message the user sees is $SYSTEM.Status.Error($$$AccessDenied). However, the user also sees the message for the $$$PasswordChangeRequired error. Return this error if you want the user to change from the current to a new password.
Setting Up Delegated Authentication
Once you have created a ZAUTHENTICATE routine to perform authentication (and, optionally, authorization tasks), the next step is to enable it for the instance’s relevant services or applications. This procedure is:
  1. Enable delegated authentication for entire instance. On the Authentication/CSP Session Options page (System Administration > Security > System Security > Authentication/CSP Session Options), select Allow Delegated authentication and click Save.
    With delegated authentication enabled for the instance, a Delegated check box appears on the Edit Service page for relevant services and the Edit Web Application page for those applications.
  2. Enable delegated authenticated for services and applications, as appropriate.
The following services support delegated authentication:
These fall into several categories of access modes:
After Delegated Authentication Succeeds
Once the user has authenticated, two important topics are:
The State of the System
Any user who is initially authenticated using delegated authentication is listed in the table of users on the Users page (System Administration > Security > Users) as having a type of “Delegated user”. If a system administrator has explicitly created a user through the Management Portal (or using any other native Caché facility), that user has a type of “Caché password user”. If a user attempts to log in using delegated authentication and is successfully authenticated, Caché determines that this user already exists as a Caché user — not a Delegated user — and so login fails.
Changing Passwords
The ZAUTHENTICATE routine also includes an entry point, ChangePassword, to include code to change a user’s password. The signature of this entry point is:
ChangePassword(Username,NewPassword,OldPassword,Status) Public {}
where