Microsoft Azure OAUTH2.0 - How can Multiple Source Clients call Azure OAUTH2.0 authentication - azure

I create an Azure APIM instance, register it as an app in AD and then create a OAUTH2.0 server under APIM which is setup using the clientid/secret key of above registered app. I make a dummy API under this APIM and then protect it with this OAUTH2.0 server. I also add a JWT policy on my api to look for a token and authenticate against the tenant-id.(No claims mentioned).
Now lets say, i have a Customer (ABC) and for that i register another app in AD and create its Clientid/secret. Customer generates its token with the help of token endpoint (this endpoint is given under Endpoints tab of AD app registration option). Customer calls the API with this token and it works.
Issue: I didn't give any permission for my APIM App in AD to the Client App in AD but it still works, which essentially means that any Clientid/secret from any app registered in AD will go through my JWT policy of the API. Because it is just validating against the tenantid. How can we stop this and make sure that it works only for a customer to which permissions is given.

This is one of the major things I mentioned in my recent article: https://joonasw.net/view/azure-ad-authentication-aspnet-core-api-part-1.
Any app of type Web App/API in Azure AD can get a valid access token for any API in that Azure AD tenant.
Even before any permissions are given to it.
This is kind of a "feature" I guess.
Quote from the article:
If you only require an authenticated user, any confidential client in your Azure AD can acquire an access token for your API and call it. So it is important that you implement the user_impersonation scope check at minimum.
Now since your caller will call your API as itself, you need to implement an App Permission.
You can see how those are defined here: https://joonasw.net/view/defining-permissions-and-roles-in-aad.
Then implement a check that ensures the roles claim contains the value of the app permission you defined.
The claim will be a string array, so some kind of contains check needs to be made.
This will then require that this app permission is granted the caller before they can make the call successfully.
If you also want to allow delegated calls (i.e. calls on behalf of a user),
then add an optional requirement for the user_impersonation scope.
Those are stored in a single string claim (scp), space-separated.
So for that one you'll need a contains check on the string.

Related

What is the flow of Azure AD based authentication in a project having SPA and web api?

I have a front end SPA (single page application) and back end api.
Each event in the SPA (like button click) invokes the respective api endpoint, and displays the result in the SPA.
I want to implement Azure AD based authentication so that only my Azure Tenant users are able to use the SPA/api.
Is the following flow correct approach to implementing such a feature:
User opens the SPA
User clicks on login button which opens Microsoft login popup
User enters Microsoft credentials in the popup, and if credentials are correct then user gets the JWT token
For every subsequent api request, the JWT token is placed in the bearer header
The endpoint validates the JWT token using Azure public key and rejects the request if token is missing or validation fails.
Is this flow correct and what is such a flow called?
There are several implementation steps that needs to be performed before you will have the flow that you have described:
User flow needs to be configured (Azure AD) - e.g. selfsignup allowed?
Backend and frontend applications needs to be registered (Azure AD)
Permissions and scopes needs to be added (Azure AD)
Backend API needs to be configured (e.g. API management) in order to validate the JWT token
I highly recommend to configure one of the Azure sample implementations end2end to get and idea of all the needed tasks: https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-authentication-sample-spa-app
The steps you outlined are correct.
An OAuth 2.0 "flow" outlines the steps to acquire a token from an Identity Provider (IdP). Since you are using a SPA, there are some restrictions on which flows you can use. A SPA can't act as a "Confidential Client" which is required for some flows. (Basically - the Client Secret required for the other flows would be visible in the browser network trace, so it's not "confidential".) The "Implicit Flow" used to be recommended for SPAs but it's less secure, so now the "Authorization code flow (with PKCE)" is recommended. Steps 2 & 3 in the question above are when you are executing the flow to acquire a token.
The authentication flow doesn't really address how you save and send the token to the API (#4 in the question), but the Microsoft Authentication Library (MSAL) helps with that - More information here - https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-overview
In Azure AD, you'll want 2 App Registrations - one for your SPA and one for your API. The API App Registration will need to "Expose an API" which really means to define a scope. Your SPA App Registration will need to Add an "API Permission" to the scope you defined from your API App Registration. (It will show up in My APIs.) This relationship is how #5 in the question is enforced.
Many of the steps for setting up authentication in Azure AD and Azure B2C are similar but Azure AD is designed for authenticating users that are part of your organization. Azure B2C allows you to build a set of users that aren't members of a particular Azure AD organization.

Difference between an application role and scope in Azure AD app registrations

I have created an API that is protected by OAuth using an app registration in Azure.
My app registration does not require assignment, but it exposes a number of roles that the underlying API verifies. To my understanding, this accomplishes almost the same thing as requiring approval.
So far I've only had user/group roles but now I've added an application role intended for integrators, and I want other application owners to be able to request permission to my API. I, as the API owner, would like to review these and either reject or consent to the request. E.g. I don't want everyone to be able to access my API within the tenant without my knowledge, just like all users/groups don't have access with me assigning them to a role.
The Role-based access control for application developers documentation makes it very clear who manages access:
...an application developer defines roles rather than authorizing individual users or groups. An administrator can then assign roles to different users and groups to control who has access to content and functionality.
However, if you create a role with allowed member types set to application, things are not quite as clear and it seems to behave more like a scope, where I give up any access management. Also from my limited understanding, a scope is used when the API needs to request data from the user (e.g. wanting to read their username), whereas a role is used for the application developer to control access to what they are developing.
This is what it looks like when I request access to my API from another app:
This same page mentions the following information:
The "Admin consent required" column shows the default value for an organization. However, user consent can be customized per permission, user, or app. This column may not reflect the value in your organization, or in organizations where this app will be used.
As well as:
Applications are authorized to call APIs when they are granted permissions by users/admins as part of the consent process
However, from my reading, it sounds like this never gives me, as the API owner, any insight into who has access to the API I own. I want to control application access the same way I'd assign a group or user to a role in the enterprise application.
Can this be achieved when it's an application on the other end, not a user? If not, how would I allow applications to integrate in a controlled manner?
I want to explain the feature Azure ad provided to protect web api here.
As you know, we usually use a token in the request header to let the api check if the request had correct permission to visit the api. Such as if the request from an allowed user role, right? So to whole progress should be authentication and authorization. Users sign in first then try to generate an access token to visit an api. Azure AD has similar architecture.
If you had a web application(e.g. web mvc app) you can integrate Azure AD into it then you can allow users use their user1#xx.onmicrosoft.com account to sign in. If you had a web api project, you can also integrate Azure ad and add [Authorize] attribute above the controller so that the incoming request should contain a correct Bearer token which we call it access token.
For Azure AD, we usually have 2 options, verification scopes or app roles. That results from the different flows we used to generate the access token. For example, we use auth code flow to sign in users and generate access token containing scp claim which is granted delegated api permissions. And we use client credential flow to let an application to generate access token containg roles claim which representing it's granted application api permissions. In short, when we set [Authorize] + [RequiredScope(scopeRequiredByApi)] in the controller, it allows requests from a user(user sign in the app and call api), when we set [Authorize(Roles = "roleRequiredByApi")], it allows requests from the application(no user signed in and the app call api by itself).
Here scopeRequiredByApi and roleRequiredByApi is what you exposed and then added to App Registration > Permissions. Just like Integrator you marked in the screenshot, it can be recognized as roleRequiredByApi because its type is Application.
And I'm afraid the roles is not what you want but to be honest what I said is what AAD can do for you... And I think the document I mentioned above about verification scopes or app roles will be a good sample for you.
The App Registration > Permissions section has a great feature for reviewing and limiting the access provided for your app registration:
enter link description here
In addition you should always define the scope of your permissions and limit it to the least required for your app. eg. NEVER set scope at the subscription level! Always set it at the resource group or lower.
Also note that Microsoft now provides Defender for APIs and you can use Sentinel to monitor a lot of the activities related to your app registration. Always always enable logging wherever possible and configure some method of alerting/reporting so you can better understand the activities for your app.

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.

Azure AAD App can access Admin App without granting permission using a token

I have two Azure Ad Apps:
1) Admin/BackendApp which guards my webapi
2) Consumer APP which will consume my webapi
When i try to access my web api using the token created using below URL passing the required ClientID, ClientSecret, Resource and grant_type=client_credentials
https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/oauth2/token
i get access token from above url and pass that token as Authorization header to my webapi i get successfull response without granting any access to/from admin/backendapp.
You need to check for valid scopes/roles in the token!
Define delegated/app permissions for the API in Azure AD and enforce them in your API. A global check that the token contains at least one valid permission is good to have.
An app in any tenant can acquire a token for your API as long as they know your tenant id and client id.
If you do not check for permissions, your API is vulnerable!
I have an article for how to define and enforce scopes in ASP.NET Core: https://joonasw.net/view/azure-ad-authentication-aspnet-core-api-part-1
Based on your query, the JWT token is created to call the API already have enough permission to call the resources. This looks like a normal scenario

Azure AD - Multi-Tenant with Daemon Service and Authorization Code Grant flow, can a target tenant generate a client_secret?

I am working with Azure AD through OAuth 2.0 protocol and also creating a Service/ Dameon application to handle the authentication process for Microsoft Graph SDK. For the service/daemon, I make a HttpWebRequest and pass along the client_id and client_secret to generate an access_token where I then can supply to the Microsoft Graph SDK.
I also have successfully created a corresponding service principal to the target tenant, in which an admin has granted permissions to the application using the authorization code grant flow. The application then shows in Overview -> Quick tasks -> Find an enterprise app, within the (portal.azure.com).
My question is there an approach where I can leverage the service/daemon approach while also allowing an admin from the target tenant to authorize the application, that would allow the target tenant to create a client_secret to pass which would be unique to that tenant?
Short answer is no. When an admin consents your multi-tenant app:
A Service Principal is created for it in their tenant
Permissions requested by the app are granted in that tenant
This means your app can now authenticate with its client credentials (id + secret) against their tenant as well. So the same keys work in all approved tenants.
What that means is your app is free to get an access token for any of them at any given time, no matter who is signed in. So it puts some responsibility to your app to keep data separated.
If you get an access token from https://login.microsoftonline.com/company.com/oauth2/token, the resulting token will contain that tenant's identifier. And APIs like the Microsoft Graph API will only give you data for that tenant with that token. So your app must make sure to only use a token that has a tenant id equal to the user's tenant id claim.
I would say that juunas' answer is 99% correct. The short answer is basically no, and the considerations he mentions are also solid.
But I believe that this would be technically possible under certain considerations. When the admin consents to your daemon service, a service principal is created in your customer's tenant. Service principals do allow addition of credentials that can be used as client secrets on a per-tenant basis. The thing is, there's not really a way to add a credential to a service principal programmatically from your app. You would have to get an administrator to run some script to add the new credential to their tenant's service principal.
Even if you went through all this, you would need to make sure that your service is also isolated on a customer/tenant basis. Security-wise, it's sort of pointless to create per-tenant client secrets if your singular daemon has access to all of the secrets.

Resources