Invoke-MgGraphRequest -OutputFilePath vs Out-File Performance Comparison

less than 1 minute read

In case you were wondering which is faster.

Invoke-GraphRequest -Uri 'beta/users' -OutputFilePath ./user.json

or

Invoke-GraphRequest -Uri 'beta/users' | Out-File -FilePath ./user.json

Surprisingly, the answer is that Out-File is the fastest

Here’s what I got when I ran the two commands:

Measure-Command { Invoke-GraphRequest -Uri 'beta/users' -OutputFilePath ./user.json }

TotalSeconds      : 3.1084942

Invoke-GraphRequest -Uri 'beta/users' | Out-File -FilePath ./user.json

TotalSeconds      : 0.5016927

That got me thinking. Does the performance change much when using different output types?

Measure-Command { Invoke-GraphRequest -Uri 'beta/users' -OutputType Json | Out-File ./user.json }

TotalSeconds      : 0.4035508

Here’s what I get when I ran the same command with different output types. There was no clear winner and they all ranged between 0.2 and 0.5 seconds.

OutputType TotalSeconds
Json 0.4035508
Hashtable 0.3948994
PSObject 0.4495978
HttpResponseMessage 0.5539832

Device filter > Device platform

less than 1 minute read

When designing a conditional access policy and have the choice between using device filter and device platform always use device filter.

The catch is that device filter can only be applied to managed or hybrid joined devices.

It’s a limitation since you can’t use it with unmanaged devices, but that is exactly the reason why it is better to use it over device platform when your CA policy is targeting managed devices.

The device platform relies on the user agent string which can be easily spoofed. Nicola has a good write up on this over at Bypassing Conditional Access Device Platform Policies

He man skeleton recommends using device filter over device platform

Azure AD multi-tenant app vs single tenant app

2 minute read

I’ve recently noticed that Azure AD admins are being asked to create multi-tenant apps in their corporate tenant.

In some instances, it was the devs in the org asking for this, in other instances it was the application vendor.

Here are some things to watch out for 👇

Multi-tenant apps are meant for ISVs and SaaS vendors to create an instance of an app in ‘their own tenant’. Examples of such apps are ServiceNow and SalesForce.

When an app is created as a multi-tenant app, ANY user from ANY Azure AD tenant can visit the app’s url and sign in.

If you create a multi-tenant app in your corporate tenant and apply a conditional access policy. The policy only applies to users and guests in your tenant.

⚠️ I’ll repeat ➟ your CA policies do not apply to users signing into your multi-tenant app in their own tenant.

So, what is the general rule of thumb that Azure AD admins and cybersecurity teams should follow?

If the app is from a vendor/SaaS provider:

✅ Add the app to your tenant from the Azure AD Application Gallery

✅ If the app is not in the gallery, you as the customer can request the vendor to get their app listed on the Azure AD app gallery

✅ If app gallery is not an option, request the vendor to create the app in their own tenant. Use the admin consent model to add the app to your tenant.

✅ If the only option provided by the vendor is to create the app in your tenant, push for the vendor to allow you to create a single tenant app.

If the app is developed by devs in your org and is only meant for users in your own org.

✅ Ask why the dev needs this to be a multi-tenant app?

✅ Ask if the devs have implemented appropriate checks to prevent sign-ins from other tenants.

There are many valid scenarios for creating multi-tenant apps in your tenant, including

✅ You are a SaaS vendor or ISV and you create and publish apps that Azure AD customers can consume

✅ You manage multiple Azure AD tenants in your org and you need a single service principle (workload identity) to access the other tenants (e.g. automate DevOps tasks across your tenants)

Here are some further reading on the topic of multi-tenancy. These are meant for devs however its good reading for admins to appreciate what it takes to build a least-privilege multitenant app.

👉 https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/

👉 https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-convert-app-to-be-multi-tenant

Note: This MSRC blog post provides additional guidance on how you can review the multi-tenant apps in your tenant and switch them to a single tenant app if multi-tenant is not a requirement.

Guidance on Potential Misconfiguration of Authorization of Multi-Tenant Applications that use Azure AD - MSRC Blog - Microsoft Security Response Center

Use a custom app for Graph PowerShell delegate access

1 minute read

If you want to follow the least privilege model for the applications in your Azure AD tenant, you might be concerned about consenting to many permissions scopes to the Microsoft Graph PowerShell app over time.

To avoid this, you can register your own app for use with Microsoft Graph PowerShell. This allows you to have more granular control.

Here are the steps to go about setting it up.

  • Browse to Entra > App registrations [adappreg.cmd.ms] > New Registration
    • Name: Microsoft Graph PowerShell - High Privilege admin use only (<- Give a meaningful name)
    • Account type: Accounts in this organization directory
    • Redirect URI:
      • Select Public client/native from the drop down
      • Uri: http://localhost
    • Click Create

That’s it!

Now you can use this app instead of the default one by connecting with

Connect-MgGraph -ClientId <Your new app clientid> -TenantId <your tenant id>

Here are a few screenshots to help guide you.

Screenshot showing how the app should be created

Remember to use the ClientId and TenantId parameters when signing in.

Screenshot signing in with the new app in PowerShell

Restricted user access

I would also recommend limiting the users that have access to these Graph PowerShell applications. To do this browse to the Enterprise Applications [adapps.cmd.ms](https://adapps.cmd.ms] blade, select the app and in Properties set Assignment required? to Yes. Then grant access to the required folks from the Users blade.

Windows PowerShell 5.1

The steps above will get you working with PowerShell 7, which is what you SHOULD be using. In the unfortunate event that you are stuck with Windows PowerShell 5.1 you need to do one more thing.

  • Open the app you just created in App registrations [adappreg.cmd.ms]
  • Select Authentication
    • Check https://login.microsoftonline.com/common/oauth2/nativeclient
    • Click Save