Why does my bearer token not contain any app roles when using client credentials flow in a multi tenant scenario in Azure? - azure-active-directory

Using client credentials flow in Azure for app registrations that live in different tenants, results in bearer tokens not containing any app roles.
I created 1 app registration named "fake-web-api" in Tenant A for a web api and that app registration contains an App Role named "fakeAppRole".
I created a admin consent link by using the following format
https://login.microsoftonline.com/{tenant-id}/adminconsent?client_id={client-id}
I navigated to that link and signed in as an Admin of Tenant B and approved the consent.
This resulted in an enterprise application "fake-web-api" to appear in Tenant B's azure active directory.
I created 1 app registration named "fake-daemon-app" in Tenant B and added an API Permission to "fake-web-api"/"fakeAppRole".
I created a client secret for the "fake-daemon-app".
Now the code that I used to test this example is in here: https://github.com/Azure-Samples/active-directory-dotnetcore-daemon-v2/tree/master/2-Call-OwnApi
This example works perfectly fine for single tenant scenario, but when I tried to get it to work for muilti tenant scenario, I run into the problem that the bearer token that is returned to me does not contain any app roles and is therefor rejected by the "fake-web-api".
I expected the token that was returned to me to contain app roles, because it did contain app roles in the single tenant scenario.

In this case the issue turned out to be using Tenant A as the authority here:
.WithAuthority(new Uri("TENANT_A_DOMAIN_NAME"))
Since the app role was assigned in tenant B, we must use tenant B as the authority to see the role in the token.

Related

How to authenticate to personal OneDrive with Graph REST API

I'm trying to write an R package to let users access the files in their OneDrive folders from R. The API is Microsoft Graph.
Everything is working fine with OneDrive for Business (which is basically SharePoint under the hood, as I understand it). However, I can't get it to work with personal OneDrive.
Custom app registration, consumers authorization endpoint
When I use an app registration under my own AAD tenant, I get the following error from the consumers AAD authorization endpoint:
AADSTS50020: User account 'xxxxx#gmail.com' from identity provider 'live.com' does not exist in tenant 'Consumers' and cannot access the application 'd44a05d5-c6a5-4bbb-82d2-443123722380'(AzureRtest_cli) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
Custom app registration, 9188040d-6c67-4c5b-b112-36a304b66dad endpoint
From this page it appears that the token should be for the tenant 9188040d-6c67-4c5b-b112-36a304b66dad instead of the generic consumers. When I tried that, I obtained a seemingly valid token. However, talking to the https://api.onedrive.com/v1.0/drive endpoint results in a cryptic 401 error.
Azure CLI app registration, consumers endpoint
As a hack, I tried piggybacking off the Azure CLI's app registration. This fails with
AADSTS65002: Consent between first party application '04b07795-8ddb-461a-bbee-02f9e1bf7b46' and first party resource '00000003-0000-0000-c000-000000000000' must be configured via preauthorization. Visit https://identitydocs.azurewebsites.net/static/aad/preauthorization.html for details
Azure CLI app registration, 9188040d-6c67-4c5b-b112-36a304b66dad endpoint
Finally, I tried using the CLI app registration with this tenant, which also failed:
unauthorized_client: The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https://go.microsoft.com/fwlink/?linkid=2083908.
What are the exact steps I need to do to get to my personal OneDrive?
It turns out I had a bug in my code: I was using the tenant consumers.onmicrosoft.com instead of consumers. The process to communicate with Graph for personal OneDrive that worked for me was:
Use the authorization code flow as described here, with the following specs:
tenant: consumers
client id: for my custom app registration
scope: https://graph.microsoft.com/{scope} offline_access openid where the scope is one of those listed here
Use the API endpoint https://graph.microsoft.com/v1.0.
With regard to that last point, note that the documentation here is incorrect or at least outdated, as it still gives https://api.onedrive.com/v1.0 as the endpoint for personal OneDrive requests.

AADSTS50020: User account does not exist in tenant

I was able to register an app created by another tenant as an enterprise app of my own tenant.
I signed in to the app as a user, but I got the following error.
AADSTS50020: User account 'test001#testdomain001.onmicrosoft.com' from identity provider 'https://sts.windows.net/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/' does not exist in tenant 'testdomain002' and cannot access the application '55555555-6666-7777-8888-999999999999'(OneDriveAPIBrowser_test001) in that tenant.
The account needs to be added as an external user in the tenant first.
Sign out and sign in again with a different Azure Active Directory user account.
How can a user of another tenant use it without the application creator tenant performing any processing?
If the Azure AD app is registered in Tenant A and you have add it as an enterprise app into Tenant B, you should use a user from Tenant B to sign in.
In your case, if the registered app is in testdomain001 and added into testdomain002, you need to use a user from testdomain002. User "test001#testdomain001.onmicrosoft.com" is not allowed to sign in to the app in testdomain002 unless it is a guest user of testdomain002.
I tried the steps below and it worked for me.
Go to azure.microsoft.com
Select Free Account.
Sign in with your email.
It will detect that you already have a subscription and give you the option to use it.

Is there a way to get a list of Azure AD tenants from within a service principal?

I have created an app to get various information from Azure AD, such as users and groups. It lives in one of my tenants as an app registration. This works fine, but now I would also like my app to get a list of the ids of other tenants I have in my account.
I have given my app user_impersonation permission on Azure Service Management, and I am able to make
GET https://management.azure.com/tenants?api-version=2016-06-01 requests using my client credentials. However, when I make that call I get a list only containing the tenant that my app/service principal lives in. Is there a way I can use this API call to see other tenant ids from within my app?
Yes, you could do that with auth code flow instead of client credentials flow.
Since you are trying to get the tenants of your account rather than the app/service principal, you have to include the account information when doing the authentication.
Client credentials flow is App-only. Auth code flow is App+user.
See reference here to learn how to implement Authorization code grant (interactive clients).
And here is the document about OAuth 2.0 authorization code flow.
You need to Request an authorization code first and then Request an access token with the code from the previous step. Using this access token, you can list the tenants you have in your account.

Why do i need to create a Multi-Tenant App?

I have been doing some R&D on using the MicrosoftGraphAPI to fetch the skus subscribed by my organization.
I have created an app as described in the documentation. I did all the steps in the above link except 'Assign application to role'.
Using postman am able to get the oauth2 token by sending a post request using the link
https://login.microsoftonline.com/<mytenantid>/oauth2/token
with the client_id, client_secret, resource(https://graph.microsoft.com) and grant_type(client_credentials) parameters.
After this token is obtained I can fire a get request https://graph.microsoft.com/v1.0/subscribedSkus with the Authorization header set as Bearer {token} which will return the SKUs subscribed by my organization.
So far so good. :-)
Now the requirement is I need to fetch the subscribed SKUs by one of the client (let's say having the azure ad tenant id 'ABCDEFG') of my organization.
I can successfully do that by registering an app in the client's tenant 'ABCDEFG' with the same steps as above.
This approach is fine if my organization has say 1 or 2 clients.
However, if the client numbers are more than say 30 this approach of registering an application in each Azure AD instance is not feasible.
If the application that I registered in my organizations AAD was multi-tenant then how should it help me?
What will be the steps needed to obtain the access token for each tenant?
Can somebody assist with some detailed explanation?
Since you need application-level access, you would assign one of the Application permissions listed in the documentation for getting SKUs: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/subscribedsku_list.
Directory.Read.All, Directory.ReadWrite.All
In this case you should require the Read Directory Data (Directory.Read.All) application permission.
Then you mark your app as multi-tenanted.
Now then in order for another org to use your app, they will have to be on-boarded.
You will need some kind of page where their administrator can click a button/link to start using your app.
This should redirect the admin to:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=your-client-id&prompt=admin_consent&response_type=code+id_token&redirect_uri=url-where-to-send-user-back
Once they sign in, they will be presented with a consent screen, where they can approve the permissions that your app requires.
If and when they do that, they will be redirected back to your app (to the URL you specified) and you can use the Id token to know which Azure AD tenant registered.
During this process a service principal for your app is created in their tenant, and the required permission is granted to it.
This means you can then get an access token for their tenant from: (using the same credentials)
https://login.microsoftonline.com/their-tenant-id/oauth2/token
Remember that access tokens are specific to an Azure AD tenant, so you will have to get an access token for each tenant.
One thing I would like to point out is that you should instead try to use delegated permissions if possible.
The application permission given here gives quite large access to your app, and some admins might not use your service for that reason alone.
Delegated permissions are more complex to handle, but allow your app to act on behalf of a user instead of purely as itself.

Multi tenant Daemon office 365 app registration on consumer AAD by granting admin consent, Does it also require separate registration on consumer?

I am developing a multi-tenant Office 365 daemon that requires access to user calendars.
I have successfully registered in the company tenant (Tenant1) that has deployed this app using certificates and I am able to get access tokens.
Now I created a separate AAD tenant (Tenant 2) and logged in to daemon app using administrator account of Tenant 2, it prompted the Admin Consent screen and I provided consent. There was no errors returned.
When I tried to get an app token however, I am able to get a token but with blank permissions. If I call the Office 365 API using this token, I get a 401.
I was of the view that service principal objects should be created. Also I am unable to see this app in Tenant 2 app registrations.
Do all my consumers have to register this app manually in their AD tenant and modify application manifest file to add certificate details?
I am not sure about the benefit of multi tenancy if that's the case.
I found the follow in the Azure Active Directory documentation:
The following diagram illustrates the relationship between an application's application object and corresponding service principal objects, in the context of a sample multi-tenant application called HR app. There are three Azure AD tenants in this scenario:
Adatum - the tenant used by the company that developed the HR app
Contoso - the tenant used by the Contoso organization, which is a consumer of the HR app
Fabrikam - the tenant used by the Fabrikam organization, which also consumes the HR app
You do not need to have each tenant register your application. In fact, you shouldn't since having dozens (or hundreds) of unique App IDs floating around would only create headaches for you.
Each tenant does however need to execute the Admin Consent workflow. This will authorize the App ID you've registered on your end to access the scopes you've requested.
Generally, I recommend using the v2 Endpoint and the apps.dev.microsoft.com portal for registering your app. While you can also register your app in your own Active Directory, the portal makes it a lot easier to manage.
The general process is:
Register you application in the Registration Portal
Populate the "Application Permissions" in the Microsoft Graph Permissions section.
Launch the Admin Consent workload using https://login.microsoftonline.com/common/adminconsent?client_id=[APPLICATION ID]&redirect_uri=[REDIRECT URI]
Get a beer
A couple of tips:
The Registration Portal only supports MSA (i.e. personal) accounts at the moment. I'd suggest creating a new Outlook.com account for this purpose so you can easily share the credentials with folks who need them internally.
If you create a shared Outlook.com account, you should also set up forwarding rules for all of the interested parties internally. This is in case something should every go wrong or change down the road and you need to recover the account.
I wrote a v2 Endpoint and Admin Consent primer that you might find helpful. They assume you're using the Authorization Code flow but the concepts remain the same for Client Credentials.

Resources