VL-Web: Active Directory authentication with ServerModule

This Q&A forum allows users to post and respond to "How Do I Do ....." questions. Please do not use to report (suspected) errors - you must use your regional help desk for this. The information contained in this forum has not been validated by LANSA and, as such, LANSA cannot guarantee the accuracy of the information.
Post Reply
Rieko Saitoh
Posts: 48
Joined: Sat Apr 30, 2016 11:46 am

VL-Web: Active Directory authentication with ServerModule

Post by Rieko Saitoh » Tue Jul 14, 2020 4:32 pm

Hi,

I would like to do Active Directory authentication with ServerModule.
Is it possible to enter UserID/Pass/Domain on the VL-Web screen and perform Active Directory authentication with ServerModule?
If it is possible, could you tell me how to do it?

In the past, VBS was executed from Visual LANSA Form with System Command for authentication.
I tried using it this time, but no response was returned from the ServerModule.

How to execute in Visual LANSA form:
#Basepath :='C:\00.VBS\PJ\ChkACCOUNT.vbs'
#Fullpath := #Basepath +'' + #UserID +'' + #Pass +'' + #Domain
Use Builtin(SYSTEM_COMMAND) With_Args('S' #Fullpath) To_Get(#CmdResult)

Thank you.

Best regards,
Reiko Saitoh
LANSA japan

jyoung
Posts: 690
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: VL-Web: Active Directory authentication with ServerModule

Post by jyoung » Tue Jul 14, 2020 11:20 pm

I don't know if you can do it directly from a Server Module, but you can using Integrator. Its how we do it at least.

Look into the OpenLDAPService. https://docs.lansa.com/14/en/lansa093/i ... 7_3640.htm

We wrap this type of stuff up in a LDAP Process with LDAP Functions which makes them really easy to call from a Server Module.

This is our Auth function, the *LDAPCONNECTION and *LDAPCONNECTPWD are System Variables that contain the appropriate info.
In our case, when a user is authenticated, we also return certain attributes and membership.

Code: Select all

* ================================================================================
* Description : Connects to Active Directory to authenticate a user by SAMACCOUNTNAME
* Written By  : JRYOUNG
* Exchange    : INPUT - wk_Username wk_Password
*             : OUTPUT - wk_Status
* Notes       : Attributes are returned in the AttributesList
*             : Errors are returned in the MessagesList
*             : wk_Status will be OK if all commands succeed, otherwase it will be ER
* Usage       : The calling program should pass the MessagesList and AttributesList
*             :     See the below definitions of the list for their structure
* ================================================================================

function options(*DIRECT) rcv_list(#MessagesList #AttributeList #MembershipList)

* ================================================================================
* INPUT/OUTPUT Fields
* ================================================================================
group_by name(#InputFields) fields(#wk_Username #wk_Password)
group_by name(#OutputFields) fields(#wk_Status)

* ================================================================================
* INPUT/OUTPUT Lists
* ================================================================================
def_list name(#MessagesList) fields(#STD_STRNG) type(*WORKING) entrys(*MAX)
def_list name(#AttributeList) fields(#STD_TEXTL #STD_STRNG) type(*WORKING) entrys(*MAX)
def_list name(#MembershipList) fields(#STD_TEXTL #STD_STRNG) type(*WORKING) entrys(*MAX)

* ================================================================================
* Components
* ================================================================================
define_com class(#ServerTraceHandler) scope(*APPLICATION)

* ================================================================================
* Working Fields
* ================================================================================
define field(#LDAPServer) type(*STRING)
define field(#DN) type(*STRING) length(512)

* ================================================================================
* Working Lists
* ================================================================================
def_list name(#WorkingList) fields(#DN) counter(#LISTCOUNT) type(*WORKING) entrys(*MAX)

* ================================================================================
* Default Values
* ================================================================================
#LDAPServer := "*****************"

* ================================================================================
* Main
* ================================================================================

exchange fields(#wk_Status) option(*ALWAYS)

#wk_Status := ER

if (#COM_OWNER.Connect <> OK)
return
endif

if (#COM_OWNER.Search <> OK)
#COM_OWNER.Disconnect
return
endif

if (#COM_OWNER.Authenticate <> OK)
#COM_OWNER.Disconnect
return
endif

if (#COM_OWNER.LoadAttributes <> OK)
#COM_OWNER.Disconnect
return
endif

if (#COM_OWNER.LoadMembership <> OK)
#COM_OWNER.Disconnect
return
endif

#COM_OWNER.Disconnect

#wk_Status := OK

* ================================================================================
* Routines
* ================================================================================

mthroutine name(Connect)
define_map for(*RESULT) class(#wk_Status) name(#status)

#status := ER

* connect this JSMX client to the Java Services Manager, and to start a thread for the service.
use builtin(JSMX_OPEN) to_get(#JSMXSTS #JSMXMSG #JSMXHDLE)
if (#COM_OWNER.check( #JSMXSTS #JSMXMSG ) = False)
return
endif

* load and initialize the service using the values defined in the OpenLDAPService.properties file.
#JSMXCMD := 'SERVICE_LOAD SERVICE (OpenLDAPService) TRACE(*NO)'
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

* establish a connection to the LDAP server.
#JSMXCMD := ('BIND HOST(&1) DN(&2) PASSWORD(&3)').Substitute( #LDAPServer *LDAPCONNECTDN *LDAPCONNECTPWD )
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

#status := OK
endroutine

mthroutine name(Search)
define_map for(*RESULT) class(#wk_Status) name(#status)

#status := ER

* search the ldap entries for a user based on the samaccountname (username). This will return a distingished name (DN) in the list if found
#JSMXCMD := ("SEARCH DN(DC=************************,DC=com) FILTER(samaccountname=&1) SCOPE(*SUB) SERVICE_LIST(DN)").Substitute( #wk_Username )
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG #workingList)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

if ((#JSMXSTS = OK) *And (#LISTCOUNT = 1))
get_entry number(1) from_list(#workingList)

if (#DN = *BLANKS)
* we found an entry but did not get the distinguished name
#STD_STRNG := ("Could not retrieve the DN for &1").Substitute( #wk_Username )
add_entry to_list(#MessagesList)
return
endif
else
* we did not get one and only one entry in the list, therefore something went wrong
#STD_STRNG := "Invalid Credentials"
add_entry to_list(#MessagesList)
return
endif

#status := OK
endroutine

mthroutine name(Authenticate)
define_map for(*RESULT) class(#wk_Status) name(#status)

#status := ER

#JSMXCMD := ('BIND HOST(&1) DN(&2) PASSWORD("&3")').Substitute( #LDAPServer #DN #wk_Password )
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

#status := OK
endroutine

mthroutine name(LoadAttributes)
define_map for(*RESULT) class(#wk_Status) name(#status)

#status := ER

* get the attributes for the DN
#JSMXCMD := ('GET DN(&1) ATTRIBUTES(DISTINGUISHEDNAME, CN, GIVENNAME, DISPLAYNAME) SERVICE_LIST(STD_TEXTL STD_STRNG)').Substitute( #DN )
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG #AttributeList)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

#status := OK
endroutine

mthroutine name(LoadMembership)
define_map for(*RESULT) class(#wk_Status) name(#status)

#status := ER

* get the attributes for the DN
#JSMXCMD := ('GET DN(&1) ATTRIBUTES(MEMBEROF) SERVICE_LIST(STD_TEXTL STD_STRNG)').Substitute( #DN )
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG #MembershipList)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

#status := OK

endroutine

mthroutine name(Disconnect)
define_map for(*RESULT) class(#wk_Status) name(#status)

#status := ER

* disconnect from the LDAP Server when we have completed.
#JSMXCMD := 'UNBIND'
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

* unload the service and to remove the temporary directory.
#JSMXCMD := 'SERVICE_UNLOAD'
use builtin(JSMX_COMMAND) with_args(#JSMXHDLE #JSMXCMD) to_get(#JSMXSTS #JSMXMSG)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

* finally close the service.
use builtin(JSMX_CLOSE) with_args(#JSMXHDLE) to_get(#JSMXSTS #JSMXMSG)
if (#COM_OWNER.Check( #JSMXSTS #JSMXMSG ) = False)
return
endif

#status := OK
endroutine

mthroutine name(Check)
define_map for(*INPUT) class(#JSMXSTS) name(#status)
define_map for(*INPUT) class(#JSMXMSG) name(#message)
define_map for(*RESULT) class(#PRIM_BOLN) name(#isOk)

#isOk := False

if (#status <> OK)
#STD_STRNG := #message
add_entry to_list(#MessagesList)
return
endif

#isOk := True
endroutine


Then in a Server Module, we call the function, exchanging the username, password and working lists

Code: Select all

* authenticate the user
exchange fields(#wk_Username #wk_Password)
call process(*DIRECT) function(LDAPN01) pass_lst(#MessageList #AttributeList #MembershipList)
Personally, Integrator is a bit of brain shock, while this works for us, if there is a way to query AD without going through Integrator, I would probably go that way. When I had to write this, there was no other way. :D

Hope this helps,
Joe

Rieko Saitoh
Posts: 48
Joined: Sat Apr 30, 2016 11:46 am

Re: VL-Web: Active Directory authentication with ServerModule

Post by Rieko Saitoh » Mon Jul 20, 2020 4:09 pm

Hi Joe,

Thank you for your reply.
I could understand that there is a way to use LANSA Integrator. I will consider based on the samples I received from you.
Thank you for your polite and kind answers. Thank you very much for your help!!

Best regards,
Rieko Saitoh
LANSA japan

Post Reply