Creating a Lua authentication module

This scenario illustrates how to create a Lua HTTP transformation rule that can be used to authenticate a user and then generate an EAI response.

About this task

Script
-- IBM Confidential 
-- PID 5725-V89 5725-V90 5737-F02
-- 
-- Copyright IBM Corp. 2022, 2022

-- This script is used to test a Lua script which is acting as an EAI to
-- authenticate a user.
--
-- In order to use this script:
--   * The transformation rule must be enabled as a postazn rule
--   * EAI authentication must be enabled
--   * The EAI trigger URL must be set to the transformation rule
--     resource
--   * Unauthenticated access must be allowed for the transformation
--     rule resource
--   * The login.html file (or other form) must be set to POST the
--     authentication data to the transformation rule resource.
--   * Create the 38b9a4b2.html error file so that authentication errors
--     can be displayed to the user.

local lualdap   = require "lualdap"
local urlencode = require "urlencode"

-- Connect to the LDAP server.  The script is currently connecting to
-- the embedded user registry but can be changed to connect to an
-- external user registry.
local ld, err = lualdap.initialize("ldaps://127.0.0.1:636")

if (ld == nil) then
    Control.returnErrorPage(err)
    return
end

-- Retrieve the username and password fields from the request body.
local body = HTTPRequest.getBody()
if (body == nil) then
    Control.returnErrorPage("No POST data was found!")
    ld:close()
    return
end

local username = nil
local password = nil

for k, v in string.gmatch(body, "(%w+)=(%w+)") do
    if (k == "username") then
        username = urlencode.decode_url(v)
    elseif (k == "password") then
        password = urlencode.decode_url(v)
    end
end

if (username == nil or password == nil) then
    Control.returnErrorPage("The required form fields were not found!")
    ld:close()
    return
end

-- Construct our expected user DN.
local userDn = string.format("cn=%s,dc=iswga", username)

-- Authenticate to the LDAP server.
local rc, err = ld:bind_simple(userDn, password)

if (rc == nil) then
    Control.returnErrorPage(err)
    ld:close()
    return
end

-- Add the full user DN as an attribute.
Authentication.setAttribute("my_user_dn", userDn)

-- Grab any additional user attributes which should be stored in the
-- authenticated credential.  In this instance we are storing the 'sn'
-- attribute.
for dn, attribs in ld:search { base=userDn, scope="base", attrs="sn" } do
    for name, values in pairs (attribs) do
        if type(values) == "string" then
            local hdrname = "my_"..name
            Authentication.setAttribute(hdrname, values)
        end
    end
end

ld:close()

-- Set the authentication response data.
Authentication.setUserIdentity(username, false) 
Authentication.setAuthLevel(1) 

Procedure

  1. Import and enable the transformation rule by adding the following configuration to the WebSEAL configuration file:
    [http-transformations]
    pkmslogin.lua = eai.lua
    
    [http-transformations:pkmslogin.lua]
    request-match = postazn:POST /pkmslogin.lua *
    
  2. Enable EAI authentication and set up a trigger URL for the transformation resource by adding the following configuration to the WebSEAL configuration file:
    [eai]
    eai-auth = https
    
    [eai-trigger-urls]
    trigger = /pkmslogin.lua
    
  3. Disable validation of the OpenLDAP server certificate.
    [system-environment-variables]
    LDAPTLS_REQCERT = never
    
    Note: This step is not recommended in a production environment. Instead, the CA certificate for the LDAP server can be added to the webseal-cert-keyfile key file, and the lua-ldap-ca-cert-label configuration entry be set to indicate the label of the CA certificate.
  4. Attach an ACL that allows unauthenticated read access to the HTTP transformation resource: /WebSEAL/<server-name>/pkmslogin.lua.
  5. Modify the login.html file (or provide an externally hosted authentication form) and set the form URL to /pkmslogin.lua.
  6. Create the 38b9a4b2.html error file so that a custom error page can be returned to the client when an authentication error occurs.