Try OpenEdge Now
skip to main content
Programming Interfaces
Data Management : Application Security : Authenticating and managing user identity in ABL : Establishing and managing identity for multi-tier applications : Managing user identities for a state-free application service
 
Managing user identities for a state-free application service
In a state-free application service, the process of managing user identities is somewhat more complicated by the lack of any client connections. This requires the application service to manage user identities independently of any physical client identity and to provide a means to exchange the client's identity with the application service on every client request. Note that for a state-free AppServer, there are no configurable activation and deactivation procedures. So, all the work of establishing and clearing user identities for a given client request must be done for each and every service call by the application service itself. However, this process is simplified using the client context ID mechanism that is available for both state-free and stateless application services. Following is a typical procedure for managing state-free user identities authenticated using application-performed user authentication together with this client context ID mechanism.
To manage users identities for a state-free application service:
1. In the AppServer's configured startup procedure, build any required session domain registry and remove any client-principal objects from a previous user context left-over from any abnormal session termination.
2. In the application service's login procedure:
a. Initialize and seal the client-principal object, including setting a unique value for the SESSION-ID attribute from the ClientContextId property on the Progress.Lang.OERequestInfo object available through the SESSION:CURRENT-REQUEST-INFO attribute.
b. Export the client-principal object.
c. Store the exported RAW value of the client-principal object in a context database keyed on the SESSION-ID attribute value.
d. Return the SESSION-ID attribute value (client context ID) as an output parameter to the client. The client will then call all non-login procedures of the application service by assigning this client context ID to the ClientContextID property on the Progress.Lang.OERequstInfo object that is available through the REQUEST-INFO attribute on the server object handle for the application service.
For example:
DEFINE OUTPUT PARAMETER cSessionID AS CHARACTER NO-UNDO.

DEFINE SHARED VARIABLE hCP AS HANDLE NO-UNDO.

DEFINE VARIABLE cAccessCode AS CHARACTER NO-UNDO.
DEFINE VARIABLE rCP         AS RAW       NO-UNDO.

CREATE CLIENT-PRINCIPAL hCP.

/* Initialize, authenticate, seal, and login client-principal object */
...
hCP:SESSION-ID = SESSION:CURRENT-REQUEST-INFO:ClientContextId.
hCP:SEAL(cAccessCode).

/* Export client-princpal object */
rCP = hCP:EXPORT-PRINCIPAL().

/* Store exported client-principal */
CREATE UserContext NO-ERROR.
ASSIGN UserContext.Principal-key = hCP:SESSION-ID
       UserContext.Principal     = rCP NO-ERROR.

/* Return the client context ID value to client */
cSessionID = hCP:SESSION-ID.
...
3. In all non-login procedures for the application service:
a. Retrieve the client context ID from the ClientContextID property on the Progress.Lang.OERequstInfo object that is available through the SESSION:CURRENT-REQUEST-INFO attribute.
b. Lookup the exported client-principal object in the context database using the security token value as the lookup key.
c. Import the client principal object.
d. Validate the imported client-principal seal, and use the validated client principal object to set the user identity.
e. Perform the application service task.
f. Clear the ABL session identity for the next user.
For example:
DEFINE        VARIABLE cSessionID AS CHARACTER NO-UNDO.
DEFINE        VARIABLE rCP AS RAW    NO-UNDO.
DEFINE SHARED VARIABLE hCP AS HANDLE NO-UNDO.

cSessionID = SESSION:CURRENT-REQUEST-INFO:ClientContextId.

CREATE CLIENT-PRINCIPAL hCP.

/* Lookup client-principal object in context database */
FIND UserContext WHERE Principal-key = cSessionID NO-ERROR.
rCP = UserContext.Principal.

/* Import client-princpal object, validate, and set user identity */
hCP:IMPORT-PRINCIPAL(rCP).
IF SECURITY-POLICY:SET-CLIENT(hCP) THEN /* Identity is valid */
  ... /* Perform application service task */

ELSE /* Identity is not valid */
  ...

/* Clear user identity for next user */
hCP:LOGOUT().
DELETE OBJECT hCP.
...
4. In the application service's logout procedure:
a. Retrieve the client context ID from the ClientContextID property on the Progress.Lang.OERequstInfo object that is available through the SESSION:CURRENT-REQUEST-INFO attribute.
b. Lookup the exported client-principal object in the context database using the security token value as the lookup key.
c. Remove the exported client-principal object from the context database.
For example:
DEFINE VARIABLE cSessionID AS CHARACTER NO-UNDO.

cSessionID = SESSION:CURRENT-REQUEST-INFO:ClientContextId.

/* Lookup client-principal object and remove from context database */
FIND UserContext
  WHERE Principal-key = cSessionID NO-ERROR.
DELETE UserContext NO-ERROR.
...
5. In the AppServer's configured shutdown procedure, empty the user context database. For example:
/* Empty the context database */
FOR EACH UserContext:
  DELETE UserContext NO-ERROR.
END.
...