Automatic logon / authentication using AD without getting a logon prompt - what am I missing

Hi

Try to setup PU with Windows Authentication in an AD domain environment so that it logs on automatically if the logged on user is in a specifc AD group and assigns relevant role e.g. if logged on to server with account which is in an AD group called PU-Admin then they logon automatically to PU (passthru?) and are assigned admin role.

For some reason though the “passthru?” is not working and i keep getting browser style network logon prompt popping up and have to keep entering my domain admin username and password to logon.

I used the method mentioned here - Security - PowerShell Universal and followed tips from here - AD Auth with group membership to role - #2 by turnitoff_onagain

What might I be missing? any thoughts / ideas please?

Thanks

Product: PowerShell Universal
Version: 3.6.2

Good question, i get this randomly the first time the site is hit.

Have you tried this?

Role to Claim Mapping

Additionally, depending on your browser setup, it may NOT be allowing the credentials to automatically be used… For example…

Microsoft Edge and IWA

Tried using Chrome and Edge - and don’t have problem with other software passing credentials so think it is just limited to PU, but will take a look at link you provided - thanks

No I haven’t tried that as can’t even get logging in to work yet re first part of issue, and assumed once that would work then code in rules.ps1 should handle assignment of correct role to the logged on user.

Other applications are working is in no way relevant to the Edge policy I posted. It all may work by default based on your default domain policy, but I won’t get too far off into the weeds. Full documentation for Edge is here.

You can check what policies are applied to your browser with…
chrome://policy
edge://policy

The link I posted is another (more direct way) of assigning roles without using a Powershell script. It’s a direct mapping of a user claim to a role. It also doesn’t rely on processing a script you ultimately have to write, so I recommend it.

Ultimately, if login IS working if you manually provide windows credentials, then I would say it’s safe to say policies/configuration in your web browser are not allowing Edge to present the credentials. This CAN be on a site-by-site basis even if it’s within your intranet.

1 Like

Getting nowhere fast here.

Have added IP address of the computer hosting PU to AuthServerAllowlist and it appears when I check:

edge://policy

But now it still doesn’t log on automatically AND with that setting enabled in policy I don’t get the old network style logon box either, so can’t login at all using AD account. I just see the normal PU logon screen and that won’t even accept the default form admin logon despite me leaving that enabled in authentication.ps1 as per example here - Security - PowerShell Universal

So I have to manually edit authentication.ps1, and restart the service to get back in again.

Think I will stick with Forms authentication for now as this is proving harder than it should to get working…

How do you have it configured?

Are you using IIS?

What does your appsettings file look like?

What does your authentication.ps1 file look like?

You mentioned adding the IP Address… Is there a reason you aren’t using the FQDN or a cname?

so, the funny thing is, if i cancel and refresh, it will then use the windows creds

Not using IIS, have it installed as a Windows Service e.g. standard MSI install method.

appsettings.json:-

{
  "Kestrel": {
    "Endpoints": {
      "HTTP": {
        "Url": "http://*:5000"
      }
    }
  },
  "Plugins": [
    "UniversalAutomation.LiteDBv5"
  ],
  "Data": {
    "RepositoryPath": "%ProgramData%\\UniversalAutomation\\Repository",
    "ConnectionString": "%ProgramData%\\UniversalAutomation\\database.db"
  }
}

I was using the example from here - Security - PowerShell Universal - for my authentication.ps1 - just changing it to my domain details and changing out-file path

It is just installed on a desktop computer rather than a server for now for testing purposes, so easier to use the IP address, other than that no real reason I couldn’t use computer name or FQDN rather than IP to connect

There should be a appsettings.json under the programdata directory too with more configurations.

Have you done this…? Security - PowerShell Universal

That was the one from within the programdata directory.

Somehow I had missed those two steps(!!), so now my appsettings.json looks like this:-

{
  "Windows": {
  "Enabled": "true"
},
  
  "Kestrel": {
    "Endpoints": {
      "HTTP": {
        "Url": "http://*:5000"
      }
    }
  },
  "Plugins": [
    "UniversalAutomation.LiteDBv5"
  ],
  "Data": {
    "RepositoryPath": "%ProgramData%\\UniversalAutomation\\Repository",
    "ConnectionString": "%ProgramData%\\UniversalAutomation\\database.db"
  }
  
  
}

My service was already running with a service user account and I have now run the setspn command.

But still not working unfortunately.

The output from the out-file line in authentication.ps1 is just showing “Authentication failed for !” - for some reason not showing result of $($Credential.UserName) or the value is empty - perhaps this might be relevant?

Okay, you are missing some things still…

Can you post the appdata.json from your ProgramData and the install directory?

I assume you meant appsettings.json rather than appdata.json?

If so this is the one from install directory (C:\Program Files (x86)\Universal)

{
  "Kestrel": {
    "Endpoints": {
      "HTTP": {
        "Url": "http://*:5000"
      }
    },
    "RedirectToHttps": "false",
    "UseHttpSys": "false",
    "BasePath": "",
    "Hsts": {
      "MaxAgeDays": 365
    }
  },
  "ApplicationInsights": {
    "InstrumentationKey": ""
  },
  "Logging": {
    "Path": "%PROGRAMDATA%/PowerShellUniversal/log.txt",
    "RetainedFileCountLimit": 31,
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",
      "Grpc": "Information"
    }
  },
  "AllowedHosts": "*",
  "CorsHosts": "",
  "Plugins": [
    "UniversalAutomation.LiteDBv5"
  ],
  "Data": {
    "RepositoryPath": "%ProgramData%\\UniversalAutomation\\Repository",
    "ConnectionString": "filename=%ProgramData%\\UniversalAutomation\\database.db;upgrade=true",
    "RunMigrations": true,
    "GitRemote": "",
    "GitUserName": "",
    "GitPassword": "",
    "GitBranch": "",
    "GitSyncBehavior": "TwoWay",
    "GitInitializeBehavior": "",
    "GitSyncInterval": "1",
    "ConfigurationScript": "",
    "Mode": "Manual"
  },
  "Api": {
    "Url": "",
    "GrpcPort": 0
  },
  "Authentication": {
    "Windows": {
      "Enabled": "false"
    },
    "WSFed": {
      "Enabled": "false",
      "MetadataAddress": "",
      "Wtrealm": "",
      "CallbackPath": "/auth/signin-wsfed",
      "Wreply": "",
      "UseTokenLifetime": true,
      "CorrelationCookieSameSite": ""
    },
    "OIDC": {
      "Enabled": "false",
      "CallbackPath": "/auth/signin-oidc",
      "ClientID": "",
      "ClientSecret": "",
      "Resource": "",
      "Authority": "",
      "ResponseType": "",
      "SaveTokens": "false",
      "CorrelationCookieSameSite": "",
      "UseTokenLifetime": true,
      "Scope": "openid profile groups",
      "GetUserInfo": false
    },
    "ClientCertificate": {
      "Enabled": "false"
    },
    "SessionTimeout": "25"
  },
  "Jwt": {
    "SigningKey": "PleaseUseYourOwnSigningKeyHere",
    "Issuer": "IronmanSoftware",
    "Audience": "PowerShellUniversal"
  },
  "UniversalAutomation": {
    "Queues": [],
    "JobHandshakeTimeout": 5,
    "JobDebugging": false,
    "ContinueJobOnServerStop": false
  },
  "UniversalDashboard": {
    "AssetsFolder": "%ProgramData%\\PowerShellUniversal\\Dashboard",
    "DashboardStartupTimeout": 10
  },
  "Secrets": {
    "SecretStore": {
      "Password": "PSUSecretStore"
    },
    "Database": {
      "EncryptionKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }
  },
  "ShowDevTools": false,
  "HideAdminConsole": false,
  "Profiling": false,
  "NodeName": ""
}

And the one from C:\ProgramData\PowerShellUniversal was posted in last post

Ahh, yeah appsettings.json.

Alright, so the problem is you never actually enabled windows authentication… I recommend reading through the documentation on configuration/settings a bit more thoroughly. While I’m sure it’s not exhaustive, I’ve found it gives you exactly what you need for setting up Windows Auth/OIDC configurations.

Use the json below for the AppSettings.json in your ProgramData. You need to preserve the structure of the document when adding settings to your appsettings.json in ProgramData (Authentication → Windows → Enabled.

{
  "Kestrel": {
    "Endpoints": {
      "HTTP": {
        "Url": "http://*:5000"
      }
    }
  },
  "Plugins": [
    "UniversalAutomation.LiteDBv5"
  ],
  "Data": {
    "RepositoryPath": "%ProgramData%\\UniversalAutomation\\Repository",
    "ConnectionString": "%ProgramData%\\UniversalAutomation\\database.db"
  },
  "Authentication": {
    "Windows": {
      "Enabled": "true"
    }
  }
}

I thought I had read the documentation.

My appsettings.json in ProgramData originally looked like this:-

{
  "Kestrel": {
    "Endpoints": {
      "HTTP": {
        "Url": "http://*:5000"
      }
    }
  },
  "Plugins": [
    "UniversalAutomation.LiteDBv5"
  ],
  "Data": {
    "RepositoryPath": "%ProgramData%\\UniversalAutomation\\Repository",
    "ConnectionString": "%ProgramData%\\UniversalAutomation\\database.db"
  }
}

I just copied the lines from here (Security - PowerShell Universal) to that file to enable it which didn’t have the “Authentication”: part!! - my mistake - will try that now and report back

still doesn’t work.

I will rip everything out tomorrow and start from scratch as fiddled about with so much now it may be something I have done inadvertently, so will do it as per all the advice you have given on a clean setup and then report back later tomorrow.

Thank you for all your help.

That is fair, the documentation builds on itself, so if you were looking to get WIA up quick it’s a bit of a gotcha.

I think if you did this when there was only an AppSettings.Json in the install directory, you would have understood what to do. Now that there is the persistent appsettings file in ProgramData, it’s a bit less intuitive.

@adam maybe some sort of disclaimer/warning could be added to the docs to make sure anyone new to the platform gets pointed to configuring the appsettings.json?

I’m totally open to whatever we can do to make this easier.

If you have particular suggestions, or even PRs, that you think will help the community, feel free to open something here: GitHub - ironmansoftware/universal-docs: Documentation for PowerShell Universal

If you have specifics and don’t want to deal with GH, I can certainly update this docs page.

Okay we have some progress :slight_smile:

I completely ripped out PU, removed all directories / files from ProgramData and reinstalled from scratch as detailed below:-

  1. Installed as Windows Service and set to use my service account to run

  2. Amended C:\ProgramData\PowerShellUniversal\appsettings.json to include

“Authentication”: {
“Windows”: {
“Enabled”: “true”
}
}

  1. Configured Service Principal Name using

setspn -S HTTP/mycomputername.mydomain.local myserviceaccount

  1. Configured registry to allow Edge to pass credentials (will obviously do via Group Policy in future)

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Edge AuthServerAllowlist REG_SZ mycomputername.mydomain.local

AND it worked!

So this is without creating an authentication.ps1 file in C:\ProgramData\UniversalAutomation\Repository.universal, whereas before I was using the example script from Security - PowerShell Universal. If I add this script now (and change it to my domain details) then it breaks it again… so basically doing above steps and C:\ProgramData\UniversalAutomation\Repository.universal being empty and containing no authentication.ps1 file works fine for me.

So part 1 sorted, now need to work out how I only allow specific AD users to login and assign roles based on AD group membership - assuming that is best way to do it? open to suggestions here. Basically will only have a handful of users, a couple will be admins so need full access, the rest will just need either Reader or User roles. Don’t want anyone without permissions to be able to gain access.