Azure DevOps Repos REST API access using service principal multi-tenant app
Asked Answered
R

1

2

I faced an access issue when I tried to access Azure Repository information in one tenant using app credentials from another tenant.

Flow inside only one tenant (works).

  1. I have created a multi-tenant app registration in "Tenant_A" in Azure Portal Entra ID. The link for admin consent looks like this:
    https://login.microsoftonline.com/common/adminconsent?client_id=<MY_CLIENT_ID>

  2. I have an Azure DevOps organization "OrgInTenant_A" connected to my Microsoft Entra Default Directory (where the app is created).

  3. I have consented my app using the link mentioned above and added this app as a service principal user to my Azure DevOps Repos "OrgInTenant_A" organization and granted this service principal Basic access and "Project Administrator" role to my project.

  4. After that, I can obtain an access token using only the credentials of my app (Tenant ID, Application (client) ID, and Client Secret) programmatically using NodeJS script and the '@azure/identity' package. The scope I am using for getToken(...): 499b84ac-1321-427f-aa17-267ca6975798/.default

  5. With this access token, I can get a project list from Azure DevOps "OrgInTenant_A", and also I can clone the repository via git CLI using this token.

So everything works as expected up to this point!

Multi-tenant flow (not works).

The interesting part begins when I try to access projects/repos in another tenant.

  1. I have created a second "Tenant_B" using another Microsoft account. Did the same admin consent using the same URL from Step 1.

  2. I added the service principal as a user in "OrgInTenant_B" Azure DevOps Org in "Tenant_B" with the same access settings. "OrgInTenant_B" connected to Default Directory in "Tenant_B".

  3. When I try to access projects/repos from "OrgInTenant_B" in "Tenant_B" using app credentials from "Tenant_A", I get the error:

"TF400813: The user '<SOME_UUID>' is not authorized to access this resource."


Questions:

  • Q1: What have I missed? What additional steps should I take, or what other permissions/roles/etc should add and where?
  • Q2: "<SOME_UUID>" - what does this ID represent? It does not correspond to any numbers that I have: not a Tenant/Client/Secret ID, not an Object ID of the consented app in "Tenant_B".
  • Q3: Is it possible at all to access projects/repositories in "OrgInTenant_B" using multi-tenant app credentials from "Tenant_A"?
  • Q4: Can it be related to the fact that Azure DevOps API permission has only "Delegated permission" scopes and "Application permission" scopes are disabled? But How it work with only one tenant scenario and does not work in the multi-tenant scenario?

Additional info and steps that I already tried:

  • I have enabled the toggle Third-party application access via OAuth in my "OrgInTenant_B" Settings -> Security -> Policies.

  • I can find the consented app in Azure Portal in the Enterprise Application tab in "Tenant_B", but only when I clear the Application type filter. So I can not see this app when the Application type equals Enterprise Application like in "Tenant_A").

  • I already granted admin consent for Default Directory in the Security Permissions tab for this app in "Tenant_B".

  • My app requires scopes:

    • Azure DevOps: vso.code_full
    • Azure DevOps: vso.project
    • Azure DevOps: user_impersonation
    • Also a lot of scopes from Microsoft Graph for test purposes
Ramonaramonda answered 28/11, 2023 at 13:45 Comment(0)
A
2

The multi-tenant application service principal is certainly able to access resources in Azure DevOps.

For your issue, it is most probably that you did not correctly configure the multi-tenant application service principal to your "Tenant_B".


To configure the multi-tenant application service principal:

  1. Ensure you have the any of the following admin roles in the tenants.

    • Global Administrator
    • Privileged Role Administrator
    • Cloud Application Administrator
    • Application Administrator
  2. When using the consent URL,

    https://login.microsoftonline.com/{organization}/adminconsent?client_id={client-id}
    

    ensure you have provided the correct values to.

    • {organization}: The tenant ID of your "Tenant_B".
    • {client-id}: The client ID of the service principal you created in "Tenant_A".
  3. After above steps, the service principal should be created and visible in "Tenant_B".

For more details, you can reference the following documentations:


To use the service principal to access resources in "OrgInTenant_A":

  • Add the service principal as a user into "OrgInTenant_A" and assign the required permissions to it.
  • When generating the access token, you should provide the tenant ID of "Tenant_A".

To use the service principal to access resources in "OrgInTenant_B":

  • Add the service principal as a user into "OrgInTenant_B" and assign the required permissions to it.
  • When generating the access token, you should provide the tenant ID of "Tenant_B".
Andean answered 29/11, 2023 at 3:20 Comment(1)
Thank you so much for the answer! It seems like I have done almost everything correctly except the last part. I was generating a token for "Tenant_B" using DefaultAzureCredential, and I have AZURE_TENANT_ID in the .env file from "Tenant_A". When I changed this ID to "Tenant_B", everything started working as expected! But the weird thing is when I remove AZURE_TENANT_ID from the env variables at all, it also works. Should it work without the tenant ID specified?Ramonaramonda

© 2022 - 2024 — McMap. All rights reserved.