Track User Access to Teams Shared Channels with Entra ID Sign-In Logs

Know Who’s Collaborating in Teams Shared Channels From Outside Your Tenant

Updated 4 March 2024

When Microsoft launched Teams shared channels into public preview (according to MC390413, shared channels will GA in mid-July 2022) the rubber hit the road as tenant administrators tried to figure out the complexities of managing shared channels in production use. It’s true that Microsoft conducted a long private preview with many customers to get shared channels to the point where they squashed obvious bugs and delivered usable software. However, once software is exposed to the kind of examination that an application with 270 million monthly active users can create, other questions bubble to the surface.

Which brings me to the topic of controlling user access to shared channels. The cross-tenant access settings in the External identities section of the Entra admin center control which tenants your organization can access using Entra ID B2B Direct Connect. This is the underlying authentication mechanism for Teams shared channels. It allows users to authenticate in their home tenant and use that authentication, including MFA and device state claims, to access resources in other tenants, if permitted by other tenants.

Entra ID Sign-Ins Track Cross-Tenant Access

Microsoft’s guidance for cross-tenant access settings advises that you can use Entra ID sign in logs to figure out user access to other tenants. It’s true that you can use the PowerShell snippet provided there, but I think we can do better.

The code uses the Get-MgBetaAuditLogSignIn cmdlet from the Microsoft Graph PowerShell SDK to look for sign in records where the resource tenant identifier (the organization delivering a resource like Teams) is not the same as the home tenant identifier (the organization hosting the sign in logs).

$TenantId = (Get-MgOrganization).Id
Get-MgBetaAuditLogSignIn -Filter "ResourceTenantId ne '$TenantId'" -All:$True

The code works (the All switch doesn’t need $True), but the result of the query is a set of sign-in records for both Entra ID B2B Collaboration (guest accounts) and Entra ID B2B Direct Connect. This is a better filter if you want to focus on access to Teams shared channels:

Get-MgBetaAuditLogSignIn -Filter "ResourceTenantId ne '$TenantId' and CrossTenantAccessType eq 'b2bDirectConnect'" -All

Next, although you might recognize the identifier for your tenant, it’s unlikely that you’ll know the identifiers for other tenants (like 22e90715-3da6-4a78-9ec6-b3282389492b). To translate these identifiers into human-friendly tenant names, we need another method.

We’re already connected to the Microsoft Graph, so we can use a Graph query to resolve the identifier into a tenant name.

Finding Tenant Names

Fortunately, a beta query called findTenantInformationByTenantId does the trick. There’s little documentation available, but by running it through the Invoke-MgGraphRequest cmdlet (runs any Graph query when an SDK cmdlet is unavailable), we can retrieve tenant data:

$ExternalTenantId = $Record.ResourceTenantId
$Uri = "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId(tenantId='$ExternalTenantId')"
$ExternalTenantData = Invoke-MgGraphRequest -Uri $Uri -Method Get

The tenant information returned is:

Name                           Value
----                           -----
@odata.context                 https://graph.microsoft.com/beta/$metadata#microsoft.graph.tenantInformation
tenantId                       22e90715-3da6-4a78-9ec6-b3282389492b
displayName                    o365maestros
federationBrandName
defaultDomainName              o365maestros.onmicrosoft.com

I assume this web site, which can return the identifier of any Microsoft 365 tenant, uses a similar API.

Flow of the Script

The flow of the PowerShell script to analyze sign-in data is therefore:

  • Find sign-in records for Entra ID Direct Connect activity. If you want to process records for Azure B2B Collaboration, change the filter to remove the check against the CrossTenantAccessType property.
  • Extract data from each record, including resolving external tenant identifiers to tenant names.
  • Report.

In normal circumstances, the sign-in data will feature just a few tenants. It would be slow to run a query to resolve the tenant identifier for every record. To ensure performance, the script resolves a tenant name the first time it is encountered and stores the tenant name identifier and name in a hash table. When the script processes subsequent records for the same tenant, it reads the information from the hash table.

You can download the script from GitHub. Normal warnings apply: use at your peril, etc. and please fix my bugs…

Script Outputs

The output of the script is a PowerShell list containing details of sign-ins which use cross-tenant access to connect to Teams shared channels in external tenants (Figure 1).

Viewing information about user connects to Teams shared channels
Figure 1: Viewing information about user connects to Teams shared channels

The data can be parsed to reveal statistics like which tenants use cross-tenant access:

$Report | Group TenantName | Sort Count -Descending | Format-Table Name, Count

Or to reveal the names of the users who connect to external tenants:

$Report | Group User | Sort Count -Descending | Format-Table Name, Count

Name       Count
----       -----
Sean Landy     4
James Ryan     3
Ken Bowers     3

And so on. I’m sure you’ll find other ways to use the information to track what’s happening with Teams shared channels. The point is that the data is there if you need it. All that’s required is a little massaging of the information.


Insight like this doesn’t come easily. You’ve got to know the technology and understand how to look behind the scenes. Benefit from the knowledge and experience of the Office 365 for IT Pros team by subscribing to the best eBook covering Office 365 and the wider Microsoft 365 ecosystem.

10 Replies to “Track User Access to Teams Shared Channels with Entra ID Sign-In Logs”

  1. Hi there Tony, i think this is the third time this year one of your articles has been extremely useful to me, pretty amazing to me that this particular article was posted by you on the very day i needed it! hope all well with you and yours (ps we were neghbours once!)

  2. Hey Tony, as always extremely useful.
    Finally, there is a way to translate the TenantID to a Domain name. I noticed two things I your script line 6 you are missing one ”
    And what I noticed during my first steps with that API call I needed the Directory.AccessAsUser.All permission as well

    Keep up with this extremely good work

    Cheers

    Christoph

    1. Thanks. This is good example of the problems of finding the right permission to run Graph SDK commands. I had the right set in one tenant, but not in another… and I went with that set.

  3. It seems like this might not work anymore. I’m getting:
    PS C:\Users\jmartinez> Get-MgAuditLogSignIn -Filter “ResourceTenantId ne ‘$TenantId'” -All:$True
    Get-MgAuditLogSignIn_List: Invalid filter clause: Could not find a property named ‘ResourceTenantId’ on type ‘microsoft.graph.signIn’.

    Any ideas?

    1. I checked with Microsoft. The script was written in 2022 when we had SDK V1 and needed to use a Select-MgProfile cmdlet to switch to the beta endpoint. SDK V2 has separate cmdlet sets, which is why Get-MgBetaAuditSignIn works.

Leave a Reply

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