Azure AD multitenant - what goes in allowed_domains?

What happened?

I’m using Azure AD as my identity provider. I followed Azure AD | Pomerium and am able to login and view authenticate.example.com/.pomerium. However, when I configure a route with allowed_domains, I get 403 Forbidden (the Pomerium page, not my app’s) when accessing that route (after successfully logging in).

I would like to support logins from multiple Azure AD, so enabled multitenant on my registered application. I’ve configured my route with allowed_domains containing the email domain of my Azure user, my Azure AD tenant ID, and an alternate domain (xxx.onmicrosoft.com). All of these are met with 403 Forbidden as above.

A route configured with allow_any_authenticated_user: true works OK.

What did you expect to happen?

Access to be allowed.

What’s your environment like?

  • Pomerium version 0.17.3
  • Linux, kubernetes, helm chart 31.1.7

What’s your config.yaml?

idp_provider: azure
# other idp config provided via env vars
routes:
- from: https://app.example.com
  prefix: /debug/httpbin
  prefix_rewrite: /
  to: http://httpbin.httpbin
  allow_any_authenticated_user: true
  pass_identity_headers: true
- from: https://app.example.com
  to: http://app
  allowed_domains: ["example.com", "< Azure AD tenant UUID >", "xxx.onmicrosoft.com"]
  pass_identity_headers: true
- from: https://authenticate.example.com
  to: https://pomerium-authenticate.default.svc.cluster.local
  allow_public_unauthenticated_access: true

What did you see in the logs?

The logs from pomerium-authorize contain:

"allow":false,"allow-why-false":["domain-unauthorized","non-pomerium-route"],"deny":false,"deny-why-false":["valid-client-certificate-or-none-required"]

Additional context

Summary: everything works when I configure allow_any_authenticated_user: true. But I’m not sure what to put in allowed_domains to restrict to certain Azure AD domains (tenants?). I turned on debug-level logging, but I don’t see anything that suggests what the current domain of my logged-in user actually is.

1 Like

Skimming through Pomerium code, it looks like “domain” is parsed out of a user’s email address (see domain.go).

And from the Troubleshooting section of the Azure AD docs:

In our testing, we found that users could be created in an Active Directory without an email address as part of their user claim. Pomerium user identity depends largely on the associated email address.

Which now makes perfect sense, since with no email, there is no domain that could be matched in allowed_domains.

Inside Azure AD, it seemed insufficient to edit the user to add “Contact info / Email”; I also had to set “Contact info / Altername email” to the same value (or perhaps I simply had not waited long enough for the change to propagate).

At any rate, the https://authenticate.example.com/.pomerium user info page previously had no Email field, and now it does. And now allowed_domains appears to work as expected.

2 Likes

Hi @patrick132135. Sorry I didn’t respond to this post earlier, but I’m glad you got the issue resolved.

As our technical writer, I’d be happy to get any feedback on that doc; if there’s anything else we can say (or say it differently) to make this quirk of Azure more apparent.