Cyber Intelligence

Entra ID External Identities Security: Governing B2B Guest Access at Scale

The average enterprise Entra ID tenant has a guest-to-member ratio approaching 1:1, and most of those guest accounts predate the conditional access policies built for employees. This guide covers Cross-Tenant Access Settings, invitation restrictions, CA policy gaps, Azure RBAC cleanup, Entra ID Access Reviews with auto-deny, and the KQL queries needed to find stale guests before they become incidents.

I
Microsoft Cloud Solution Architect
Entra IDB2B Guest AccessIdentity SecurityConditional AccessAzure SecurityGovernanceCross-Tenant Access

The Guest Account You Forgot You Created

Your active Entra ID tenant likely contains guest accounts for contractors who left 18 months ago, partners from a deal that never closed, and vendors who had project access that was never revoked. Unlike member accounts, guest accounts often bypass the conditional access policies built for employees, hold Azure RBAC assignments directly rather than through managed groups, and retain access to SharePoint sites, Teams channels, and Azure resources long after the business relationship ended.

Guest access is one of the most undergoverned attack surfaces in Microsoft 365 and Azure security programs. This is the operational guide for locking it down at scale.

How Entra ID External Identities Works (Security-Relevant Differences)

When you invite a guest user, Entra ID creates an external identity object in your tenant with a #EXT# suffix in the UPN (e.g., vendor@contoso.com becomes vendor_contoso.com#EXT#@yourtenant.onmicrosoft.com). This object has userType: Guest rather than userType: Member.

PropertyMemberGuest
Default directory permissionsRead most directory objectsLimited: cannot enumerate users, groups, or applications by default
Conditional Access inclusionAll policies apply by defaultMust be explicitly included in CA policy scope
MFA enforcementThrough CA policies in your tenantThrough CA policies (if guest is included) OR via the external tenant's own MFA claim
License requirementRequires Entra ID licenseGuest user ratio: 5 MAU guests per 1 P1 license
Cross-tenant accessN/AGoverned by Cross-Tenant Access Settings
Access reviewsFull supportFull support, but guest authenticates to their own tenant
PIM eligibilityFull supportFull support within your tenant
The conditional access gap is the one that produces incidents. New CA policies default to targeting "All Users," but many organizations exclude guests explicitly (or forget to include them) to avoid breaking external collaboration. The result: guests are exempt from MFA requirements, device compliance requirements, and location-based restrictions that apply to employees.

Cross-Tenant Access Settings: The Control Most Teams Have Not Configured

Cross-Tenant Access Settings (CTAS) governs:

  1. Inbound access: which external organizations can invite their users into your tenant as guests
  2. Outbound access: which of your users can be invited into external tenants
  3. Trust settings: whether to trust MFA claims and device compliance signals from the external tenant

The default state for all settings is "inherited from default policy." The default policy is: allow inbound and outbound B2B collaboration from all external tenants. Any external organization can invite your users, and your users can accept invitations from any external tenant, with no controls.

To audit your current CTAS configuration:

# List all partner-specific CTAS configurations
az rest --method GET   --uri "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/partners"   --query "value[].{TenantId:tenantId,InboundAllowed:b2bCollaborationInbound.usersAndGroups.accessType,OutboundAllowed:b2bCollaborationOutbound.usersAndGroups.accessType}"

# Check the default CTAS policy az rest --method GET --uri "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/default" --query "{InboundB2B:b2bCollaborationInbound,OutboundB2B:b2bCollaborationOutbound,TrustSettings:inboundTrust}"

The security baseline: set the default policy to block all inbound B2B collaboration, then create explicit partner-specific policies for approved organizations. This is the allowlist model. Most organizations are running the inverse: default allow with no partner-specific overrides.

To update the default policy to block inbound B2B by default:

az rest --method PATCH   --uri "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/default"   --body '{
    "b2bCollaborationInbound": {
      "usersAndGroups": {
        "accessType": "blocked",
        "targets": [{"target": "AllUsers", "targetType": "user"}]
      },
      "applications": {
        "accessType": "blocked",
        "targets": [{"target": "AllApplications", "targetType": "application"}]
      }
    }
  }'

Then add explicit allow rules for each approved partner tenant using their tenant ID. This prevents ad-hoc B2B relationships from unknown organizations from being established without administrative approval.

Restricting Guest Invitations

By default, any member of your tenant can invite external guests. The Guest inviter role is assigned implicitly to all members in most tenants. A line-of-business employee can invite a personal email address (vendor@gmail.com) as a guest to a Teams channel, and that guest account now exists in your Entra ID tenant with no business owner, no expiration date, and no review schedule.

To audit current invitation settings:

az rest --method GET   --uri "https://graph.microsoft.com/v1.0/policies/authorizationPolicy"   --query "{AllowInvites:allowInvitesFrom,GuestUserRole:guestUserRoleId}"

The allowInvitesFrom field has four possible values:

  • none: Only global administrators can invite
  • adminsAndGuestInviters: Admins and users with the Guest Inviter role
  • adminsGuestInvitersAndAllMembers: All members (default for most tenants)
  • everyone: Members and guests can both invite

The security baseline is adminsAndGuestInviters. Set it via:

az rest --method PATCH   --uri "https://graph.microsoft.com/v1.0/policies/authorizationPolicy"   --body '{"allowInvitesFrom": "adminsAndGuestInviters"}'

Complement this with a defined request process: guest invitations go through an approved workflow (ServiceNow, Jira, or a Power Automate form), a business owner must be assigned at invitation time, and the guest account must have an expiration date configured at the point of creation.

Conditional Access Policies for Guests

Critical CA policies that must explicitly include guests: MFA for all guest access to any application. In the CA policy, use the guestOrExternalUserTypes condition rather than including guests through the generic "All users" scope. This gives finer control over which external user types are targeted:

# Create CA policy requiring MFA for B2B guests (using Graph API)
az rest --method POST   --uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies"   --body @/dev/stdin << 'CAPOLICY'
{
  "displayName": "Require MFA for all B2B guest users",
  "state": "enabled",
  "conditions": {
    "users": {
      "includeGuestOrExternalUsers": {
        "guestOrExternalUserTypes": "b2bCollaborationGuest,b2bCollaborationMember",
        "externalTenants": {"membershipKind": "all"}
      }
    },
    "applications": {"includeApplications": ["All"]}
  },
  "grantControls": {
    "operator": "OR",
    "builtInControls": ["mfa"]
  }
}
CAPOLICY
Block guest access to Azure portal and Azure CLI. If guests do not manage Azure subscriptions under your tenant, block their access to the Azure management plane entirely. The relevant application IDs are 797f4846-ba00-4fd7-ba43-dac1f8f63013 (Azure portal) and 04b07795-8ddb-461a-bbee-02f9e1bf7b46 (Azure CLI and Azure Resource Manager). Trust MFA from specific partner tenants. If your partner organization has Entra ID with enforced MFA and you have contractual assurance of their security posture, configure CTAS trust settings to accept their MFA claims. This avoids double-MFA challenges for known partners:
az rest --method PUT   --uri "https://graph.microsoft.com/v1.0/policies/crossTenantAccessPolicy/partners/<partner-tenant-id>"   --body '{
    "inboundTrust": {
      "isMfaAccepted": true,
      "isCompliantDeviceAccepted": false,
      "isHybridAzureADJoinedDeviceAccepted": false
    }
  }'

Only set isMfaAccepted: true for partners where the MFA requirement is contractually enforceable. Trusting MFA from a partner whose enforcement posture is unknown defeats the control.

Azure RBAC and Guest Account Access

Guest accounts can be assigned Azure RBAC roles directly, just like member accounts. This is frequently how guests end up with production access: a developer adds a contractor as Contributor on a resource group to solve an immediate problem, and that assignment never gets reviewed.

To find all guest RBAC assignments across your Azure subscriptions using Resource Graph:

az graph query -q "
AuthorizationResources
| where type == 'microsoft.authorization/roleassignments'
| extend principalType = tostring(properties.principalType)
| extend principalId = tostring(properties.principalId)
| extend roleId = tostring(properties.roleDefinitionId)
| extend scope = tostring(properties.scope)
| where principalType == 'User'
| project principalId, roleId, scope
| limit 1000" --query "data" -o json

Cross-reference the returned principalId values against the Entra ID guest user list. Any guest with Owner or Contributor at subscription or resource group scope should be reviewed immediately and converted to time-bound PIM eligible assignments with a defined expiration.

Access Reviews: The Operational Foundation for Guest Governance

Entra ID Access Reviews (Entra ID P2) provide the systematic review mechanism. Configure three review schedules: Quarterly review of all guest accounts. Reviewer is the business owner assigned at invitation time. If the business owner has left the organization, escalate to their manager or trigger auto-deny. Configure via the Entra admin center or through the Graph API. Monthly review of privileged guest access. Any guest with Azure RBAC Owner, Contributor, or User Access Administrator assignments should be on a tighter review cycle than the general guest population. Annual review of all guests with SharePoint site owner access. Configured at the Microsoft 365 group level through access reviews scoped to unified groups.

Key configuration detail: set defaultDecision to Deny. This means if a reviewer fails to act within the review window (typically 14 days), the guest account is automatically removed. This is the operationally correct default: access is removed unless explicitly justified, not retained by reviewer inaction.

az rest --method POST   --uri "https://graph.microsoft.com/v1.0/identityGovernance/accessReviews/definitions"   --body @/dev/stdin << 'REVIEW'
{
  "displayName": "Quarterly Guest Account Review",
  "descriptionForAdmins": "Review all B2B collaboration guest users quarterly",
  "scope": {
    "@odata.type": "#microsoft.graph.principalResourceMembershipsScope",
    "principalScopes": [{
      "@odata.type": "#microsoft.graph.accessReviewQueryScope",
      "query": "/users?$filter=userType eq 'Guest'",
      "queryType": "MicrosoftGraph"
    }]
  },
  "reviewers": [{
    "query": "/users/{id}/manager",
    "queryType": "MicrosoftGraph",
    "queryRoot": "decisions"
  }],
  "settings": {
    "mailNotificationsEnabled": true,
    "reminderNotificationsEnabled": true,
    "defaultDecisionEnabled": true,
    "defaultDecision": "Deny",
    "instanceDurationInDays": 14,
    "recurrence": {
      "pattern": {"type": "absoluteMonthly", "interval": 3},
      "range": {"type": "noEnd"}
    }
  }
}
REVIEW

Monitoring Guest Account Activity with KQL

Guest accounts that are active but unused are risk without value. Guest accounts with sudden spikes in activity warrant immediate investigation.

Guest sign-in activity summary:

SigninLogs
| where TimeGenerated > ago(30d)
| where UserType == "Guest"
| summarize
    SigninCount = count(),
    UniqueApps = dcount(AppDisplayName),
    UniqueIPs = dcount(IPAddress),
    LastSeen = max(TimeGenerated)
    by UserPrincipalName, UserDisplayName
| order by SigninCount desc

Stale guest accounts with no sign-in activity in 90 days (immediate removal candidates):

let activeGuests = SigninLogs
| where TimeGenerated > ago(90d)
| where UserType == "Guest"
| summarize LastSignin = max(TimeGenerated) by UserPrincipalName;

AuditLogs | where TimeGenerated > ago(365d) | where OperationName == "Invite external user" | extend GuestUPN = tostring(TargetResources[0].userPrincipalName) | distinct GuestUPN | join kind=leftanti activeGuests on $left.GuestUPN == $right.UserPrincipalName | project StaleGuestAccount = GuestUPN

Guest accounts performing Azure management operations (these should be rare and warrant review):

AzureActivity
| where TimeGenerated > ago(7d)
| where Caller contains "#EXT#"
| where CategoryValue == "Administrative"
| project TimeGenerated, Caller, OperationNameValue, ResourceGroup, _ResourceId, ActivityStatus
| order by TimeGenerated desc

Both SigninLogs and AuditLogs require Entra ID diagnostic settings configured to forward logs to a Log Analytics workspace. If you are not already doing this, enable it before building any guest monitoring capability.

Guest Account Expiration and Domain Restrictions

Automatic expiration. Set guest user access expiration to 365 days in the External Collaboration Settings in the Entra admin center (Identity > External Identities > External collaboration settings). Guests must re-authenticate or re-accept an invitation to reset the expiration clock. This is a backstop control: it does not replace access reviews, but it catches guest accounts where the assigned reviewer has also left the organization. Domain allowlisting. In Collaboration Restrictions, specify an explicit list of allowed partner domains. Guest invitations from domains not on the list are blocked at the tenant level, regardless of individual user permissions. If your external collaboration is limited to 15 known partner organizations, a domain allowlist eliminates the entire ad-hoc invitation surface.

To retrieve current collaboration restrictions via the API:

az rest --method GET   --uri "https://graph.microsoft.com/v1.0/policies/authorizationPolicy"   --query "allowInvitesFrom"

Domain restrictions are configured in the Entra admin center under External Collaboration Settings > Collaboration restrictions. They cannot currently be set via the Graph API (as of 2026); use the portal or PowerShell's Set-EntraExternalIdentityPolicy cmdlet. Guest access to directory objects. The default guest permissions allow guests to read certain directory properties. Restrict this further by setting the guestUserRoleId in the authorization policy to 10dae51f-b6af-4016-8d66-8c2a99b929b3 (Restricted Guest User), which limits guests from enumerating directory objects even within your tenant.

Lifecycle Management with Entitlement Management

For organizations with 50 or more active external users, Entra ID Entitlement Management (P2) provides a structured access request and lifecycle workflow. Instead of direct invitations, external users request access to an Access Package, which bundles specific group memberships, Azure RBAC roles, and application assignments.

Key capabilities:

  • Access packages with configurable expiration dates: guests get access for 90 days and must re-request
  • Approval workflows: the assigned business owner must approve each external access request before provisioning
  • Auto-assignment policies: guests from specific partner organizations automatically receive an access package on first authentication
  • Catalog separation: a Catalog Owner manages which resources can be included; a business owner approves individual requests; an access reviewer confirms ongoing need

The critical organizational change: disable direct guest invitations from member users (allowInvitesFrom: adminsAndGuestInviters) and route all external access through Access Package requests. This gives you a complete audit trail of who requested access, who approved it, and when it expires.

Entra External ID: The Identity Platform Shift to Know About

Microsoft has been consolidating Entra ID's B2B and B2C capabilities under the Entra External ID umbrella since 2024. If your organization is building new customer-facing applications or partner portals, Entra External ID replaces Azure AD B2C for new workloads. The security model is similar but the configuration surface differs: External ID uses workforce tenant external collaboration for employees and partner tenants for customer-facing workloads.

The governance controls in this article (CTAS, invitation restrictions, access reviews, CA policies) apply to the B2B collaboration scenario in your existing workforce tenant. For External ID customer tenants, the security model involves consumer identity controls (SSPR, email OTP, social identity federation) with a separate admin center.

Hardening Checklist

  • [ ] Audit all guest accounts: az ad user list --filter "userType eq 'Guest'" and flag accounts older than 12 months with no recent sign-in
  • [ ] Set allowInvitesFrom to adminsAndGuestInviters via the authorization policy API
  • [ ] Configure CTAS default policy to block inbound B2B collaboration; add explicit allow partner policies for approved tenant IDs only
  • [ ] Deploy a CA policy requiring MFA for all b2bCollaborationGuest users on all applications
  • [ ] Deploy a CA policy blocking guest access to Azure portal (797f4846-ba00-4fd7-ba43-dac1f8f63013) and Azure CLI (04b07795-8ddb-461a-bbee-02f9e1bf7b46)
  • [ ] Enumerate all guest Azure RBAC assignments at subscription and resource group scope; convert Owner and Contributor assignments to PIM eligible with time bounds
  • [ ] Configure quarterly Entra ID Access Reviews for all guest accounts with defaultDecision: "Deny"
  • [ ] Configure monthly Access Reviews for guests holding privileged Azure RBAC roles
  • [ ] Enable guest user access expiration at 365 days in External Collaboration Settings
  • [ ] Configure a collaboration domain allowlist for all approved partner domains
  • [ ] Enable Entra ID diagnostic logs (SigninLogs, AuditLogs) to Log Analytics workspace for guest activity monitoring
  • [ ] Deploy KQL alerts for: guests with 90-day inactivity, guest Azure management operations outside change windows, and new invitations from non-allowlisted domains
  • [ ] Set guestUserRoleId to Restricted Guest User (10dae51f-b6af-4016-8d66-8c2a99b929b3) to limit guest directory enumeration capabilities
  • [ ] If managing 50+ active external users: implement Entra ID Entitlement Management with Access Packages and disable direct member-initiated invitations

Get weekly security insights

Cloud security, zero trust, and identity guides โ€” straight to your inbox.

I

Microsoft Cloud Solution Architect

Cloud Solution Architect with deep expertise in Microsoft Azure and a strong background in systems and IT infrastructure. Passionate about cloud technologies, security best practices, and helping organizations modernize their infrastructure.

Share this article

Questions & Answers

Related Articles

Need Help with Your Security?

Our team of security experts can help you implement the strategies discussed in this article.

Contact Us