Skip to main content
  1. Tips/

Federating Microsoft 365 / EntraID Guest Accounts with Okta

Fabio Grasso
Author
Fabio Grasso
Solutions Engineer specializing in Identity & Access Management (IAM) and cybersecurity.
Table of Contents

If you’ve ever tried to let EntraID (Azure AD) guest users sign in to an Okta-protected app via the built-in Microsoft IdP, you’ve probably hit a wall. The login flow either drops the user on a personal Microsoft account screen or fails outright with a confusing error.

The root cause is simple: guest accounts (B2B) live in a specific tenant, but Okta’s default Microsoft IdP talks to the common endpoint, which assumes the user can be discovered globally. Here are the notes I keep handy when wiring this up.

Why the default Microsoft IdP fails for guests
#

Okta’s out-of-the-box Microsoft IdP is pre-configured against the multi-tenant endpoint:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize

The /common endpoint relies on Microsoft’s home realm discovery: it inspects the email entered by the user and routes the authentication to the tenant where that identity lives. For a guest, the email (alice@example.com) resolves to a personal Microsoft account namespace, not the inviting tenant. The result is the classic error:

You can’t sign in here with a personal account. Use your work or school account instead.

…unless the user happens to also own a personal Microsoft Account with that email — in which case they’ll authenticate against the wrong identity and Okta will receive a token that has no relationship with your tenant.

Fix: use a tenant-specific Custom OIDC IdP
#

The solution is to bypass /common and pin the authentication to your tenant by using its tenant ID (a GUID, found in EntraID → Overview). This forces Microsoft to authenticate the user against your directory, where the guest object actually exists.

In Okta, don’t edit the built-in Microsoft IdP — create a new OIDC Identity Provider (Security → Identity Providers → Add → OpenID Connect IdP) with the following endpoints, replacing [MS_TENANT_ID] with your tenant GUID:

Setting Value
Issuer https://login.microsoftonline.com/[MS_TENANT_ID]/v2.0
Authorization endpoint https://login.microsoftonline.com/[MS_TENANT_ID]/oauth2/v2.0/authorize
Token endpoint https://login.microsoftonline.com/[MS_TENANT_ID]/oauth2/v2.0/token
JWKS endpoint https://login.microsoftonline.com/[MS_TENANT_ID]/discovery/v2.0/keys
Userinfo endpoint https://graph.microsoft.com/oidc/userinfo
Scopes openid profile email https://graph.microsoft.com/User.Read

You’ll also need an App Registration in EntraID (Application type: Web) with:

  • The Okta redirect URI (https://<your-okta-domain>/oauth2/v1/authorize/callback) added under Authentication → Redirect URIs.
  • A client secret generated under Certificates & secrets.
  • The delegated permissions openid, profile, email, and User.Read granted under API permissions.

Understand the guest username format
#

When an external user (e.g. alice@example.com) is invited as a guest into an EntraID tenant, Microsoft does not store their email as the UPN. Instead it generates an internal identifier:

alice_example.com#EXT#@contoso.onmicrosoft.com

This matters because:

  • Microsoft’s preferred_username / upn claim will return that mangled string, not alice@example.com.
  • If you want Okta to match the user by email, you must map the IdP’s email claim (not sub or upn) to Okta’s username/email attribute in the IdP profile mapping.
  • JIT provisioning rules, group rules, and policy conditions should be written against the email claim too, otherwise you’ll end up with users whose Okta username looks like alice_example.com#ext#@contoso.onmicrosoft.com.
Tip

Always inspect the ID token returned by Microsoft (e.g. via the Okta System Log → “Authentication of user via IDP” event) before finalizing the mapping. Different tenants and consent scopes return slightly different claim sets.

Note

The User.Read scope is what allows Okta to call https://graph.microsoft.com/oidc/userinfo and retrieve the guest’s actual email address rather than the #EXT# UPN.


Powered by Hugo Streamline Icon: https://streamlinehq.com Hugo Hugo & Blowfish