0

I'm creating a class that will allow an authentication window to appear and the User types a Domain\Username & Password to authenticate against the Active Directory. I have the working code below, but now I want to authenticate against a specific AD Group that the user is in. I'm unclear on the best way to implement this code, and I'm having a tough time with this. is LOGONUSER able to authenticate against an AD Security Group? Any help would be appreciated.

i.e If the user Admin is in the group "AD_CanAccessApp". That user would be able to access after typing in the Domain/Username and Password and authenticating against the AD.

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Win.ScktComp;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function getDomain: string;
var
  vlDomainName : array[0..MAXCHAR] of char;
  vlSize : ^DWORD;
begin
  New(vlSize);
  vlSize^ := MAXCHAR;
  ExpandEnvironmentStrings(PChar('%USERDOMAIN%'), vlDomainName, vlSize^);
  Dispose(vlSize);
  Result := vlDomainName;
end;

function IsAdmin: Boolean;
const
  SECURITY_NT_AUTHORITY: TSIDIdentifierAuthority =
    (Value: (0, 0, 0, 0, 0, 5));
  SECURITY_BUILTIN_DOMAIN_RID = $00000020;
  DOMAIN_ALIAS_RID_ADMINS     = $00000220;
var
  hAccessToken: THandle;
  ptgGroups: PTokenGroups;
  {$IFDEF FPC}dwInfoBufferSize: PDWORD;{$ELSE}dwInfoBufferSize: DWORD;{$ENDIF}
  psidAdministrators: PSID;
  x: Integer;
  bSuccess: BOOL;
begin
  if Win32Platform <> VER_PLATFORM_WIN32_NT then
  begin
    Result := True;
    exit;
  end;

  Result := False;
  bSuccess := OpenThreadToken(GetCurrentThread, TOKEN_QUERY, True,
    hAccessToken);
  if not bSuccess then
  begin
    if GetLastError = ERROR_NO_TOKEN then
    bSuccess := OpenProcessToken(GetCurrentProcess, TOKEN_QUERY,
      hAccessToken);
  end;
  if bSuccess then
  begin
    GetMem(ptgGroups, 1024);
    bSuccess := GetTokenInformation(hAccessToken, TokenGroups,
      ptgGroups, 1024, dwInfoBufferSize);
    CloseHandle(hAccessToken);
    if bSuccess then
    begin
      AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2,
        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0, psidAdministrators);
      {$R-}
      for x := 0 to ptgGroups.GroupCount - 1 do
        if EqualSid(psidAdministrators, ptgGroups.Groups[x].Sid) then

        begin
          Result := True;
          break;
        end;
      {$R+}
      FreeSid(psidAdministrators);
    end;
    FreeMem(ptgGroups);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
    const
  DNLEN = 255;
var
  sid               : PSID;
  sidSize           : DWORD;
  sidNameUse        : DWORD;
  domainNameSize    : DWORD;
  domainName        : array[0..DNLEN] of char;
  x : string;
 hToken : THandle;
begin
    sidSize := 65536;
    GetMem(sid, sidSize);
    domainNameSize := DNLEN + 1;
    sidNameUse := SidTypeUser;
    try
       if LookupAccountName(nil, PChar(Edit1.Text), sid, sidSize,
          domainName, domainNameSize, sidNameUse) then
           x:=StrPas(domainName);
    finally
    FreeMem(sid);
    end;

    //showmessage(x);

if edit3.Text = x then
  begin
  if (LogonUser(pChar(edit1.Text), pChar(edit3.Text), pChar(edit2.Text), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken)) then
    begin
    CloseHandle(hToken);
    showmessage('logon successful');

    end
    else
    showmessage('Failed logon! Username or password incorrect!');
  end
  else showmessage('Failed logon! Domain name incorrect!');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
if IsAdmin then showmessage('it''s an administrator')
   else showmessage('it''s a simple user');
end;

end.

Thank you

john

  • I see you have posted a comment [here](https://stackoverflow.com/a/339123/12763954). Did you try the code? – Olivier May 29 '20 at 19:13
  • Copy/paste the code from the link that you commented on (as mentioned by @Olivier) into a test project, run it, and see what happens when you ask for a group to which you belong and one you do not, and see if it works for you. – Ken White May 29 '20 at 22:28
  • Hi @Olivier, I'm very new to RAD studio and Delphi in general. I would definitely be willing to run the code to figure out the output, but I'm unsure on how to do this testing with the above code. I've been playing around in RAD 10.2 and I'm not sure how to get the output from the Unit. Would I need to make a front end text box for the results to post? or do you have any specific suggestions? –  May 29 '20 at 23:00

0 Answers0