So you’ve read through part 1 and part 2 in this series as well as the attached links, right? 🙂 Excellent, let’s dive right into it.
Introducing Guest Users
When a licensed user of Office 365 needs to share data with a business partner the concept of an Azure AD guest user comes into play. Guest users are representations of Microsoft Live and Azure AD users that exist outside the user’s tenant. AAD Guest Users are created using three primary methods:
- User is added through Azure AD tab of the Azure Management Portal using the option User in another Microsoft Azure AD Directory
- User accepts an invite sent through an Office 365 application such as SharePoint Online
- User is invited through Azure AD B2B
When one of three above actions are taken, a subset of information about the user’s identity is copied from the source identity (whether it be a Microsoft Live or Azure AD identity). At the time of this writing this is a one time sync. Microsoft has hinted that this may change as the expand the System for Cross-domain Identity Management (SCIM for short) capabilities in Azure AD. What does this one time sync mean to you? Well if information in the guest user’s source AAD changes, that data may not be updated on the AAD Guest User object.
AAD Guest Users always authenticate to their own identity provider, no credentials are synchronized during the provisioning process. This also means that you do not have the ability to enable MFA on a guest user. This may change at a later date, but is a limitation at this time. This link provides more detail on guest users including limitations..
Review of Configuration
Now that I’ve provided an overview of guest users, let’s dive a little deeper. Recall from part 1, I’m using the following configuration:
- Azure AD Tenant 1
Name: feltonma.onmicrosoft.com
DNS Domain: feltonma.com
Subscriptions: Azure AD Premium, Office 365 Business PremiumWe’ll refer to this instance of AAD as the destination AAD. - Azure AD Tenant 2
Name: journeyofthegeek.onmicrosoft.com
DNS Domain: journeyofthegeek.com
Subscriptions: NoneThis is an independent instance of AAD. - Azure AD Tenant 3
Name: junkfelton.onmicrosoft.com
DNS Domain: None
Subscriptions: NoneThis instance of AAD has been provisioned by a global admin of the destination AAD. This means that the global admin has the ability to add users from this instance of AAD to the destination AAD through the Azure Management Portal. - Azure AD Tenant 4
Name: geekintheweeds.onmicrosoft.com
DNS Domain: geeksintheweeds.com
Subscription: NoneThis instance of AAD doesn’t exist yet. It will be provisioned when we leverage the B2B feature to invite a user that has an email address with the geeksintheweeds.com domain name.
Scenario 1 – Method 1 – Adding user through Azure Management Portal
In this first scenario I’ve added the user clark.devereaux@junkfelton.onmicrosoft.com from Azure AD Tenant 3 to our destination AAD via method 1. Let’s take a look at three key attributes using the Azure AD PowerShell module.
Queried from Azure AD Tenant 3 (source AAD)
Queried from Azure AD Tenant 1 (destination AAD)
Notice anything? The AlternateEmailAddresses attribute in the destination AAD doesn’t include the value from the source AAD. This means that the destination AAD doesn’t know about the user’s email address. Additionally, this user has no value in CloudExchangeRecipientDisplayType attribute (more on this attribute later). The net result of these two issues is the user is not considered mail enabled by Office 365 applications preventing Office 365 users from using built in features to email these users.
After I’ve granted the user access to a site in SharePoint Online and attempt to access that site as the clark.devereaux@junkfelton.onmicrosoft.com user, I receive the following error:
Why is this occurring? I will hold off on answering that question until we cover some additional scenarios.
Scenario 1 – Method 2 – Using SharePoint Online Invite System
In the second scenario I have added the user michael.walsh@journeyofthegeek.onmicrosoft.com from Azure AD Tenant 2 to the destination AAD via method 2. There are some interesting differences in what information is populated in the destination AAD.
Queried from Azure AD Tenant 1 (destination AAD)
Notice that the SignInName attribute has a value equal to the email address the invitation link was sent to. Additionally you’ll notice that values in the ProxyAddresses attribute include the user’s email address that has been configured in the AlternateEmailAddresses attribute in the source AAD instance. The CloudExchangeRecipientDisplayType also comes into play here.
The CloudExchangeRecipientDisplayType attribute is used to denote a mail-enabled user in Office 365. This attribute is the counterpart of the Exchange on-premises attribute msExchangeRecipientDisplayType as explained in this link. From my experience so far, AAD Guest User accounts that are mail-enabled have a value of 6 which means it is a Remote Mailbox (explained here. Interesting that the AAD Guest User we added via Method 1 doesn’t have a value of 6 isn’t it?
Scenario 3 – Method 3 – Inviting User through Azure AD B2B
In the last scenario I’ve added the user lawrence.cohen@geekintheweeds.com from Azure Tenant 4 via the Azure AD B2B feature. As I’ve explained above, prior to my invite there was no Azure AD instance associated with the geekintheweeds.com domain. After I accepted the B2B invite and went through the process of setting up the new Azure AD account, Microsoft spun up a new Azure AD instance associated with the geekintheweeds.com domain. This new instance can be taken over by anyone who can prove ownership of the geekintheweeds.com domain.
Let’s take a look at the user in the destination AAD instance and the source:
Queried from Azure AD Tenant 1 (destination AAD)
Queried from Azure AD Tenant 4 (source AAD)
Here we see that the AAD Guest User in this scenario is very similar to the AAD Guest User in the second scenario. The only significant difference is the source directory ProxyAddresses attribute is populated with a value. Note that while not displayed, this user also has a CloudExchangeRecipientDisplayType attribute with a value of 6.
Users in scenarios 2 and 3 can access the shared Office 365 content without issues. So why does the user in scenario 1 fail? Well, the best I can offer is a guess since I’ve been unable to find information on the identifier SharePoint Online uses to query for a user in Azure AD. From comparing how the users are represented in the destination, my guess is it has something to do with the user’s email address. In both scenarios that worked, the user’s SignInName attribute had a value of the user’s email address.
There is one other quirky thing I noticed when adding a user to the destination AAD using method 1. Let’s take a look at some of the most interesting attributes of the three users when queried via PowerShell from the destination AAD.
- User added through Azure Management Portal
AlternateEmailAddresses: {clark.devereaux@junkfelton.onmicrosoft.com}
CloudExchangeRecipientDisplayType:
SignInName: clark.devereaux@junkfelton.onmicrosoft.com
StrongAuthenticationUserDetails: Microsoft.Online.Administration.StrongAuthenticationUserDetails
StrongPasswordRequired: True
UserPrincipalName: clark.devereaux_junkfelton.onmicrosoft.com#EXT#@feltonma.onmicrosoft.com
UserType: Member - User added through an invite via SharePoint OnlineAlternateEmailAddresses: {michael.walsh@journeyofthegeek.onmicrosoft.com}
CloudExchangeRecipientDisplayType: 6
ProxyAddresses: {smtp:michael.walsh_journeyofthegeek.onmicrosoft.com#EXT#@feltonma.com, SMTP:michael.walsh@journeyofthegeek.com}
SignInName: michael.walsh@journeyofthegeek.com
UserPrincipalName: michael.walsh_journeyofthegeek.onmicrosoft.com#EXT#@feltonma.com
UserType: Guest - User added through Azure AD B2BAlternateEmailAddresses: {lawrence.cohen@geekintheweeds.com}
CloudExchangeRecipientDisplayType: 6
ProxyAddresses: {smtp:lawrence.cohen_geekintheweeds.com#EXT#@feltonma.onmicrosoft.com, SMTP:lawrence.cohen@geekintheweeds.com}
SignInName: lawrence.cohen@geekintheweeds.com
UserPrincipalName: lawrence.cohen_geekintheweeds.com#EXT#@feltonma.onmicrosoft.com
UserType: Guest
Notice something odd? The user I added through the Azure Management Portal is configured as a UserType of Member instead of a Guest. Odd huh? If this is by design, I haven’t been able to find any articles describing the reason why.
Take a look at the users within the Azure AD tab in the Azure Management Portal:
All users display as being sourced from another directory, yet this user is a user type guest. Super weird.
Summing it all up
It seems that users added via Method 1 cannot natively access information shared with them in Office 365. I plan on playing with the attributes a bit to see if can make it work, but even if that works, that is an ugly solution.
Method 2 and 3 both work as they should. So what’s the big deal? Well it comes down to control. If I want to have tight control over who my users can share data with, Method 1 would be a reasonable solution because it would require either the User Management or Global Admin role in Azure AD and I could even provision another tenant and provision users to it. Those users could have both company and consumer email addresses.
Method 2 means I have to give us some of my control to my users. In a large enterprise where roles and responsibilities are highly distributed and the enterprise has very sensitive data, there could be significant risk to handing over that control.
Method 3 seems to be the direction Microsoft wants to move. While B2B is extremely slick, there are limitations that come with it. One such limitation is the users I need to share data with can’t use consumer email domains. I haven’t tested whether or not Microsoft Live accounts associated with a consumer email address work, so that needs to be tested.
Diving deeper into situations like this really help put the puzzle pieces together on how each part of Azure works together to form the solution. It also helps reinforce the speed of change and innovation occurring within Azure and how important it is to have a good knowledge set in the foundations of the solution to keep up with that change.
In my next post I’ll dive a bit deeper and try to test some of the unknowns I’ve discussed above.