Microsoft Graph API Multi tenant App-only auth scheme - microsoft-graph-api

Microsoft Graph API provides App-only authentication scheme, which works perfectly for the tenant that owns an application.
I have an Azure tenant and I created the application inside it following documentation guide. My application is now able to obtain an access token using https://login.microsoftonline.com/<tenantId>/oauth2/token endpoint, which allows me to query the Graph API for the users inside my tenant.
However, I would like my application to be able to obtain access tokens for other tenants as well. I suppose the external tenant owner should somehow insert my application inside their Azure tenant, apply certain app-only scopes and provide me the tenant id in order to query the token endpoint.
Is multi-tenancy possible for app-only authentication scheme?
How does the tenant owner insert my application into their Azure tenant?

Multi-tenancy for app-only is possible, however, in order to enable this you require two things:
You need to have a web UI for the tenant admin to sign in to and perform admin consent in order to, as you called it, "insert my application into their Azure tenant." Make sure you add the query string parameter &prompt=admin_consent.
More info on admin consent: https://azure.microsoft.com/en-us/documentation/articles/active-directory-devhowto-multi-tenant-overview/#understanding-user-and-admin-consent
Sample controller method that "signs up" the user for an app via admin consent:
https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-multitenant-openidconnect/blob/master/TodoListWebApp/Controllers/OnboardingController.cs#L33-L58
You will need to keep track of which tenants consented to your application so that you can enabled the code that runs the app-only flow for them. Unlike the delegated flow, you can't use the common endpoint (https://login.microsoftonline.com/common) but rather need to use the tenant specific endpoint for each instance or run of the app only flow.

Related

Is ClientCredentials flow access token only scoped to the specific tenant?

I wanted to confirm that the access token returned from the /{tenant}/oauth2/v2.0/token endpoint in client credentials flow (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow) is only usable to fetch data from the tenant that's specified in the request - i.e. it cannot be used to make an api call against another tenant who's admin has installed the app?
Can you confirm that my understanding is correct? Thanks!
From the documentation on Azure AD, yes. The token you obtained against a specific tenant is only good enough to communicate with endpoints that are configured/permissioned to access by that Tenant.
If you want a multi-tenant approach, you need to follow multi-tenant application flow which specifically mention about /commonendpoint.
From documentation
Update your code to send requests to /common
In a single tenant application, sign-in requests are sent to the
tenant’s sign-in endpoint. For example, for contoso.onmicrosoft.com
the endpoint would be:
https://login.microsoftonline.com/contoso.onmicrosoft.com. Requests
sent to a tenant’s endpoint can sign in users (or guests) in that
tenant to applications in that tenant.
With a multi-tenant application, the application doesn’t know up front
what tenant the user is from, so you can’t send requests to a tenant’s
endpoint. Instead, requests are sent to an endpoint that multiplexes
across all Azure AD tenants: https://login.microsoftonline.com/common

In the Microsoft Graph API, can an app with admin consent generate a token for a different user than the admin that approved it?

I have a multi tenant app registered in Microsoft Active Directory that uses admin consent to gain access to some application scope APIs in the Microsoft Graph API. It uses the /token endpoint to get a token, then calls those Graph APIs. It's working perfectly.
https://learn.microsoft.com/en-us/graph/auth-v2-service#token-request
Now I want to enhance my app to access some delegated (user) scope APIs, that do not allow access at application scope. My app is already configured to request these delegated permissions from the admin at admin consent time. But I'd like to call these APIs as each user in the directory, not the admin who installed my app.
Importantly, it is not feasible for me to have every user in the organization individually go through the OAuth flow for my app.
Is that possible?
Can I impersonate a user somehow by exchanging my application token for a user token?
Can the admin do something programmatically to generate tokens as individual users for my app as if they had been put through an OAuth flow?
No, you cannot convert an Application token to a Delegated token. The only way to act as a specific User is for that User to "delegate" those activities to your application.
Note that Admin Consent only provides consent to your App to operate within a tenant. It is destinct from, not a superset of, User Consent. In order to obtain a Delegated token, you need to receive both User and Admin consent.

Scopes Not Returned w/ Client Credential Flow

Can I define custom scope(s) and have them returned when using the client credential flow in Azure AD?
In my experiment, I configured 2 Azure AD applications, one for a Web API and one for a client (Web API Client A). I added a scope to the Web API but when requesting the access token via the client credential flow, the scope wasn’t returned. 🤔
Also, it only allowed me to request an access token when using .default for a scope, i.e. api://web-api-client-credential-flow/.default.
I ran across this Azure Feedback item: V2.0 Client Credentials Implement Scopes so it appears scopes aren't supported in Azure AD under the client credential flow?
What’s the point in giving my Web API Client A application permissions for that scope if they are not returned? How could the Web API know if the daemon application has that scope to perform the necessary action?
It would seem I would have to use application permissions?
Yes, you have to use application permissions.
Scopes aka delegated permissions only apply when a user is involved in the login process.
They allow you to act on behalf of a user.
Application permissions are sort of roles given to the application itself.
They only apply when doing client credentials authentication, where no user is involved.
You can define application permissions on the app via the Manifest in the app registration.
These can then be assigned to the client application.
When getting the token, you must use .default because you cannot change your app permissions dynamically.
You always get what has been granted already.
In the token the permissions will be in a roles claim.
Can I define custom scope(s) and have them returned when using the client credential flow in Azure AD?
No, but you can define application permission(s) via the manifest (definitely not as nice as the UI for delegated scopes) and have them returned via the client credential flow:
Then you can provide the client app permission:
Now when requesting a token with a scope of api://web-api-client-credential-flow/.default the "scopes" are returned in the roles claim. Sample JWT
Yes, you need to use api://web-api-client-credential-flow/.default for client credential flow.
And the application permissions will be returned in roles instead of scopes.

Suggest OAuth flow(grant type) or approach for below requirement

CompanyA is integrating with CompanyB where CompanyA's users will be buying devices of CompanyB.
CompanyA wants to show user's device(CompanyB) details on their app by calling
CompanyB's API on each user login.
CompanyA user is authenticated on CompanyA IAM.
CompanyA has to call register device when user tries to add an device first time.
Help me to identify the flow which i can use to query particular loggedin user's device only.
Do i need to create duplicate user account on CompanyB's IAM?
If i use client credential flow for API to API call, access token given by CompanyB is only provides access for API calls but it does not tell that on behalf of correct user only call is invoked.
Assume that CompanyA uses IdentityServer or any other provider as IAM and CompanyB uses Azure AD B2C.
Any other approach?
Please see below diagram,
You should be able to do this by making the Company B API multi-tenant in their Azure AD.
There are other options surely, this is just the first one that came to my mind.
Overview of the multi-tenant pattern
You would have to do admin consent on it to get the API's service principal in your Azure AD tenant.
The Company B API can give you an endpoint for doing this, redirecting you with the proper parameters to the authorization endpoint. How to send a sign-in request
After doing this, you should be able to then require permissions on the API from Company A API in your tenant (configured in Azure AD).
Configure a client application to access web APIs
After doing those things, your API should be able to use On-Behalf-Of grant flow to get an access token for Company B API.
Using Azure AD On-Behalf-Of flow in an ASP.NET Core 2.0 API
Company B API must be configured to accept access tokens from another issuer than their Azure AD of course.
In general multi-tenant scenarios, the issuer validation is commonly turned off.
If Company B wishes to have control over this, currently they will have to explicitly list the valid issuers.
Issuer values look like this: https://sts.windows.net/31537af4-6d77-4bb9-a681-d2394888ea26/, the GUID is your Azure AD tenant id.
The Company B API can extract the tenant id and user object id from the access token, and authorize the user to resources based on them.
I was looking at the AWS side and looks like they have something that could meet the requirements
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_federated-users.html
Was wondering if something like this exists in Azure.

How to configure users access to an API protected with Azure AD oAuth2

we have an existing "private/internal" API (non MS/Azure) that we would like to protect with oAuth2 provided by Azure AD, so, that the user's access to the API could be maintained by the Azure AD administrators.
It seems like the way to do this is to configure the API as a web application in the Azure AD. Then, users can get the authorization token from the Azure oAuth2 server and send it to the api (e.g. from a single page web app).
The API is expected to validate the scope, as per my understanding, received in the token and make a decision regarding the access.
But I can't figure out how to configure the API access scope in the Azure AD against a user. I.e. how to link a particular user and the API scope in Azure AD?
Can someone pls advise?
Thank you.
When you configure the app, you can enable "User assignment required" (in the Enterprise application Properties in the Azure Portal), and then configure which users or groups should have access.
Alternatively, if you need more granularity, you can use the Role based access, where you define roles in the application manifest (https://learn.microsoft.com/en-us/azure/architecture/multitenant-identity/app-roles), and then assign users to the different roles.
The [Authorize] attributes on the API controllers or on actions in them can then be configured with the required roles to access them, like so:
[Authorize(Roles = "Admin, Writer, Approver")] (any of the three named roles have access).
There is a sample which demonstrates this.

Resources