Theoretical Foundation: Manage external users
1. Initial Intuitionβ
Imagine your company is developing a project with an external consulting firm. The consultants need to access some SharePoint documents, open tickets in the ITSM system, and maybe even view dashboards in Power BI. But they're not your company's employees. You don't want to create internal accounts for them, because when the project ends you'll need to remember to remove them, and while they exist, they appear in your directory as if they were employees.
Microsoft Entra ID solves this with the concept of external user (or guest user): an identity that exists in your directory, can receive permissions to access resources, but whose authentication is managed by the user's original identity provider, whether another Azure tenant, a personal Microsoft account, Google, Facebook, or any federation-compatible provider.
The consultant uses the password they already have at their company. You only control what they can access in your tenant, not how they prove who they are.
2. Contextβ
External user management is part of a broader set of Entra ID functionalities called Microsoft Entra External ID (formerly known as Azure AD B2B, Business-to-Business). It's the layer that enables secure collaboration between distinct organizations.
For AZ-104, the focus is on B2B Collaboration: inviting external users to your tenant as guests, managing what they can access, and controlling the lifecycle of these accesses.
B2B Direct Connect and External ID for Customers (B2C) are outside the scope of AZ-104 and are mentioned only to contextualize the complete landscape.
3. Concept Constructionβ
3.1 What is a Guest Userβ
A guest user is a user object in your tenant with userType equal to "Guest". Unlike a member user (userType: "Member"), the guest doesn't have a password managed by your tenant. When they try to access a resource, your tenant (called resource tenant or inviting tenant) redirects authentication to the user's original identity provider (called home tenant or source tenant).
This model is fundamental: the resource tenant controls authorization (what the guest can do), but the home tenant controls authentication (who the user is and how they prove it).
3.2 Supported Identity Providersβ
The external user doesn't need to have an account in another Azure tenant. Accepted providers are:
| Provider | Account Example | Note |
|---|---|---|
| Microsoft Entra ID (another tenant) | joao@partner-company.com | Cleanest flow for corporate collaboration |
| Personal Microsoft account | joao@hotmail.com, joao@outlook.com | Supported, but less recommended for corporate environments |
joao@gmail.com | Requires Google federation configuration in the tenant | |
| Facebook account | Possible, but rarely used in corporate context | |
| Email OTP (One-Time Password) | Any email address | For accounts without federated identity provider; Azure sends a code via email at each login |
| SAML/WS-Fed | Any compatible corporate IdP | For partners with their own identity provider that isn't Azure |
Email OTP is the fallback mechanism: if the invited user doesn't have any configured identity provider, Azure sends a one-time code to the email. This ensures that anyone with an email can be invited, regardless of their provider.
3.3 The Invitation Processβ
The invitation is the mechanism by which an external user is added to the tenant. The flow has well-defined stages:
"PendingAcceptance" State: while the invitation hasn't been redeemed, the user exists in the directory with status invitationState: PendingAcceptance. They still can't access resources. The invitation link can be resent by the administrator if the user didn't receive it or lost it.
Invitation redemption involves the guest:
- Clicking the link in the email
- Being redirected to their identity provider to authenticate
- Reviewing and accepting access permissions
- Being redirected to the original resource
After redemption, the user object in the inviting tenant is marked as active and the user can access resources for which they received permission.
3.4 Default Guest Permissionsβ
By default, guests have much more restricted permissions in the directory than member users. This is a security measure to prevent an external partner from exploring information in your directory.
| Capability | Member User | Guest (default) |
|---|---|---|
| Read other users' profiles | Yes | Limited (can't browse directory) |
| Read group members | Yes (public groups) | No (unless group member) |
| Register applications | Yes | No (configurable) |
| Invite other guests | Yes (configurable) | No (configurable) |
| Read tenant properties | Yes | No |
| Create security groups | Yes (configurable) | No |
Default guest permissions can be adjusted in Microsoft Entra ID > External Identities > External collaboration settings.
3.5 External Collaboration Settingsβ
The tenant has global settings that control who can invite guests and from which domains:
Who can invite guests (Guest invite settings):
| Setting | Who can invite |
|---|---|
| Anyone in the organization can invite | All member users |
| Member users and users assigned to specific admin roles can invite | Members + admins with Guest Inviter role |
| Only users assigned to specific admin roles can invite | Only admins (most restrictive) |
| No one can invite (disable guest access) | Nobody |
Domain restrictions (Allow/Deny list):
You can configure a list of allowed domains (allowlist) or blocked domains (denylist) for invitations:
- Allowlist: only users from listed domains can be invited. Example: only accept guests from
partner-company.comandconsulting.com. - Denylist: any domain except those listed can be invited. Example: block invitations from
competitor.com.
The two lists are mutually exclusive: you use one or the other, never both simultaneously.
4. Structural Viewβ
An important point of this structure: guests are subject to Conditional Access from the inviting tenant, not just from the source tenant. You can create Conditional Access policies that apply specifically to guests, requiring, for example, that all external accesses go through MFA managed by your tenant, regardless of what the source tenant requires.
5. Practical Operationβ
Invitation and Access Flowβ
The complete cycle of an external user, from invitation to access:
Important and Non-Obvious Behaviorsβ
The guest already exists in another tenant: when you invite joao@partner-company.com, if that address already has a guest object in another Azure tenant, Entra ID creates a separate object in your tenant. Each tenant has its own representation of the guest, with its own accesses and settings.
Home tenant Conditional Access can block: if the guest's home tenant has a Conditional Access policy that blocks logins from outside certain networks, the guest may not be able to authenticate even though your tenant (resource tenant) allows access. The guest is subject to policies from both tenants.
MFA: who requires and who executes: if your tenant has a Conditional Access policy that requires MFA for all guests, Azure requests MFA at access time. The guest can satisfy this MFA using MFA configured in the home tenant (if the home tenant is another Azure tenant with active MFA) or Azure can request additional MFA. This behavior is configurable via trust settings in external collaboration settings.
Trust settings: you can configure your tenant to trust MFA claims and compliant device claims from the home tenant. If enabled, a guest who already completed MFA in the home tenant won't need to redo MFA in your tenant. If disabled, your tenant will require MFA independently.
Guest Representation in Directoryβ
The UPN of a guest in the inviting tenant has a special format:
joao_partner-company.com#EXT#@contoso.onmicrosoft.com
The #EXT# is a marker indicating it's an external user. The user's actual address (joao@partner-company.com) is stored in the object's mail property. This is important because scripts and filters need to handle this special format when working with guests.
6. Implementation Methodsβ
6.1 Azure Portalβ
When to use: invite individual users, review accesses, check pending invitation status.
Path: Microsoft Entra ID > Users > New user > Invite external user
Fields to fill:
- Email: the external user's email address
- Display Name: how the name will appear in your directory
- Invitation message: custom message included in the invitation email (optional, but recommended to give context to the guest)
- Groups: you can already add the guest to groups at invitation time
- Roles: you can already assign directory roles (rarely necessary for guests)
6.2 PowerShell (Microsoft Graph PowerShell SDK)β
When to use: invite multiple guests, automation, integration with onboarding flows.
Invite an external user:
New-MgInvitation `
-InvitedUserEmailAddress "joao@partner-company.com" `
-InvitedUserDisplayName "JoΓ£o Silva (Partner Company)" `
-InviteRedirectUrl "https://myapps.microsoft.com" `
-SendInvitationMessage:$true
The InviteRedirectUrl parameter defines where the user is redirected after redeeming the invitation. Using https://myapps.microsoft.com is common as it takes the guest to the applications portal where they can see what they have access to.
Invite multiple guests from CSV:
Import-Csv -Path "guests.csv" | ForEach-Object {
New-MgInvitation `
-InvitedUserEmailAddress $_.Email `
-InvitedUserDisplayName $_.Nome `
-InviteRedirectUrl "https://myapps.microsoft.com" `
-SendInvitationMessage:$true
}
Check guests with pending invitation:
Get-MgUser -Filter "userType eq 'Guest'" -All `
-Property "displayName,mail,externalUserState,externalUserStateChangeDateTime" |
Where-Object { $_.externalUserState -eq "PendingAcceptance" }
Resend invitation to a pending guest:
# Resend requires deleting and recreating the object, or using the invitation API again
New-MgInvitation `
-InvitedUserEmailAddress "joao@partner-company.com" `
-InviteRedirectUrl "https://myapps.microsoft.com" `
-SendInvitationMessage:$true `
-ResetRedemption:$true
The ResetRedemption parameter is important: it resets the invitation state for a guest who was invited before, allowing the link to be resent without needing to delete and recreate the object.
6.3 Azure CLIβ
# Invite a guest
az ad invitation create \
--invited-user-email-address joao@partner-company.com \
--invite-redirect-url "https://myapps.microsoft.com" \
--send-invitation-message true
# List all guests
az ad user list --filter "userType eq 'Guest'" \
--query "[].{Nome:displayName, Email:mail, Estado:externalUserState}"
Limitation: CLI has less coverage for guest management compared to PowerShell with Graph SDK. Reset redemption and advanced invitation settings are more accessible via PowerShell or Graph API directly.
6.4 Microsoft Graph APIβ
Send invitation:
POST https://graph.microsoft.com/v1.0/invitations
Content-Type: application/json
{
"invitedUserEmailAddress": "joao@partner-company.com",
"invitedUserDisplayName": "JoΓ£o Silva (Partner Company)",
"inviteRedirectUrl": "https://myapps.microsoft.com",
"sendInvitationMessage": true,
"invitedUserMessageInfo": {
"customizedMessageBody": "You've been invited to collaborate on Project Alpha. Click the link to accept."
}
}
List all guests with pending invitation:
GET https://graph.microsoft.com/v1.0/users?$filter=userType eq 'Guest' and externalUserState eq 'PendingAcceptance'&$select=displayName,mail,externalUserState
7. Control and Securityβ
Conditional Access Policies for Guestsβ
Conditional Access policies can be applied specifically to external users. This allows creating different rules for guests without affecting internal users.
Example of useful policy for guests:
- Condition:
userType is Guest - Control: Require MFA + Require compliant device (or just MFA if device isn't managed)
- Result: all external user access requires MFA in your tenant
Critical point: when creating Conditional Access policies for guests, be careful not to inadvertently block all guests before configuring accepted MFA methods. A policy that requires MFA without configuring trust settings can block guests who can't register MFA methods in your tenant.
Cross-Tenant Access Settingsβ
Entra ID has a feature called Cross-Tenant Access Settings that allows configuring specific trust relationships per source tenant. It's different from global external collaboration settings.
With Organizational Settings, you can configure for a specific partner tenant:
- Trust MFA they already executed (avoiding double-MFA)
- Trust compliant devices registered in their tenant
- Completely block inbound or outbound collaboration with that tenant
Entra ID Identity Governance: Access Reviews for Guestsβ
One of the biggest concerns with guests is accumulation over time: consultants who finished projects, partners from terminated contracts, former suppliers. Access Reviews (with Entra ID P2 license) allows creating periodic reviews specific for guests:
- Configurable frequency (monthly, quarterly, annual)
- Reviewer: group owner, guest sponsor, or the guest themselves
- Automatic action if no response: remove access or maintain (configurable)
8. Decision Makingβ
How to configure guest permissions?β
| Situation | Recommended configuration | Reason |
|---|---|---|
| Collaboration with few known partners | Allowlist with specific domains | Minimizes attack surface, ensures control |
| Open environment for many partners | Denylist with prohibited domains | Flexibility while maintaining blocks on competitors or suspicious domains |
| High security, no external collaboration | Disable invitations completely | Zero risk of inadvertent external access |
| Partner with deep and long-lasting relationship | Cross-tenant trust settings configured | Smoother experience (no double-MFA), more productivity |
How to control MFA for guests?β
| Situation | Approach | Consideration |
|---|---|---|
| Guests from another Azure tenant with active MFA | Configure trust to accept MFA from home tenant | Avoids double-MFA, good experience |
| Guests with personal account (Gmail, Hotmail) | Require MFA via Conditional Access in your tenant | Home tenant doesn't have corporate controls |
| Guests via Email OTP | Implicit MFA in the OTP itself | The code sent via email already works as an additional factor |
| High security environment | Always require MFA, without trust settings | Maximum security, more friction in experience |
How to terminate a guest's access?β
| Situation | Action | Impact |
|---|---|---|
| Project ended, access no longer needed | Delete the guest object | Removes access immediately, object goes to recycle bin for 30 days |
| Project paused, access temporarily unnecessary | Disable the account | Blocks login, preserves settings and associations |
| Multiple guests from an ended project | PowerShell script to disable/delete in bulk | Efficient for mass cleanup |
9. Best Practicesβ
Define a sponsor for each guest: the sponsor is the internal user responsible for that external relationship. They are notified in Access Reviews and are the point of contact for any questions about access. Entra ID has a sponsors field in the guest object to formally register this.
Use groups to manage guest access, not direct assignments: adding a guest to an access group is much more scalable than assigning RBAC roles directly. When access needs to be revoked, just remove the guest from the group.
Implement periodic Access Reviews for groups with guests: especially for groups that control access to sensitive resources. Quarterly is a reasonable frequency for most environments.
Name guests in an identifiable way: use the format First Last (Company) in the Display Name, like "JoΓ£o Silva (XYZ Consulting)". In a directory with hundreds of users, identifying who is external and from which company greatly facilitates management.
Record the purpose and creation date: use fields like Department or extensionAttribute1 in the guest object to record the project or context of access and when it was created. This facilitates future reviews.
Configure redirect URL to myapps.microsoft.com: when inviting, use https://myapps.microsoft.com as the redirect URL. This gives the guest a clear view of everything they can access in your tenant, improving the experience and reducing support calls.
10. Common Errorsβ
Inviting guests without defining access scope beforehand
The invitation is sent, the guest redeems it, and then no one knows for sure what they should be able to access. Result: the guest stays in the directory without real access to anything, or receives excessive access "to make it easier". Always define beforehand which groups the guest will be added to before sending the invitation.
Not removing guests after the need ends
Guests accumulate over the years. A tenant without periodic cleanup can have hundreds of guests from projects ended years ago, some with access to resources that still exist. Implement Access Reviews or a manual process for semi-annual review.
Confusing the authentication domain with the email domain
A user joao@empresa-parceira.com can have their authentication managed by an Azure tenant different from empresa-parceira.com if the partner company uses a tenant with a custom domain. In most cases this works transparently, but in login problem diagnostics, it's important to understand that the email address and authentication tenant don't always correspond exactly.
Applying Conditional Access policies without exception for emergency accounts
If you create a policy that blocks all guests without MFA and don't test before activating, you can inadvertently block all guests at once. Always test Conditional Access policies in "Report-only" mode before activating, and have an emergency access account excluded from policies.
Forgetting that the guest is subject to policies from two tenants
When a guest complains they can't access, the problem may be in their home tenant (conditional access policy, MFA not configured, blocked account) or in the resource tenant (poorly configured policy, access not assigned). Diagnosis needs to consider both sides, but the resource tenant administrator only has visibility of their own side.
Assuming that deleting a guest from the directory terminates all access immediately
When a guest is deleted, they go to the recycle bin for 30 days. During this period, the object still exists and technically could be restored with all access. For immediate and definitive termination, delete AND confirm that the object was removed from the recycle bin, or simply disable the account if you want to preserve history.
11. Operation and Maintenanceβ
Auditing Accumulated Guestsβ
List all guests and when they were created:
Get-MgUser -Filter "userType eq 'Guest'" -All `
-Property "displayName,mail,createdDateTime,externalUserState,signInActivity" |
Sort-Object createdDateTime |
Select-Object displayName, mail, createdDateTime, externalUserState
The signInActivity property (requires P1 or P2 license) shows the last login. Guests who never logged in or haven't logged in for more than 90 days are candidates for review and possible removal.
List guests without login in the last 90 days:
$cutoff = (Get-Date).AddDays(-90)
Get-MgUser -Filter "userType eq 'Guest'" -All `
-Property "displayName,mail,signInActivity" |
Where-Object {
$_.SignInActivity.LastSignInDateTime -lt $cutoff -or
$null -eq $_.SignInActivity.LastSignInDateTime
}
Monitoring Pending Invitationsβ
Invitations that remain pending for a long time may indicate that the email didn't arrive or that the user no longer has interest/need:
$diasLimite = 14
$cutoff = (Get-Date).AddDays(-$diasLimite)
Get-MgUser -Filter "userType eq 'Guest' and externalUserState eq 'PendingAcceptance'" -All `
-Property "displayName,mail,externalUserStateChangeDateTime" |
Where-Object { $_.ExternalUserStateChangeDateTime -lt $cutoff }
This lists guests whose invitation was sent more than 14 days ago and still hasn't been redeemed.
Important Limitsβ
| Item | Limit |
|---|---|
| Guests per tenant | Up to 50,000 by default (adjustable via support) |
| Guest/member ratio | Originally 5:1; this limit was removed by Microsoft. There's no longer a mandatory ratio |
| Invitation link expiration | 30 days to redeem the initial invitation |
| Objects in recycle bin after deletion | 30 days for restoration |
12. Integration and Automationβ
Entitlement Management: Access Packages for Externalsβ
The Entra ID Entitlement Management (with Governance or P2 license) allows creating Access Packages that externals can request on their own, without needing an administrator for each individual invitation.
This is ideal for scenarios where externals need to request resource access in a self-service manner, such as in partner portals or open collaboration programs.
Automation via Graph API with Approvalβ
For automated invitation scenarios with validation (for example, integrated with the company's contract management system):
- Contract system detects new approved supplier
- Calls Graph API to create invitation
- Adds the guest to the supplier access group
- Schedules access review for the contract end date
This flow can be implemented with Azure Logic Apps, Azure Functions, or Power Automate, connecting the contract lifecycle with the access lifecycle in Entra ID.
Lifecycle Workflows for Guestsβ
Lifecycle Workflows (with Governance license) allows creating automated flows triggered by lifecycle events. For guests, relevant events include:
- Guest created (trigger onboarding)
- Guest inactive for X days (trigger review or automatic removal)
- Expiration date defined in object reached (trigger offboarding)
13. Final Summaryβ
Essential points:
- A guest user has
userType: Guestand their authentication is managed by the home tenant (original identity provider), not the resource tenant. - The resource tenant controls what the guest can access; the home tenant controls how the guest proves their identity.
- The invitation process creates the object in the directory only after the redemption of the link by the guest. Before redemption, the state is
PendingAcceptanceand access doesn't work. - A guest's UPN in the inviting tenant has the format
email_domain#EXT#@tenant.onmicrosoft.com. - Guests have much more restricted directory permissions than members by default. They cannot browse the directory or see members of groups they don't belong to.
Critical differences:
- Allowlist vs. Denylist: they are mutually exclusive. Allowlist defines the only accepted domains; Denylist defines blocked domains, accepting all others.
- Disable vs. Delete guest: disable blocks login, preserves object and associations. Delete removes access and places object in recycle bin for 30 days.
- Trust settings per specific tenant (Cross-Tenant Access Settings) vs. global settings (External Collaboration Settings): per-tenant specific settings take precedence over global ones.
- MFA by home tenant vs. MFA by resource tenant: if trust settings are configured to accept MFA claims from home tenant, the guest doesn't need to perform MFA again. Without trust settings, the resource tenant can require additional MFA.
What needs to be remembered:
- Implement periodic Access Reviews to clean up inactive guests or those from ended projects.
- Always define an internal sponsor for each guest, making responsibility for access clear.
- Use groups to grant access to guests, never direct RBAC assignments when possible.
- The
signInActivityproperty (requires P1/P2) is the most reliable indicator to identify inactive guests. - The
ResetRedemptionparameter in the invitation API allows resending the invitation without deleting and recreating the guest object. - Conditional Access policies in the resource tenant apply to guests and can require MFA even if the home tenant doesn't require it.