Try OpenEdge Now
skip to main content
Programming Interfaces
Data Management : Application Security : Authenticating and managing user identity in ABL : Establishing database connection identity : Built-in client support for authenticating database connection identity
 
Built-in client support for authenticating database connection identity
OpenEdge provides built-in support for client authentication of OpenEdge database connections. If the security administrator has defined authentication-enabled domains in an OpenEdge database, your application can prompt for a user ID and password at the appropriate point to establish a database connection identity by running the standard OpenEdge startup pro2cedure, _prostar.p. This procedure, in turn, runs the standard ABL authentication procedure, _login.p, for each connected database. Your application can also reset a current connection identity, as your application requires.
The _prostar.p procedure also prepares _login.p to run appropriately in the current application environment (character or graphical) and verifies that no connected databases have the logical name DICTDB. This allows _prostar.p to assign the same alias (DICTDB) to each connected database before calling _login.p. Then, _login.p can authenticate access as it is called for each different database using the same database name.
This is the _login.p procedure.
_login.p
DEFINE INPUT PARAMETER viewAsDialog AS LOGICAL NO-UNDO.

{ login.i }
DEFINE VARIABLE tries     AS INTEGER NO-UNDO.
DEFINE VARIABLE lFound    AS LOGICAL NO-UNDO.
DEFINE VARIABLE hCP       AS HANDLE  NO-UNDO.
DEFINE VARIABLE setdbclnt AS LOGICAL NO-UNDO.
DEFINE VARIABLE cUserid AS LOGICAL NO-UNDO.

IF USERID("DICTDB") <> ""  THEN
    RETURN.

IF INTEGER(DBVERSION("DICTDB")) > 10 THEN DO:
    FIND FIRST  dictdb._sec-authentication-domain
            WHERE (dictdb._sec-authentication-domain._Domain-enabled = YES
              AND  dictdb._sec-authentication-domain._Domain-id > -1 AND
                   dictdb._sec-authentication-domain._Domain-type = "_oeusertable") NO-ERROR.
       IF AVAILABLE(dictdb._sec-authentication-domain) THEN
          lFound = BUFFER dictdb._user:FIND-FIRST("WHERE dictdb._User._sql-only-user = FALSE") NO-ERROR.
    
       IF NOT lFound THEN
       DO:
          FOR EACH dictdb._sec-authentication-domain
             WHERE (dictdb._sec-authentication-domain._Domain-enabled = YES
               AND  dictdb._sec-authentication-domain._Domain-type <> "_oeusertable"
               AND  dictdb._sec-authentication-domain._Domain-id > -1 ) ,
             FIRST dictdb._sec-authentication-system OF dictdb._sec-authentication-domain
                 WHERE (dictdb._sec-authentication-system._PAM-plug-in = YES ) :
                 lFound = YES.
                 LEAVE.
          END.
       END.
    
    IF lFound = FALSE THEN RETURN.
END.
ELSE IF NOT CAN-FIND(FIRST DICTDB._User) THEN
    RETURN.

CREATE CLIENT-PRINCIPAL hCP. /* create a CLIENT-PRINCIPAL only once during login*/

DO ON ENDKEY UNDO, LEAVE:

    currentdb = LDBNAME("DICTDB").

    /* reset id and password to blank in case of retry */
    ASSIGN id = ""
           domain = ""
           password = "".
    if viewAsDialog then

    do:

      DISPLAY currentdb WITH FRAME logindb_frame view-as dialog-box.

      UPDATE id password domain ok_btn cancel_btn help_btn {&WHEN_HELP}
             WITH FRAME logindb_frame view-as dialog-box.
    end.
    else do:
      DISPLAY currentdb WITH FRAME login_frame.

      UPDATE id password domain ok_btn cancel_btn help_btn {&WHEN_HELP}
             WITH FRAME login_frame.
    end.
    cUserid = id
            + if domain = "" then "" else "@" + domain.
    
    /* Use SET-DB-CLIENT instead of SETUSERID */
    hCP:INITIALIZE(cUserid,?,?,password).
    
    setdbclnt = SET-DB-CLIENT(hCP,currentdb) NO-ERROR.
    if NOT setdbclnt THEN
    DO:
        MESSAGE "Userid/Password is incorrect."
                VIEW-AS ALERT-BOX ERROR BUTTONS OK.
        IF tries > 1 THEN
            QUIT. /* only allow 3 tries*/
        tries = tries + 1.
        UNDO, RETRY.
    END.    
END.

DELETE OBJECT hCP.
hCP = ?.

HIDE FRAME login_frame.
The _login.p procedure initializes a client-principal object by passing the fully qualified user ID and password that the user enters to the INITIALIZE( ) method and uses the ABL SET-DB-CLIENT function to authenticate the user's identity that is passed in the client-principal object. The user has three tries to enter the correct user ID and password for each database. If the user fails to do so after three tries, OpenEdge exits the user from the application. If the user ID and password combination is valid for the database, SET-DB-CLIENT establishes that user ID as the database connection ID and deletes the client-principal.
Note: Following execution of _login.p, to set the ABL session identity using the same identity as a database connection, the application can invoke the GET-DB-CLIENT function on that connection to return a copy of the client-principal. For more information on setting the ABL session identity, see EstablishingABL session identity.
The input parameter for _login.p allows it to display the authentication prompts either in a dialog box (viewAsDialog = TRUE) or in the frame of a separate window (viewAsDialog = FALSE). The _prostar.p procedure uses a separate window in graphical environments and the default window in character environments, so it always passes FALSE as an argument to _login.p.
As explained previously, the _login.p procedure only works for a database with the DICTDB alias. (By default, this alias is assigned to the first database you connect to during a session.) If you want to avoid this restriction, you can create your own procedures, based on _prostar.p and _login.p, that pass an argument with the database name.
If your application uses server authentication, you might also create your own client login procedure, for example, that replace the call to SET-DB-CLIENT in _login.p with a call to a remote login procedure on the authentication server. Typically, this remote login procedure invokes the SECURITY-POLICY:SET-CLIENT( ) method to authenticate the user identity and returns a sealed client-principal to the client, which then calls SET-CLIENT( ) to set the client session identity and possibly the connection identity for all connected application databases.
If the application does not run _prostar.p at connection time, or if the user bypasses _login.p (by pressing ENDERROR when prompted for the user ID and password), the user is assigned an OpenEdge default user ID. For more information on the OpenEdge default user identity, see Authenticating and managing user identity in ABL.
If you connect to a database dynamically using the CONNECT statement, you can use the User ID (–U) and Password (–P) connection parameters in the CONNECT statement, or you can use the SET-DB-CLIENT (or SETUSERID) function to reset the connection user identity after the connection is already established.
Note: While the OpenEdge default user identity can connect to a database (unless database options are set to prevent it), it cannot be used to reset an existing database connection identity.
The following i-passts.p procedure connects to the mywork database that has a list of valid users. The user initially connects to the database using the CONNECT statement with the OpenEdge default user identity. The code then enters a loop that forces the user to provide a valid user ID and password for the database user list.
i-passts.p
DEFINE VARIABLE passwd  AS CHARACTER NO-UNDO FORMAT "x(16) LABEL "Password".
DEFINE VARIABLE success AS LOGICAL   NO-UNDO.
DEFINE VARIABLE user-id AS CHARACTER NO-UNDO FORMAT "x(32)" LABEL "User ID".
DEFINE VARIABLE hCP     AS HANDLE    NO-UNDO.

CONNECT mywork.

DO WHILE NOT success:
  MESSAGE "Enter a user ID and password for the database mywork.".
  SET user-id passwd BLANK.

  CREATE CLIENT-PRINCIPAL hCP.
  hCP:INITIALIZE(user-id,?,?,passwd).

  IF SET-DB-CLIENT(hCP, "mywork") THEN
    success = TRUE.
  ELSE DO:
    BELL.
    MESSAGE "Invalid user ID and password; please try again.".
  END.
END.