Cross-tenant access policy (XTAP) and the Graph API

Microsoft just announced the public preview of the Cross-tenant access settings (or policy) controls, which power both the “old” B2B and the new “native” (aka “B2B direct connect”) collaboration models within its cloud service. For details about what XTAPs are and how to configure them, refer to the original blog announcement or the official documentation. Doing things via the UI is of course no fun, so let’s explore how you can get the current configuration or make changes programmatically.

We will start with the Default settings, which control the experience for any resource for which no specific policy exists. To get the default configuration, issue a GET request against the /beta/policies/crossTenantAccessPolicy/default endpoint, and make sure you have Policy.Read.All permissions. Here’s the result, or the first part of it anyway:

From the top, we have the id (GUID) of the default policy; the isServiceDefault flag which indicates whether the defaults have been modified; the tenantRestrictions flag which indicates whether tenant restrictions are in place; the inboundTrust property which lists the claims (MFA, compliant device, Azure AD joined device) we trust from external organizations. In the example above, the default settings have not been modified, and you can see that no claims will be trusted, unless you specifically decide to make a change.

Next, the output of the “traditional” B2B inbound and outbound settings is returned. Since we haven’t made any changes yet, all users and groups are allowed to connect in both inbound and outbound direction, and so are all applications. The same however does not hold true for the “native federation” or “B2B direct connect” settings, whose output is shown below. You will notice that in the default settings, all “B2B direct connect” functionality is blocked, both inbound and outbound, for all users and all applications!

We’re not going to discuss the individual segments just yet, as you’ll need some easing into them, trust me. For now, it’s important to understand that the default settings are always into play, unless a tenant-specific (or partner-specific) settings object is configured. Such tenant-specific settings will take precedence, however any specific segment not configured on a per-tenant level will always fallback to the default settings. We will examine this scenario next.

To create a new partner-specific configuration, you will need to issue a POST request against the /policies/crossTenantAccessPolicy/partners endpoint, with Policy.ReadWrite.CrossTenantAccess permissions. The actual settings configuration is provided via the JSON payload and is where things get a bit complicated. As hinted by the screenshots above, you can configure three types of settings: those relevant to the “old”  B2B collaboration model, those relevant to “B2B direct connect”, and some generic settings which include the tenant id and trust settings for authentication claims. If you do not provide values for any of these settings, the /default policy settings will apply.

For example, if we want to create a policy for a new partner, and want to limit B2B collaboration while ensuring users will not be double-asked for MFA, we can use a payload similar to the below. Do note that any identifiers you need to provide must be GUIDs, so if you want to limit inbound access to specific users/groups or applications, you will need to get the corresponding data from a person within the partner organization. For outbound policy settings, you can select them directly from the corresponding “picker” control. Speaking of which, the picker allows you to select from Security Groups, Distribution Groups, Mail-enabled Security Groups and Microsoft 365 Groups, as well as User objects. I couldn’t find any statement as to which group types are actually supported, and I only tested the Security group scenario, so keep that in mind. Also, the documentation mentions that Azure AD P1 license is required in order to configure specific target(s), whereas the “All object” scenario seems to be included OOTB.

In this example, we are blocking users from specific group and preventing them from accessing any Office 365 application within our tenant. This is signified by the “Office365” reserved value in the application targets field. Similarly, you can use the “AllMicrosoftApps” value to designate all Microsoft cloud apps, and “AllUsers” to apply the settings to all user objects accordingly. Adding individual entries is of course also possible, including multiple objects of the same type, each with a separate target element.

The JSON format we used above is not that complicated, but it can become annoying to handle when you have to add multiple targets, or configure multiple partner-level policies. My motivation in this case is to explore the corresponding API endpoints, but as any sane person I’ll likely rely on the Azure AD UI to configure this feature when needed. Do note that the Azure AD UI currently only allows you to configure B2B settings though, not “B2B direct connect” ones. Regardless of which method you use, you can use various permutations for accessType and targets, but covering all of them goes beyond the scope of this article. Refer to the official documentation for more info and examples.

Once the policy is configured to your liking, you can list its settings via a GET request against the /policies/crossTenantAccessPolicy/partners endpoint. if multiple policies are configured, you can filter based on the tenantId value, which is also used as the policy identifier. This in turn makes is possible to get the settings for specific tenant via a direct /partners/{tenantId} query. For example:

Do note all the “null” values. All of these will reflect the value of the corresponding setting within the default policy, as mentioned above. Thus it’s very important to first check the default configuration, and make any changes as necessary. Which in turn in done via a PATCH request against the /policies/crossTenantAccessPolicy/default endpoint. And in case you make a total mess of the default configuration, Microsoft is also providing a method to “reset” it. This is done by submitting an “empty” POST request against the /policies/crossTenantAccessPolicy/default/resetToSystemDefault endpoint.

To finish up on the various operations you can perform against XTAP policy objects, let’s also cover the scenario of removing a partner-specific configuration. This is done by issuing a DELETE request against the corresponding /policies/crossTenantAccessPolicy/partners/{tenantId} endpoint. Lastly, there is the “generic” policy object you can GET via the /policies/crossTenantAccessPolicy/ endpoint, which basically presents a “summarized” view of any and all configured policies, in a nifty JSON. Which you can also get via the Get-CrossTenantAccessPolicy ExO PowerShell cmdlet:

Lastly, let’s talk a bit about the “end user” experience. And set your expectations in the process. The “B2B collaboration” controls apply to “traditional” Guest user experiences, but as the functionality was just launched in public preview, do not expect all Microsoft 365 applications to abide by the rules you configure. For example, even though the “block” policy I configured above does prevent users from accepting an Azure AD Guest invitation, it did nothing to stop them from being added to a Group, have a file directly shared with them or prevent them from accessing a shared document library. In addition, keep in mind that policies do not retroactively remove blocked users!

You will also find the corresponding sign-in failure event with additional details, in both the resource and account tenants. Interestingly enough, the invitation status was updated to “Accepted” for said user, regardless of the message above. That said, this is still a preview functionality, and you can expect things to be a bit unpredictable. As the feature matures and support is added across all Microsoft 365 apps that support the B2B model (both “old” and “new”), such oddities will likely disappear.

This entry was posted in Azure AD, Exchange Online, Graph API, Microsoft 365, Office 365, PowerShell. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.