I'm sure most everyone has solved this but I'm putting some answers here for posterity as I know that as of late '23, not every MSP has been forced over to GDAP.
One existing answer mentioned GDAP but didn't provide much clarity or practical guidance.
Basically, you need to change how your registered application gets permissions to operate on client tenants. The conversion process works fine but involves jumping through hoops and some trial and error. Here's an overview of the process and some notes at end.
Overview of Steps
- Create a service account and group in your own tenant.
- Call the service acct something like gdap-automations@[MspTenantDomain].
- Call the group something like grpGdap (or whatever).
- Add the service account to the group Agent Admins in your MSP tenant AAD.
- Log in as the service account to make sure MFA is configured (MFA is required).
- Give the service account Global Admin role temporarily (use PIM for this ideally so the role falls off automatically - it's not needed long term).
- Modify your registered application by adding the equivalent Delegated permissions, corresponding to those that you may have added in the past as "Application" permissions. You don't need to delete the existing ones, but the Application level permissions won't do anything for us in the GDAP model, just the Delegated permissions.
- Go into Microsoft Partner Center, select a random customer, and select "Admin Relationships". You'll probably have an existing relationship here, but it will likely be insufficient for what we need. Create a new Admin Relationship. Call it GDAP or something.
- Set the relationship to Auto-Extend, set expiration to 90 days or more, add the Entra permissions of Cloud App Admin or Application Administrator (at least).
- Add the custom group from step 1b to this relationship.
- Get the invitation URL for this new relationship and then grant it by logging into the customer tenant as a global admin (just like you may have done to grant your delegated admin permissions in the past).
- Now that the admin relationship is active, you need to run some PowerShell scripts as a POC, or just start modifying your application to work as follows:
- Get a refresh and access token from Partner Center using the service account we built in Step 1a.
- Use the access token to register an application in the customer tenant mirroring your own automation application. This will create the registration and propagate the same API permissions (as long as they are delegated not application, remember? App-style perms will not show up in the created app).
- Use the refresh token to request an access token on the customer tenant.
- Use this access token when making Graph API calls against the customer tenant.
Some References
Good, clear examples of the code in ste p 10 in PowerShell can be found here: https://tminus365.com/my-automations-break-with-gdap-the-fix/
While the above link has some really good instructions, I found that reading the Microsoft info alongside it helped me understand what was going on a little better. This page in particular was helpful: https://learn.microsoft.com/en-us/partner-center/developer/gdap-and-secure-application-model
Powershell vs. REST
So all the PowerShell stuff in step 10 is a good PoC, but if you have an app where you're using Graph REST API it's pretty easy to convert over. The POST request to get a token uses the same endpoint as you used to use: https://login.microsoftonline.com/{{tenant}}/oauth2/v2.0/token
but the body of the request changes slightly:
- the value of the grant_type property will now be "refresh_token".
- you'll need a new property named "refresh_token" whose value is the refresh token from step 10a.
- Other properties like client_id, client_secret, and scope are the same.
The access token returned from this request will now be fed into your other existing requests for tasks like getting users from customer tenants. You just replace the token you had been using earlier with this new access token. Everything should work assuming you got your API permissions correct for the calls you're making.
Pitfalls
- Make sure the registered automation application in your own tenant has a defined redirect URI. If this hasn't been set up, you'll get the error message telling you to do it when trying to run the PowerShell script for the Partner Center stuff. Just go to your app registration, Overview, and there should be a link there named "Add redirect URI" or similar. Add app type of Web, and then just use http://localhost:8400 or whatever.
- Make sure your registered application is using Delegated API permissions, not Application API permissions. Only the delegated perms will propagate to the app registration that gets created in the client tenant.
- Make sure your Admin Relationship has Cloud App Admin or App Admin permissions - this is what lets us create the application in the client tenant.
I wouldn't be surprised if I've missed something, but hopefully this helps someone else. Of course, your application should have some mechanism to save the refresh token and keep it updated on a regular basis to avoid having to go through the sign-in process with the service account multiple times.