Welcome to the SRP Forum! Please refer to the SRP Forum FAQ post if you have any questions regarding how the forum works.

Windows user authentication and CFG.LOGIN

My question is about best practices in user security.

What I would like is a way in BASIC+ to know - "What user did I log in as" and go from there.

The Story

In the old days, the app startup script would echo %USERNAME% to a file, which I would then read and then do internal lookups, bypassing OI's authentication in favor of my own - my app has its own user system.

But I don't like relying on writing things to files which others might intercept. So now I thought - OK, I'll query the environment variable %USERNAME%. But then I saw that I can overwrite its value (!) in the cmd line, which makes me worry about trusting this avenue.

So I read OI's documentation, where you can create a CFG.LOGIN. record in SYSENV and use it to control how OI and your application authenticate users.

So I went down the CFG.LOGIN.APP rabbit hole. I selected 3 (strict), thought I set my groups properly... and almost locked myself out of my copy of the application. (!!)

The outcome
Now I'm just gun-shy about CFG.LOGIN.APP and setting the fields there. I realize it may be a matter of understanding AD better, but I don't like giving up this much control.

So I still want to pick up who the user is who started the app, in a way that is not easily spoofed by malicious actors. What have others done? (I do have an internal user system, so once I know "this user logged in as Alice", I can go from there.)

Comments

  • The CFG_LOGIN feature works as advertised in our implementations. As you have already acknowledged, this allows OpenInsight to rely upon Active Directory groups to authenticate the user and authorize the user to a specific level of access (i.e., super administrator, administrator, or regular user). It's primary benefit is to support SSO and centralize authentication.

    If your goal is to bypass OI's authentication method then this is certainly one way to handle it. If you are nervous about reliance upon the CFG_LOGIN method and/or Active Directory in general, you can allow the user to login automatically with a generic OI user (which can bypass the default login screen) and then use the GetUserName Windows API function to determine their Windows username.

    Our apps typically bypass the OI authentication method using the generic OI user method but we still require them to login using our own custom authentication screen. Clients have the choice to use our built-in user management system or they can use the LogonUser Windows API function to authenticate with their Windows user.
  • So I decided to follow the pattern used to create the GetEnvironmentVariable routine.

    I went to https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getusernamea

    I studied the way they declare the routines there tried to apply it to the OI help example "Reading the Environment PATH Variable", where it shows how you would add the GetEnvironmentVariable.

    I first made sure I could call the GetEnvironmentVariable call successfully and read any environment variable I wanted.

    I then decided to implement the GetUserName API call following the same pattern.

    So I created a new entry into SYSPROCS:
    * AAF 2/16/2023 BOOL STDCALL GetUserNameA(LPSTR, LPDWORD) As GetUserName, following the definition from the URL above.

    But I realized that there may be some issues with some of the types used (e.g. BOOL) because RUN_FCNS complained about it. So I tried to revert back to something simpler like INT, but then RUN_FCNS didn't like LPDWORD.

    Is the OI facility not compatible with the latest Windows API?
  • I'm not the expert in this area on our team so I can't answer your question. I know that things have vastly improved in OI 10. I couldn't find my original prototype for GetUserName but I noticed that it has the same signature as GetComputerName, which is already defined in DLL_KERNEL32. So I just created this and it works:

    ADVAPI32 LONG STDCALL GetUserNameA(LPCHAR, LPLONG) as SRPWinAPI_GetUserName
  • edited February 2023
    I created GetUserName following this pattern, and it does work. Thanks for the suggestion Don.

    I'll also follow your idea of using a generic user named after my application, passing it into the run string,

    C:\OIPHS\OINSIGHT.exe /ap=PHS /un=PHS

    with

    CFG.LOGIN.PHS<1>=1
    CFG.LOGIN.PHS<2>=PHS

    Then, in order to access the app, you'll have to have an account on the accessing machine which matches the internal users I maintain.

    Are there any pitfalls associated with this approach? I am pushing the security responsibility to an extent to clients having decent security on their accessing machines.
  • I think that looks fine except that CFG.LOGIN.PHS should be CFG_LOGIN*PHS.
  • It is. :-) That was a typo.
    Do fields 3 and 4 matter anymore with this setup?
  • That depends. Do you require anybody to be able to log in as an administrator?
  • edited February 2023
    Yes, possibly. In the production RevG environment, we maintain "normal" users as tabs1, tabs2, ..., and an administrative user, tabsadmin. So I could leverage 3 and 4 for this. We don't have a clear distinction between admin and system admin in our application philosophy, so I might just add the same name of tabsadmin to both. I'll think it over.
  • Sounds like a plan.
Sign In or Register to comment.