I have an ASP.NET MVC Web Application running as a web app in Azure App Service. This web app calls an Azure Function via HttpClient from a Controller. Authentication/Authorization is configured in the web app with Azure Active Directory. I need the user to also be authenticated when a call to the Azure Function is made so that I can access the user Claims.
I tried to also configure Authentication in the Azure Function itself but this resulted in an "Unauthorized response" whenever I called the function from my web app.
Is there a way to make both the web app and the Azure function use the same Active Directory Authentication. So that when a user is authenticated to the web app, he does not need to authenticate again in the Azure function and all the User Claims would be available in the function itself?
I can think of three different approaches that would work.
Using Bearer token.
Create two separate application registrations, one for the web application and one for the function application. Setup the Authentication/Authorization feature for the respective applications, with both configured to require AAD access. Give the web application's AAD app registration permission to access the function application's AAD app registration.
To make sure that the access token of your web application is a JWT that can be used to contact your function application, you need to add additional login parameters to your web application. To do this, follow the instructions here, but instead set additionalLoginParams to resource=<your-function-app-registration-client-id>.
When a user makes an authenticated request to the web app, a header should be populated called X-MS-TOKEN-AAD-ACCESS-TOKEN which should be an access token with an audience of your Function application's app registration. This can then be used as a bearer token to the Function application API calls, which should satisfy the authentication/authorization requirements of the function application.
Using on-behalf-of flow
Create two separate application registrations, one for the web application and one for the function application. Setup the Authentication/Authorization feature for the respective applications, with both configured to require AAD access. Give the web application's AAD app registration permission to access the function application's AAD app registration.
Then, follow the on-behalf-of flow so that the web application can get an access token for an authenticated user user for the function application. There are several libraries that help with this flow. See ADAL if your app registrations are AAD V1 apps, or MSAL if your app registrations are AAD V2 apps.
Use Client-Directed-Flow (X-ZUMO-AUTH)
Create two separate application registrations, one for the web application and one for the function application. Setup the Authentication/Authorization feature for the respective applications, with both configured to require AAD access. Give the web application's AAD app registration permission to access the function application's AAD app registration.
To make sure that the access token of your web application can be used to authenticate against your function application, you need to add additional login parameters to your web application. To do this, follow the instructions here, but instead set additionalLoginParams to resource=<your-function-app-registration-client-id>.
When a user makes an authenticated request to the web app, a header should be populated called X-MS-TOKEN-AAD-ACCESS-TOKEN which should be an access token with an audience of your Function application's app registration, along with an id token in the header X-MS-TOKEN-AAD-ID-TOKEN. Make a POST request to https://.azurewebsites.net/.auth/login/aad with the payload
{"id_token": <id-token>, "access_token": <access-token>}. This will return a session token, that you can attach as an X-ZUMO-AUTH header to authenticate requests.
NOTE: The claims in this option will be the claims of the authentication token, which are not the claims of the identity provider like in the first two options. To get the same claims as the other options, set the application setting WEBSITE_AUTH_ZUMO_USE_TOKEN_STORE_CLAIMS to true.
Related
In a hypothetical scenario where I am using Microsoft Identity Platform for authentication, how would I also leverage it to control user permissions. Specifically, user permissions within the custom app. These permissions would not be related to other Azure resources or apps. For example, a web app that allows various different operators of a production plant to enable and disable different systems in the plant such as water coolers, air compressors, and conveyor belts. If I have a web app that allows a user to control these devices on a plant floor, how can I use MSAL to control the permissions to these different areas in the app? I only want user A to control coolers and compressors, and I only want user B to control the belts. I already know how to authenticate the users to the application using MSAL. I would prefer to control the permissions using something similar to AzureAD groups unless there is something better suited to this use case.
Scenario 1:
You have a Web App containing all the business logic. For this scenario you create one app registration for your Web App in Azure AD and define app roles for the various operators. You can name these app roles anything you want, for example: Coolers.Control and Belts.Control.
Example App Registration for Web App with App Roles (Image)
These roles can be assigned to individual users or groups in Azure AD at the Enterprise Application page. If you click on the "How do I assign App roles" on the app roles page, you will find the link that will redirect you to the Enterprise Application page.
If the user navigates to your Web App and signs in using the authorization code flow, the OAuth 2.0 authorization endpoint will return an Identity Token including a roles claim. You can use these roles in your web application to determine what areas the user is allowed to access.
More information: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-web-app-sign-user-overview?tabs=aspnetcore
Scenario 2:
But there is another option that you might want to consider. You could also create a Web App for UI logic only and place the business logic in a separate Web API. With this architecture you are able to allow multiple (future) client applications to use the functionality of the API, for example: native mobile apps or background apps.
For your scenario you would create two app registrations: one for your Web App and one for your Web API. You define the app roles in the app registration for the Web API and define a scope, for example: access_as_user, to allow delegated access. This scope needs to be assigned to the app registration for your Web App.
Example App Registration for Web API with Scope (Image)
In the Web App you use the access_as_user scope (including app id prefix) in the call to the authorization endpoint. If the user signs in and grants this scope to the Web App so it can call the Web API on behalf of the signed-in user, the authorization endpoint returns an Access Token. If the app roles are defined in the app registration of the Web API and assigned to the user, the Access Token will contain a roles claim. This token is meant for the Web API to authorize the user. When the Web App calls the Web API, it also sends this Access Token in the Authorization Header of the HTTP request. The Web API determines what the user is allowed to do based on the roles in the Access Token.
More information: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-web-app-call-api-overview
Additional information:
Because I had a similar question, I wrote an article about understanding scopes and app roles in Azure AD. The article explains how to use both scopes and app roles in a delegated access scenario, and how to use app roles in an app-only access scenario. I think this answers your question about how to control the permissions using something similar to Azure AD groups.
URL: https://cloudfirstapproach.com/understanding-oauth-scopes-and-roles-in-azure-ad/
I have React app on the frontend, I have registered it at Azure AD as REACT_AZURE and I use #azure/msal-react npm package to authenticate the user.
In order to protect my Express routes, I have registered another app at Azure AD as API_AZURE, and in "Expose an API" section I have added scope 'access_as_user'.
In REACT_AZURE app in "API permissions" section I have added permission for 'access_as_user'.
Now I can acquire access token for 'access_as_user' scope and make an API call to my express server.
In my protected route, I am using passport-azure-ad BearerStrategy to validate the access token, if it is valid I am authorized to get resources.
Is this the right flow? Do I have to register two apps with Azure AD? if not, how do I do it right?
Is this the right flow? Do I have to register two apps with Azure AD?
if not, how do I do it right?
Of course, your process is absolutely correct. You need to register two applications in Azure, one representing the client application and the other representing the api application. Then expose the api of the api application and add the client application to the api application. Then let the user log in to the client application to complete the authenticate and obtain the token, and use the token to call the api. I have answered similar questions before, you can refer to it.
But I’m not sure if you want to control which users can access the api based on the user role. If you only want certain users in the tenant to access the api, then you can add a step that is to create an app role and grants users who you wish to have access to the api. Then users in the tenant who are not granted the app role will not have permission to access the api. see more detailed answer.
I have two Azure Web Apps, one is a website and acting as the front-end, the other one is an API and acting as the backend. I would like to add authentication to this solution so only the front-end can access the backend. To do this, I've configured AAD authentication on the backend Web App with the express option that creates a new Azure AD application configured with the correct reply URL, API permissions (User.Read), etc. When I then navigate to the backend Web App URL, I need to sign-in with my Azure AD credentials.
Which steps do I need to take to restrict that so I as an user cannot login and only the front-end Web App can authenticate to the backend API?
For example, I can set the "Authorized client applications" on the Azure AD application of the backend API. However, I need to have an application ID to add an authorized client and I would like to use the Managed Identity of the front-end Web App for this, not a new and additional Azure AD application.
Any idea how to do this?
This is weird, if the login screen still appears, there is a problem with your code configuration, because the client credential flow does not involve user interaction.
I found a useful sample for your reference, this sample application shows how to use the Microsoft identity platform to access the data from a protected Web API, in a non-interactive process. It uses the OAuth 2 client credentials grant to acquire an access token, which is then used to call the Web API.
I'm trying to utilize built-in Azure App Service / Function AD authentication for access control. I'd like to use the same authentication for both the app service (which is a UI SPA app) and the function (HTTP trigger) so that users only need to log in once. My function app is a node.js function.
I do not need authorization, i.e. I just want to let certain users use the app service and function but they all have full access.
I have an app service set up with AD authentication which works beautifully by just enabling AD authentication from the portal and selecting "express" mode with the correct AD application. The AD app has implicit authentication flow enabled.
The problem is the function. How do I reuse the user's authentication status from the app service (i.e. the single-page frontend app) for the function?
Right now I'm at a point where I can obtain an authentication token using AAD MSAL but I cannot seem to be able to access the function with that. It doesn't help that there seem to be a dozen ways to use the auth (X-ZUMO, OAuth bearer, etc.).
To summarize, I'd like to just restrict access to SPA web app (app service) and function so that user is only required to login once. I can implement authentication code in the function but if I can get it to just Work(tm) without touching the function code, even better.
Assuming you already have the Easy Auth setup to your Web App, all you need to do is add your function app as as allowed audience.
More info: https://stackoverflow.com/a/53511688
I have an Angular 5 app and a web api app, both of which are hosted in Azure.
They have been secured with Azure AD at the website level e.g. no anonymous access is allowed.
When browsing the Angular site, it asks me to log in fine and I can access .auth/me which uses the local cookie to get token/claim information.
I now want to call the separate api but not sure how to go about it.
Both sites have an application in Azure AD, and I've set the client to have delegated permissions of 'Access to API'.
I've tried accessing the api using both the local cookie from the client (not sure if this would work) and the token returned .auth/me but neither work.
In my client manifest I have the following:
"resourceAppId": "3cddd33c-2624-4216-b686-7f8fa48f38cf", // api id
"resourceAccess": [
{
"id": "c2712c68-ea93-46d2-9874-61b807b19241",
"type": "Scope"
}
]
but haven't seen any additional scopes added to the claims, should it?
According to your description, you have both created the separate AAD application for your Angular app and your web api app, and configured the delegated permissions for your Angular AAD app to access the web api AAD app.
Based on my understanding, you are using the build-in App Service Authentication / Authorization for authentication, at this point you could do not need to change code on your app backend. You may have set Action to take when request is not authenticated to Log in with Azure Active Directory instead of allowing anonymous access, at this time your app service would directly redirect the user for authentication. After logged, your client could access https://{your-angular-app-name}.azurewebsites.net/.auth/me for retrieving the logged user info. For accessing your web api website, you could just send the request as follows in your angular client:
GET https://{your-webapi-app-name}.azurewebsites.net/api/values
Header Authorization:Bearer {id_token or access_token of AAD}
UPDATE:
That is exactly the route I'm trying to implement. One thing missing though, I had to add the client application id to the allowed token audience of the api app in Azure.
For retrieving the access_token, you need to set additional settings for the AAD provider in your Angular web app as follows:
"additionalLoginParams": [
"response_type=code id_token",
"resource=<AAD-app-id-for-your-webapi-webapp>"
]
Details you could follow this similar issue.
Use the EasyAuth server flow for logging, you would get the access_token, and you could leverage https://jwt.io/ to decode your token as follows:
Pass the access_token as the bearer token to your webapi web app, at this time you do not need to specific the ALLOWED TOKEN AUDIENCES.
At this time, you could invoke .auth/refresh against your Angular web app for refreshing the access_token, then you could use the new access_token to access your webapi web app.
I want roles included in the token so might have to stick with id?
If you want your Web API exposing access scopes to your Angular application which would be contained in the access_token as the scp property, you could follow the Configuring a resource application to expose web APIs section in this tutorial. Moreover, you could also follow Application roles.
UPDATE2:
You could follow Authorization in a web app using Azure AD application roles & role claims for detailed tutorial and code sample.
The usual approach would be to use ADAL.JS (or MSAL.JS with AAD v2 endpoint/B2C) to get an access token for the API.
ADAL.JS uses a hidden iframe to get an access token using the user's active session in Azure AD.
You can find an example Angular app here: GitHub.
An especially important part of the ADAL.JS configuration is here:
var endpoints = {
// Map the location of a request to an API to a the identifier of the associated resource
"https://myapi.azurewebsites.net/": "https://myaadtenant.onmicrosoft.com/MyApi"
};
The property name/key should be the URL for your API. ADAL-Angular detects calls to URLs starting with that, and attaches the correct access token to them.
The value should be the App ID URI of the API. You can find it from your API's App Registration from Azure Active Directory -> App registrations -> All Apps -> Your API -> Settings -> Properties.
You do need to enable implicit grant flow on the Angular app from the app registration for the SPA. You can find it from the Manifest.