Azure AD B2B Guest User Types

Advertisement

What is up y’all? I hope you are doing awesome and that you’re amped up to read my blog post (also check out my other posts on awesome identity stuff) about Azure AD B2B guest user types!

Azure AD B2B Overview

I’m sure that most of you working with Azure AD know about the Azure AD B2B features which allow organizations to collaborate with external users in other organizations (guest users). Some examples of this are sharing a document in SharePoint or sharing out an application or resource with someone. Azure AD B2B makes this extremely easy, especially when the guest user has an account in another Azure AD tenant. Recently released preview features for Azure AD B2B have extended these capabilities. In this blog post I will provide an overview of these features and will also show some important properties/attributes which appear on guest users. These properties change slightly based on the type of guest user.

Direct Federation Overview

The Azure AD B2B Direct Federation feature allows organizations to share resources with outside organizations who do not have an Azure AD tenant. An organization can create a federation trust with a partner/outside organization that has some kind of federation service which supports SAML or WS-Fed. This could be an on-prem federation service such as AD FS or Ping Federate (or others). It could be a cloud identity service such as Google Cloud Identity or PingOne (or others).

Direct Federation trusts are added on the ‘Identity Providers’ blade

There are some limitations with the current release. One limitation is that a direct federation trust needs to be created for each domain used in the usernames of the invited users. Another limitation is that the domain added needs to also be part of the federation service DNS name (except for some approved cloud identity services as noted in the Microsoft article).

Direct Fed users appear with ‘Other’ as the source in the AAD Admin Center

Email OTP Overview

An email OTP user is another variety of Azure AD B2B guest user types. The Email OTP feature is a fundamental shift for guest users who do not exist either in a managed Azure AD tenant or an unmanaged Azure AD tenant. Instead of a user filtered out of the Azure AD Connect sync experiencing an error or potentially having a viral Azure AD tenant provisioned on the fly for each unmanaged domain, an EOTP guest user is created in the AAD tenant that is sharing the resource. The authoritative federation service for these accounts is marked as ‘mail’ when checking the Microsoft Graph for Email OTP guest users. The Email OTP feature was created mainly for two reasons:

  1. Partially Synced Tenant Issue: Historically users would experience issues redeeming their invitation if their user account was filtered from being synced via Azure AD Connect. This issue is known as ‘partial sync’.
  2. Unmanaged domains/Viral Tenants: With the Email OTP feature disabled (and before the Email OTP feature was released) a B2B invitation sent to a user who has an email domain which does not exist as a verified domain in Azure AD would result in a viral Azure AD tenant being created in an unmanaged state. Other users using the same domain would be created in this same tenant which remains in an unmanaged state until an admin takeover occurs.
Email OTP users are marked as ‘OTP’ in the AAD Admin Center
Advertisement

The Email OTP feature can be enabled or disabled in the Azure AD Admin Center. The change takes effect almost immediately based on my testing.

The Email OTP feature can be enabled or disabled via the Settings blade under Organizational relationships

Guest User Properties

Here, we will look at how to analyze the different Azure AD B2B guest user types. The first place you probably want to check out to learn about the various Azure AD B2B Guest user properties is the Microsoft Graph documentation for user objects. The list below contains what I feel are the most important ones to focus on for guest users:

  • userType
  • userPrincipalName
  • mail
  • creationType
  • externalUserState
  • identities

There are a few ways you can view these properties. One of them is by using the Get-AzureADUser cmdlet in the Azure AD version 2 PowerShell module. This module actually uses the Azure AD Graph or the Microsoft Graph behind the scenes (which one depends on which cmdlet you are running) when you execute cmdlets. However the v2 module does not show the identities property as of the time of this writing. Both Graph endpoints are listed below:

https://graph.windows.net (Azure AD Graph)

https://graph.microsoft.com (Microsoft Graph)

Another method is by using the Get-MsolUser cmdlet in the Azure AD PowerShell version 1 PowerShell module. This module does not show all of the properties listed above but it does show a property called AlternativeSecurityIds which seems to be a predecessor of what appears in the Identities property the Graph shows (I’ll demonstrate this later). It is worth noting that the v1 module does not use the Azure AD Graph or the Microsoft Graph. It actually uses a SOAP based endpoint known as the MSOL provisioning API: https://provisioningapi.microsoftonline.com/provisioningwebservice.svc

The last place to check (the place I recommend if you are comfortable interacting with REST APIs) is the Microsoft Graph. The beta endpoint for the Microsoft Graph will always have the latest updates and the newest user properties available. The innovation happens here first and the updates take time to be added to the Azure AD v2 PS module (note the identities property I mentioned earlier).

The easiest way to interact with the Microsoft Graph is through the Graph Explorer tool. You can log in against your Azure AD tenant and start sending requests and running queries fairly quickly. I will show some below. Of course, you can also use Postmon, PowerShell, a custom developed application or your scripting language of choice to interact with the Graph.

External Azure AD Guest Properties

The first type of guest I will review is the ‘external Azure AD’ guest user. This is the most traditional form of a guest user where usually the invited person is a member of another organization which also has an Azure AD tenant. During the invitation creation process, the invitations API checks the provided email address and determines the state of the user’s email domain and username. After the invitation is redeemed by the user, the guest user is marked as ‘external Azure Active Directory’ under the source property which appears in the Azure AD Admin Center. When the new guest user attempts to access a resource in the inviting tenant, they are directed to their home tenant to authenticate.

Properties in AAD v2 PS Module

You can run a cmdlet like this one to pull down the guest information with the v2 module:

Get-AzureADUser | where -Property UserType -eq Guest | select DisplayName,UserType,UserPrincipalName,mail,creationType,UserState

Here is an example of the output for one of these users:

DisplayName       : Ed Korth
UserType          : Guest
UserPrincipalName : ed_homedomain.com#EXT#@invitingtenant.onmicrosoft.com
Mail              : ed@homedomain.com
CreationType      : Invitation
UserState         : Accepted

Properties in AAD v1 PS Module

You can run a cmdlet like this one to pull down the guest information with the v1 module:

Get-MsolUser | where -Property UserType -eq Guest | select DisplayName,UserPrincipalName,SignInName,AlternativeSecurityIds,UserType -ExpandProperty AlternativeSecurityIds | select DisplayName,UserPrincipalName,SignInName,IdentityProvider,Type,UserType

Here are the results for one of the users:

DisplayName       : Raymond Jones
UserPrincipalName : rjones_homedomain.com#EXT#@invitingtenant.onmicrosoft.com
SignInName        : rjones@homedomain.com
IdentityProvider  :
Type              : 5
UserType          : Guest

As I referenced earlier, the v1 module has the AlternativeSecurityIds property. When you extend this property, it contains some useful properties like IdentityProvider and Type which seem to be similar to the values under the identities collection that appears in the Microsoft Graph. Type 5 seems to indicate that the user is from an external AAD tenant. For these users, the IdentityProvider is null.

Properties in the Microsoft Graph

To obtain guest user info in the Graph, you can send the following GET request:

https://graph.microsoft.com/beta/users?$filter=UserType eq 'Guest'&$select=displayName,userType,userPrincipalName,mail,creationType,externalUserState,identities

Here is an example of how one of the results appears:

{
    "displayName": "Ed Korth",
    "userType": "Guest",
    "userPrincipalName": "ed_homedomain.com#EXT#@invitingtenant.onmicrosoft.com",
    "mail": "ed@homedomain.com",
    "creationType": "Invitation",
    "externalUserState": "Accepted",
    "identities": [{
            "signInType": "userPrincipalName",
            "issuer": "invitingtenant.onmicrosoft.com",
            "issuerAssignedId": "ed_homedomain.com#EXT#@invitingtenant.onmicrosoft.com"
        }
    ]
}

This is similar to the output from the AAD v2 PS module. However, the identities property is more similar to the AlternativeSecurityIds property from the v1 module.

DirectFed Guest Properties

The next type of guest I will discuss is the ‘DirectFed’ guest user. These users do not exist in another Azure AD tenant. Instead, their identity provider is a non-Azure AD federation service.

In this case, when the user is invited the invitations API identifies that the user’s domain is not a verified domain in any Azure AD tenant. At some point between when the invitation is created and the user redeems the invitation during the Azure AD Home Realm Discovery process the Azure AD service takes the provided username and searches for a matching external domain federation object (managed via the Azure AD Graph API) in the inviting tenant to identify which federation service the user should be redirected to.

After the invitation is accepted by the user, the guest user is fully provisioned and marked as ‘Other’ under the source property which appears in the Azure AD Admin Center. When the new guest user attempts to access a resource in the inviting tenant, they are sent to their non-Azure AD identity provider to authenticate.

Properties in AAD v2 PS Module

Using the same cmdlet mentioned previously, here is an example of a DirectFed guest user:

DisplayName       : dpereyra
UserType          : Guest
UserPrincipalName : dpereyra_homedomain.com#EXT#@invitingtenant.onmicrosoft.com
Mail              : dpereyra@homedomain.com
CreationType      : Invitation
UserState         : Accepted

Notice here that in the V2 module, there is no difference between the external AAD guest user and the DirectFed guest user.

Properties in AAD v1 PS Module

Use the same cmdlet above. Here is an example of a DirectFed user in the v1 module:

DisplayName       : dpereyra
UserPrincipalName : dpereyra_homedomain.com#EXT#@invitingtenant.onmicrosoft.com
SignInName        : dpereyra_homedomain.com#EXT#@invitingtenant.onmicrosoft.com
IdentityProvider  : https://accounts.google.com/o/saml2?idpid=<GoogleSAMLUniqueIdentifier><invitingAADtenantID>
Type              : 6
UserType          : Guest

What is interesting here are the IdentityProvider and the Type properties. In this case, I used Google Cloud Identity as the 3rd party federation service (you can get a free instance of it with a GCP trial). A value of 6 for type seems to indicate the guest is a federated user.

Properties in the Microsoft Graph

Use the same query to look at a DirectFed user in the Graph. Keep in mind you can also locate the user’s objectId and append it to the request after “users/” to get a specific user object like the following: https://graph.microsoft.com/beta/users/<objectId>

{
    "displayName": "dpereyra",
    "userType": "Guest",
    "userPrincipalName": "dpereyra_homedomain.com#EXT#@invitingtenant.onmicrosoft.com",
    "mail": "dpereyra@homedomain.com",
    "creationType": "Invitation",
    "externalUserState": "Accepted",
    "identities": [{
            "signInType": "federated",
            "issuer": "https://accounts.google.com/o/saml2?idpid=<GoogleSAMLUniqueIdentifier><invitingAADtenantID>",
            "issuerAssignedId": "dpereyra@homedomain.com"
        }, {
            "signInType": "userPrincipalName",
            "issuer": "invitingtenant.onmicrosoft.com",
            "issuerAssignedId": "dpereyra_homedomain.com#EXT#@invitingtenant.onmicrosoft.com"
        }
    ]
}

The most notable property here is the identities collection property. For DirectFed users, it shows the non-AzureAD federation service identifier as one of the objects in the array. External AAD guest users do not have an object like this.

Email OTP Guest Properties

If you made it this far, you can review the last type of guest I will discuss. This is the ‘EOTP’ guest user. These users do not exist in another Azure AD tenant. This is either because their organization does not have a managed Azure AD tenant or because the user is filtered out from being synchronized via Azure AD Connect to their organization’s managed Azure AD tenant.

When the user is invited the invitations API identifies that the user does not exist in any Azure AD tenant and that there is no external domain federation object associated with the user’s domain. When the user redeems the invitation the Azure AD service sends a code to the invited email address. The user then checks their email for the code and enters it as a password. After the invitation is accepted the guest user is provisioned and marked as ‘OTP’ under the source property in the portal.

Properties in AAD v2 PS Module

Here is an example of an EOTP user in the v2 module:

DisplayName       : dlee
UserType          : Guest
UserPrincipalName : dlee_homedomain.com#EXT#@invitingtenant.onmicrosoft.com
Mail              : dlee@homedomain.com
CreationType      : Invitation
UserState         : Accepted

Nothing too exciting here. Let’s move on.

Properties in AAD v1 PS Module

Here is a sample EOTP user from the v1 module:

DisplayName       : dlee
UserPrincipalName : dlee_ekorth.life#EXT#@modernwavecloud.onmicrosoft.com
SignInName        : dlee_ekorth.life#EXT#@modernwavecloud.onmicrosoft.com
IdentityProvider  : mail
Type              : 6
UserType          : Guest

Two interesting things happened here. One is that the value for Type is 6. This will make more sense when looking at the Graph output below. The other thing which is interesting is the IdentityProvider is listed as mail. This leads me to believe that these EOTP users have a special Microsoft service or AAD tenant which is used to validate their codes. I haven’t seen any documentation stating this so this is just a theory.

Properties in the Microsoft Graph

Here is what the properties look like for an EOTP user in the Graph:

{
    "displayName": "dlee",
    "userType": "Guest",
    "userPrincipalName": "dlee_homedomain.com#EXT#@invitingtenant.onmicrosoft.com",
    "mail": "dlee@homedomain.com",
    "creationType": "Invitation",
    "externalUserState": "Accepted",
    "identities": [{
            "signInType": "federated",
            "issuer": "mail",
            "issuerAssignedId": "dlee@homedomain.com"
        }, {
            "signInType": "userPrincipalName",
            "issuer": "invitingtenant.onmicrosoft.com",
            "issuerAssignedId": "dlee_homedomain.com#EXT#@invitingtenant.onmicrosoft.com"
        }
    ]
}

Again, the most interesting property here is the identities collection, much like I mentioned in the DirectFed guest user scenario. EOTP users also have an object in the array with a signInType of federated. Also, If you look closely, the issuer appears as mail.

It seems like the Type property and the IdentityProvider property (from the v1 PS module) map to the signInType and issuer, respectively. These properties in the v1 module are not documented anywhere so I cannot confirm this.

Conclusion

I hope you find this blog post regarding Azure AD B2B guest user types useful for learning about the different types of Azure AD guest users and how the properties set on each type of guest user vary. Stay tuned for my next post which should be coming within the next week or so. Please leave comments below if you have any feedback or questions.