AAD OIDC set groupMembershipClaims gets ERR_HTTP2_PROTOCOL_ERROR

Product: PowerShell Universal
Version: 1.5.19

Hi

I am trying to place our on-prem PU server to go behind Azure AD (AAD) for logins, as we want the end-user to use MFA (controlled by our conditional access). I have followed the guides and managed to get users to go through the process using OIDC and they either log on to the dashboard (which has authentication enabled and roles set up) or they get access denied message to the dashboard as their role is not part of the authentication, so this works! :smiley:

However, looking to set up roles within PU using Hasclaim and as soon as I change the AAD application manifest from "groupMembershipClaims": null, to "groupMembershipClaims": "SecurityGroup", or "groupMembershipClaims": "All", when I try and logon on any account I get “ERR_HTTP2_PROTOCOL_ERROR” once logged on. Revert back to null and it works, but ideally, I need to use claims and policy to define the users’ access. I am sure that I have missed something, can anyone help?

Set-up
Windows 2019 Server
IIS Setup (ZIP Install)
Authentication for IIS - Anon

Web.config
Set as default install - i.e. forwardWindowsAuthToken=“false”

OIDC Configuration:

"OIDC": {
  "Enabled": "true",
  "CallbackPath": "/auth/signin-oidc",
  "ClientID": "xxxx-xxxxxx-xxxxxx-xxxxx-xxxxx",
  "ClientSecret": "xxxx-xxxxx-xxxxx-xxxxx-xxxxx",
  "Resource": "https://graph.microsoft.com",
  "Authority": "https://login.microsoftonline.com/xxxx-xxxx-xxxxx-xxxxxx-xxxxxxx",
  "ResponseType": "id_token token",
  "SaveTokens": "true",
  "UseTokenLifetime": "false",
  "CorrelationCookieSameSite" : "None"
},

Azure App
Note that I have ticked the following

Access tokens (used for implicit flows)
ID tokens (used for implicit and hybrid flows)

Can you let me know how many group claims you expect to have per user? This error can happen if you have a lot of groups and it overflows the maximum header size. We’ve bumped this value a couple times to support a couple hundred claims but it always seems like there are more.

I honestly thought we just removed the limit in the current version but maybe we have a regression here.

The test account I am using has 35 group claims and this will be probably the minimum number for our environment. From your comment, I have managed to get this working. In AAD → Enterprise Application I have assigned one of the groups that are needed, for example, ‘Service Desk’, which the test user was part of and then in the manifest, I have changed “groupMembershipClaims” to have the value “ApplicationGroup”, (Emits only the groups that are explicitly assigned to the application and the user is a member of) . I have to do some more testing but my initial test looks good. Any user that is not in the group will get an error (HTTP ERROR 500), which is fine for the moment (as they shouldn’t have access anyway).

I will do some more testing and build the environment with what I have found, unless you think this is wrong. I will update once i have finished my testing.

Strange. That’s not that many claims. When I get a moment I’ll test in my environment. I have like 300 groups setup for one of my users for this particular case.

Hey @adam any update? I’m running 2.3.1 and getting the same problem. My user only has 79 groups and had another try that has 56 groups with the same results. I did notice this in the logs
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/1.1 POST http://mydomain.com/auth/signin-oidc application/x-www-form-urlencoded 1331 - 302 0 - 1638.6758ms

shouldnt that be going to HTTPS://mydomain.com instead of HTTP://mydomain.com?

I have no problem using Azure AD and PSU 2.3.1 That is suspicious that it’s posting to the HTTP address. Can you share how you’ve configured the appsettings.json? Do you have HTTP and HTTPS enabled?

Here is my appsettings.json

{
  "Kestrel": {
    "Endpoints": {
	"HTTPS": {
         "Url": "https://*:443",
           "Certificate": {
             "Subject": "mydomain.com",
             "Store": "My",
             "Location": "LocalMachine",
             "AllowInvalid": "true"
           }
      }
    },
    "RedirectToHttps": "false"
  },
  "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",
    "AspNetCoreRateLimit"
  ],
  "Data": {
    "RepositoryPath": "%ProgramData%\\UniversalAutomation\\Repository",
    "ConnectionString": "filename=%ProgramData%\\UniversalAutomation\\database.db;upgrade=true",
    "GitRemote": "",
    "GitUserName": "",
    "GitPassword": "",
    "GitBranch": "",
    "GitSyncBehavior": "TwoWay",
    "ConfigurationScript": ""
  },
  "Api": {
    "Url": ""
  },
  "Authentication": {
    "Windows": {
      "Enabled": "false"
    },
    "WSFed": {
      "Enabled": "false",
      "MetadataAddress": "",
      "Wtrealm": "",
      "CallbackPath": "/auth/signin-wsfed",
      "Wreply": "",
      "UseTokenLifetime": true,
      "CorrelationCookieSameSite": ""
    },
    "OIDC": {
      "Enabled": "true",
      "CallbackPath": "/auth/signin-oidc",
      "ClientID": "xxxxxxxxxxxxxxxxxxxx",
      "ClientSecret": "xxxxxxxxxxxxxxxxxxxxxxx",
      "Resource": "",
      "Authority": "https://login.microsoftonline.com/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
      "ResponseType": "code",
      "SaveTokens": "false"
    },
    "ClientCertificate": {
      "Enabled": "false"
    },
    "SessionTimeout": "25"
  },
  "Jwt": {
    "SigningKey": "PleaseUseYourOwnSigningKeyHere",
    "Issuer": "IronmanSoftware",
    "Audience": "PowerShellUniversal"
  },
  "UniversalAutomation": {
    "JobHandshakeTimeout": 5,
    "JobDebugging": false,
    "ContinueJobOnServerStop": false
  },
  "UniversalDashboard": {
    "AssetsFolder": "%ProgramData%\\PowerShellUniversal\\Dashboard",
    "DashboardStartupTimeout": 10
  },
  "ShowDevTools": false,
  "HideAdminConsole": false
}

I did originally have the HTTP setting in the Kestrel block and removed it to see if it would help but it didn’t make a difference. Then again I saw this in the docs "The Kestrel endpoints section allows you to configure the web server. This settings are not used when hosting in IIS. " so I figured it doesnt apply anyway since this is hosted in IIS.

Ah, interesting. I wonder if has to do with IIS somehow. I’ll try in IIS. Those Kestrel settings shouldn’t be used when hosting in IIS.

I was having a similar issue with Azure AD/OIDC and IIS. Ultimately narrowed it down to including the Resource=“https://graph.microsoft.com.” Ended up ditching the resource, defining roles in the App Registration, and using $User.HasClaim(“roles”,"[ROLENAME]") for policy defined authorization.

1 Like