Pass AD user authentication to Azure REST API calls to provision resources - azure

I'm creating a React App that requires authentication into Azure Ad. This is simple enough through the Adal libraries. When a user now requests my app, they are redirected to the login page first to authenticate.
The next step in my app, is for logged in users to be able to create various Azure resources, e.g. VM's through a simple form page in the app. For this, I'm looking at using the 'azure-sdk-for-node'. My problem, is that users can belong to different subscriptions based on their region globally. There are cases that users are in more then one subscription and have the rights to create resources in whichever subscription they are assigned to.
I'm not sure how to do this with the node SDK, as you only have three methods to authenticate calls:
Basic authentication (requires username/password which is redundant because they are already signed in
Interactive login (same as above)
Service Principal (everone uses the same 'account' to call the REST api's.
Not sure what's the best way then to do this?
https://github.com/Azure/azure-sdk-for-node

Related

Azure Identity SDK (JS) How to Authenticate to User's Azure Account

I am designing my first dev tool with the Azure SDK (JavaScript), and I am having a difficult time understanding how to authenticate users in production so the dev tool can access the user's Azure account. The tool is going to retrieve metrics from all of the user's Azure Functions in their tenant to display React component graphs based on those metrics over time. The app will be run locally with an npm run command.
My entry point for using Azure Identity in my app was this blog post (https://devblogs.microsoft.com/azure-sdk/authentication-and-the-azure-sdk/). I like the way the DefaultAzureCredential is working in development, using the tenant for whichever developer is running it by using the AzureCliCredential. I want a similar functionality for production, but for the browser instead of Azure Cli. In other words, if a user is already logged in to Azure Portal, it will get a credential for their tenant. How do I go about this?
One of the things I tried was opting into the Interactive Browser of the DefaultAzureCredential as described in that blog post. But even though, I could see the browser method in the src (https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/identity/identity/src/credentials/defaultAzureCredential.browser.ts), I couldn't figure how to opt into this when using the actual SDK. I couldn't find that method in the npm package in Azure Identity, and the documentation (https://learn.microsoft.com/en-us/javascript/api/#azure/identity/defaultazurecredentialoptions?view=azure-node-latest) didn't help me either. If this is the correct option for my use case, I would like to understand how to opt into it and use it.
Another thing I tried was implementing the InteractiveBrowserCredential. As long as I pass in a redirectUri with a port not already being used by my app, it did open another tab to tell me to login to the Azure Portal if I am not already logged in. This is exactly the user experience I would want in my app. However, after logging in the credential didn't actually do anything. The credential returned actually has a client Id equal to the application Id (04b07795-8ddb-461a-bbee-02f9e1bf7b46) of Azure CLI (https://learn.microsoft.com/en-us/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in) for some reason. This led me to look into the Interactive Browser Credential and find out that it is using the Authorization Code Flow (https://learn.microsoft.com/en-us/javascript/api/#azure/identity/interactivebrowsercredential?view=azure-node-latest). This flow doesn't seem right for my use case, since I have to register my app. I am not trying to grant users access to my app, but access to their own Azure account. Is InteractiveBrowserCredential what I should be using?
Next, I looked into all of the different authentication flows. None of them seem quite right for my use case though. The closest one I found was the client credentials flow (https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow) since I am authenticating the user to their own Azure account and not my app. However, even this one doesn't seem quite right because when I looked up how to implement that flow with Azure Identity (https://github.com/Azure/azure-sdk-for-js/blob/main/documentation/using-azure-identity.md#clientsecretcredential-and-clientcertificatecredential) I found out that I have to pass in the tenant Id. But the app won't know the user's tenant Id of the user before they log in. Which flow is right for this use case?
It seems like there is a gap in my understanding. How can I use the Azure SDK to implement an authentication flow that authenticates the user to their own Azure tenant (not authenticates them to my app) through the browser?
Thank you ShwetaMathur for answering this question in Q & A. Posting the same here to help Stack Overflow community members.
To access your application by Azure AD users, your application should also need to register in Azure AD.
Once your application is register, you can acquire the access token based on different OAuth flows which is needed to call various resources(Users in your case) or protected API based on your scenario.
Azure Identity TokenCredential provide various flows to obtain an access token based on different scenarios.
InteractiveBrowserCredential is one way to launches the system default browser to interactively authenticate a user and obtain an access token.
Using access token, you can retrieve user’s info or access any other resource in Azure tenant. The InteractiveBrowserCredential uses Authorization Code Flow to authenticate users for browser based applications and to access resources further.
Client credential flow is OAuth flow commonly used for server-to-server interactions that usually run in the background, without immediate interaction with a user and help to acquire the token and call protected web APIs.
Complete reference

Azure ADB2C access without a user

I am using an Azure ADB2C tenant to sign-up/in users with custom policies and rest api claims exchanges. This works fine.
Now I would like to start a service (daemon) that runs in a cloud environment for each user that signs-up with my service. This background service will access resources on other servers. Accessing these resources require a token and the service should only have access to the resources that the user has (i.e.: the access token used by the background service should also include the custom REST API claims). For the common users, this is taken care of by my REST API claims server, which enriches the token in such a way that it gives users' access only to the allowed resources.
I have found this page describing how to get access without a user. But this page assumes that the background service is a single instance that has access to all users' data that it needs. My background service is a 1-to-1 mapping to the signed up user.
Ideally this is how I see it working:
A new user signs up.
My REST API claims exchange gets called for this user.
Call Azure ADB2C to create a token for the background service. (Token should also contain my custom claims)
Start a new instance of the background service using the token created at step 3.
Return the custom claims for the new user.
This will happen for every new user, so every user in my system will have a corresponding background service running in the cloud.
Is this possible with Azure ADB2C? If yes, how?
The link you provide to get access without a user is only suitable for calling ms graph api and not for calling custom api.
If you are calling ms graph api, then you can indeed use the daemon-based client credential flow to obtain an access token (that is, without user involvement). This flow is usually used in Azure AD, but if it is used to call ms graph api, then it is also applicable to Azure AD B2C.
But if you are calling a custom api, then you must use a user login flow. Azure AD B2C obtains tokens in a different way from Azure AD. To use Azure AD B2C, you must first create a policy to enable users to sign up and sign in to your application.

When to use OBO with Azure

I want to develop a SaaS application on Azure and deploy to the Azure marketplace. This app will be able to obtain information about the user's network. (for instance VNET information). Ideally I would like to have a single-page application that would authenticate with the user who subscribed to the app, and then make calls on a backend API tier, which would make calls to Azure management API endpoints.
The Azure docs layout a number of scenarios of how apps could interface with AD. how-to guides
I believe what im trying to do most closely matches the "Build a web app that calls web APIs" flow, which is an example of OBO. My question is, is that really describing what im doing? Is "calls web APIs" really an example of invoking APIs on the microsoft azure platform?
So my understanding is that I would develop my own API app, that would accept requests from my client browser code, which would contain an oauth token, and then the API layer would derive another token to pass onto the Azure API layer?
Im trying to keep the architecture as simple as possible, but im afraid I may be misinterpreting the Azure docs.
OBO (On-Behalf-Of) allows you to exchange an access token that your API received for an access token to another API.
The important bit is that the access token must have been acquired in the context of the user and must contain user information.
The new access token will then also contain this user's info.
So it allows your back-end API to call Azure Management APIs on behalf of the current user.
This means your API can't do anything the current user can't do.
It is limited to the user's own access rights.
The other option for authentication is to use client credentials authentication,
where your back-end API uses only a client id + certificate/secret to authenticate.
In this case the token will not contain user information.
To enable this approach, the target organization's users would have to assign RBAC access rights to your app's service principal, so it can act by itself.
You could also build a flow in your app where you setup these RBAC accesses on behalf of the current user.
Personally, I would prefer to use delegated access (OBO) whenever possible, as it will block the user from doing things they cannot do.
Though on the other hand, service principal-based access allows the organization to control your app's access better.

Secret Key / Access Key with Azure Active Directory, enterprise application, app roles?

We are working on WEB APIs and want to integrate Azure AD for AuthN and AuthZ. We have successfully integrated the same. We have created enterprise applications, custom roles, assigned users for the same.
Now we need to allow access to APIs with AWS like keys (Secret / Access keys). Individual user can generate their own keys and store those in Azure AD so that when those keys are used, user can be authenticated.
I didn't find any way to achieve this using Azure AD. Any suggestions around same are welcome.
Meanwhile I have gone through custom store for keys. Please refer link : https://www.codeproject.com/Articles/1228892/Securing-ASP-NET-CORE-Web-API-using-Custom-API-Key
Thanks in advance.
Azure AD authentication uses tokens.
So any app wishing to call your API must authenticate with AAD and acquire a token for the API.
If these users are making apps within your organisation, then they can register their app in your AAD and require access to your API. They will create and manage their own keys.
If on the other hand these users are making an app for another organisation, you'll have to make your API a multi-tenant app.
And you'll need to have an on-boarding page in your API through which you will redirect their admin/user to the AAD login page, where they will consent to any permissions your API requires.
After this a service principal is created in their tenant.
Then they can register their client apps and require access to your API.
They will have full control which permissions they want to assign to each app, what roles to give to users etc. But of course the tokens will contain their tenant id so you can filter access on that.

Requesting Azure AD permissions on-demand

We have a multi-tenant single page app (and backend) that uses Azure AD for authenticating users. We'd like do queries to customer's Azure AD for retrieving groups but make it an opt-in behavior for customers (tenants). The reasoning behind that is that not all customers necessary need the functionality and would rather not grant us access to their AAD unnecessarily.
Is there some way of implementing this with Azure AD?
I've been trying to test with different OAuth /authorize calls with resource IDs and scopes but mostly I end up with "AADSTS65001: The user or administrator has not consented to use the application with ID ''. Send an interactive authorization request for this user and resource." error. Configuring the web app or backend to require the permission would surely fix the error but that will also make the approval of it mandatory for all users of the app.
Is there a way of using the authorize/consent API to request access to a new application on-demand?
An ugly work-around that should work would be to have 2 client IDs and 2 backend IDs with different permissions but ADAL.js doesn't seem to be designed to work with multiple Client IDs (it's singleton, for starters). Also Application Permissions should of course work but I'm not sure how much of those are required to search for groups.
Is there a way of using the authorize/consent API to request access to
a new application on-demand?
Do take a look at Azure AD v2.0. With their incremental & dynamic consent model, it is possible to do so though I am not sure if this specific functionality (managing groups) is available there.
I had a discussion with Azure AD team member recently about this (as we are also facing the same problem) and he suggested that we take a look at this.
Essentially the way things work in Azure AD v2.0 is that you start with basic set of permissions (like sign in, read profile etc.). Then when some tenant need specific permission, you essentially ask them to grant those permissions to your application at that time only. What this means is that different users in your application have granted different permissions to your application.
If you are using MSAL, and looking for a way to dynamically change your scopes before authenticating, have a look at this: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/configuration.md#msalguard---dynamic-auth-request
More here: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/configuration.md#platformbrowserdynamic

Resources