Caché Security Administration Guide
Using Delegated Authorization
[Home] [Back] [Next]
InterSystems: The power behind what matters   
Class Reference   
Search:    

Caché supports the use of user-defined authorization code. This is known as delegated authorization. Topics in this chapter include:

Overview of Delegated Authorization
Delegated authorization allows administrators to implement custom mechanisms to replace the role-assignment activities that are part of Caché security. For example, user-defined authorization code might look up a user’s roles in an external database and provide that information to Caché.
To use delegated authorization, there are the following steps:
Note:
Delegated authorization is only supported with Kerberos and Operating-System–based authentication.
Interactions between Delegated Authentication and Delegated Authorization
Delegated authorization through ZAUTHORIZE.mac is not supported for use with delegated authentication. The routine for delegated authentication (ZAUTHENTICATE, which is described in the chapter Using Delegated Authentication) provides support for authorization. When using ZAUTHENTICATE, you have the option to segregate authentication and authorization code.
Creating Delegated (User-defined) Authorization Code
Topics associated with creating delegated authorization code include:
Working from the ZAUTHORIZE.mac Template
A system-supplied copy of the ZAUTHORIZE routine is available in the SAMPLES namespace in the routine ZAUTHORIZE.mac for instances with the manager utility source code installed. To install the manager utility source code, select an installation type of Development, Server, or a Custom installation that includes the Caché Database Engine.
To create your own ZAUTHORIZE.mac:
  1. To use ZAUTHORIZE.mac as a template, copy its contents and save them into a ZAUTHORIZE.mac routine in the %SYS namespace.
  2. Review the comments in the system-supplied code for ZAUTHORIZE. These provide important guidance about how to implement a custom version of the routine.
  3. Edit the routine by adding custom authorization code and any desired code to set user account characteristics.
Caution:
Because Caché places no constraints on the authorization code in ZAUTHORIZE, the application programmer is responsible for ensuring that this code is sufficiently secure.
Upgrading Delegated Authorization Code
Before upgrading to a new version of Caché, check ZAUTHORIZE.mac to determine if your current authorization code needs any changes to support new functionality.
ZAUTHORIZE Signature
When configured for delegated authorization, the system automatically calls ZAUTHORIZE after authentication occurs. Caché supplies values for the parameters defined in the ZAUTHORIZE signature as necessary. The signature of ZAUTHORIZE is:
ZAUTHORIZE(ServiceName, Namespace, Username, Password, 
        Credentials, Properties) PUBLIC {

  // authorization code
  // optional code to specify user account properties and roles
}
where:
Authorization Code with ZAUTHORIZE
The purpose of ZAUTHORIZE is to establish or update the roles and other characteristics for the authenticated user. The content of authorization code is application-specific. It can include any user-written ObjectScript code, class method, or $ZF callout.
ZAUTHORIZE specifies role information by setting the values of the Properties array, which is passed by reference to ZAUTHORIZE. Typically, the source for the values being set is a repository of user information that is available to ZAUTHORIZE.
Caution:
Because Caché does not and cannot place any constraints on the authorization code in ZAUTHORIZE, the application programmer is responsible for ensuring that this code is sufficiently secure.
ZAUTHORIZE and User Properties
Elements of the Properties array specify values of attributes associated with the user specified by the Username parameter. Typically, code within ZAUTHORIZE sets values for these elements. The elements in the Properties array are:
Each of these elements is described in more detail in one of the following sections.
Note:
It is not possible to manipulate the value of any member of the Properties array after authorization.
Comment
If ZAUTHORIZE returns a value for 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 holds no content.
FullName
If ZAUTHORIZE returns a value for 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 holds no content.
NameSpace
If ZAUTHORIZE 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 holds no content.
Once connected to Caché, the value of Startup Namespace — as specified by the value 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, 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 ZAUTHORIZE 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.
If ZAUTHORIZE returns a password, this allows the user to log into the system via Password authentication if it is enabled. This is a possible mechanism to help migrate from delegated authentication to Password authentication, though with the usual cautions associated with the use of multiple authentication mechanisms; see Cascading Authentication in the Authentication chapter for more details.
Roles
If ZAUTHORIZE 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 there are no roles associated with the user account and the Management Portal indicates this. Information about a user’s roles is available on the Roles tab of a user’s Edit User page and a user’s profile.
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 ZAUTHORIZE 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 Console, Terminal, or Telnet). If Properties("Routine") has no value or a value of "", then login starts the Terminal session in programmer mode, subject to whether they have the privilege to access programmer mode or not.
Username
If ZAUTHORIZE 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 (while ensuring that the normalized username only differ by case).
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.
The User Information Repository
ZAUTHORIZE 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, ZAUTHORIZE 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 ZAUTHORIZE 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 reset by ZAUTHORIZE.
ZAUTHORIZE Return Value and Error Messages
The routine returns one of the following values:
ZAUTHORIZE 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 use these error codes, uncomment the #Include %occErrors statement that appears in ZAUTHORIZE.mac.
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.
Configuring an Instance to Use Delegated Authorization
Once you have created a customized ZAUTHORIZE routine, the next step is to enable it for the instance’s relevant services or applications. This procedure is:
  1. Run the ^SECURITY routine from the %SYS namespace in a Terminal or Console window.
  2. In ^SECURITY, choose System parameter setup; under that, choose Edit authentication options; and under that, choose either Allow Kerberos authentication or Allow Operating System authentication. (Delegated authorization is only supported for these two authentication mechanisms.).
Selecting either of these choices causes Caché to invoke the ZAUTHORIZE.mac routine, if one exists, in the %SYS namespace.
Important:
Caché only calls ZAUTHORIZE after user authentication.
Delegated Authorization and User Types
When a user first logs in to Caché with an authentication mechanism that uses delegated authorization, the system creates a user account either of Type OS (for Operating System) or Kerberos. (Note that this value does not appear in the Type column of the table of users on the Users page (System Administration > Security > Users).) At the time of account creation and, for subsequent logins, the ZAUTHORIZE routine specifies the roles for the user.
Any attempt to log in without using delegated authorization will result in a login failure. This is because only delegated authorization specifies the user Type as OS or Kerberos. When using these authentication mechanisms without delegated authorization, the user is authenticated as being of Type "Caché Password User"; the login fails because a user can only have one type and a user of one type cannot log in using mechanisms associated with another type. (Delegated authentication and LDAP authentication also both fail for the same reason.)
For general information about user types, see the section About User Types in the “Users” chapter.
After Authorization — The State of the System
If the user is successfully authorized, the Cache security database is updated in one of the following ways:
  1. If this is the first time the user has logged in, a user record is created in the security database for the entered username, using properties returned by ZAUTHORIZE.
  2. If the user has logged in before, the user record is updated in the security database, using properties returned by this function.
Whether for a first-time user or not, the process that logs in has the value of the $ROLES system variable set to the value of Properties("Roles"). For a terminal login, the namespace is set to the value of Properties("NameSpace") and the startup routine is set to the value of Properties("Routine").