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.
Related
I have had been struggling to make my Azure Active Directory Oauth 2.0 Client Credentials Flow work with API Management. but I get authenticated via postman too. But in return I do not get any access token just a bunch of HTML. How can I fix this? The settings of the applications are exactly as per the documents including the validation of JWT Policy.
Basically I want my client apps to connect with my azure API's using Oauth 2.o without any consent using provided client id/secret. I'm trying to set this up for now with ECHO API provided out of the box with API Management console.
thanks
Postman Access token Error Screen
To use application permissions with your own API (as opposed to Microsoft Graph), you must first expose the API by defining scopes in the API's app registration in the Azure portal. Then, configure access to the API by selecting those permissions in your client application's app registration. If you haven't exposed any scopes in your API's app registration, you won't be able to specify application permissions to that API in your client application's app registration in the Azure portal.
For an example, if I sent scope parameter with custom name like https://testwebapp.in/.default without configuring same as application ID URI in Azure AD then is an expected behavior and you will get error AADSTS500011.
scope parameter in the request should be the resource identifier (application ID URI) of the resource you want, affixed with the .default suffix. For the Microsoft Graph example, the value is https://graph.microsoft.com/.default. This value tells the Microsoft identity platform that of all the direct application permissions you have configured for your app, the endpoint should issue a token for the ones associated with the resource you want to use.
Reference: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#application-permissions
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 feel like I may be going a little mad here.
I have basic architecture that features a frontend react app (SPA Auth) which communicates with a backend GraphQL Nodejs API service (Protected Web API Auth), hosted in Azure and authenticating with Azure AD.
Frontend access token requires User.Read access to azure graph, and access to Backend exposed scope
Backend exposes an API and single scope for access
Backend also requires User.Read access to azure graph on behalf of the user
I have been trying to configure the authentication to use the On-Behalf-Of Flow.
The react app successfully retrieves an access token using it's own app registration details
The access token is supplied to the backend service with each GraphQL request
The backend service verifies the access token provided to it
The backend service requests it's own access token via the On-Behalf-Of grant_type urn:ietf:params:oauth:grant-type:jwt-bearer
This all works EXCEPT I cannot get past this issue -
The user or administrator has not consented to use the application with ID '9b56c153-be42-499a-a41a-20176ed2ce69' named 'service-cbcity-api'. Send an interactive authorization request for this user and resource.
Basically I have not been able to successfully configure the app registrations and token requests to ensure that when the backend requests it's token it is allowed to call User.Read on behalf of the originally authenticated user.
In the On-Behalf-Of documentation it states the following regarding using /.default scope -
/.default and combined consent
The middle tier application adds the client to the known client applications list in its manifest, and then the client can trigger a combined consent flow for both itself and the middle tier application. On the Microsoft identity platform endpoint, this is done using the /.default scope. When triggering a consent screen using known client applications and /.default, the consent screen will show permissions for both the client to the middle tier API, and also request whatever permissions are required by the middle-tier API. The user provides consent for both applications, and then the OBO flow works.
I have tried all sorts of combinations of configuration in the App Registrations as well as different combinations of scope requests and I simply cannot get this to function as expected; the prompt doesn't seem to include the combined consent.
The only way I have gotten it to function is by manually providing admin consent to the Backend app for User.Read, this just seems like a hack and I would prefer to correctly configure this to ask for users consent.
If anyone has configured something similar before (seems like an expected use case) please let me know how you got it working, including configuration like
App registration config for Frontend service (eg api permissions set)
App registration config for Backend service (eg exposed scope, api permissions, authorized client applications)
Scopes requested on various auth requests
At this stage I am going to have to revert to possibly using the one App Registration and sharing the same access token between frontend and backend, even though personally this seems like a poorer solution to me.
Figured it out, my main issue was that I confused known client applications list with Authorized client applications.
The Authorized client applications is present in the UI and is configurable from the Expose an API area -
However this is different from known client applications which is a setting only found if you edit the manifest -
The key pieces to this puzzle are -
Add your frontend app client id to the knownClientApplications in your backend app registration manifest
When doing login with the frontend app your scope needs to be {{api_clientid}}/.default, where {{api_clientid}} is your the client id of your backend app registration
This will present the API Permissions you have configured in the backend app registration to the user at time of consent, and it will permit your backend process to retrieve an AccessToken using the OBO flow.
For what it's worth, this is the tutorial that helped me realise I needed to update the manifest and gave me guidance on the exact OAUTH request format -
https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/tree/master/2.%20Web%20API%20now%20calls%20Microsoft%20Graph#how-to-deploy-this-sample-to-azure
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.
Is it possible to secure a Web API in an App Service within Azure, using the built in Authentication/Authorization options and at the same time access it using the OAuth Client Credential Grant flow?
I have an app service being authenticated with Azure AD B2C. In that B2C tenant I have the web app/API registered and authentication working fine for using the web app.
I added a scope in the Published Scopes section of that AD B2C app and also added an App ID URI for that scope.
Then I created another App (ClientApp) in the tenant to represent another service I want to provide access to the first API. I generated a Secret key for it and also in the API access section added the scope I had created in the other app.
Then in postman I get the token using the next
Grant type: Client credentials
Access token URL: https://login.microsoftonline.com/mytenantname.onmicrosoft.com/oauth2/v2.0/token (for some reason I have to use login.microsoftonline as the b2clogin domain doesn't work for this)
Client ID: The ID that appears in the app registered for the ClientApp
Client secret: The secret generated under the ClientApp
Scope: the App ID URI I added the the web app registration.
I successfully get the token, but when I try to access the web site using the bearer token with postman, I just get a 401.
It is not supported to use client_credentials flow against AAD B2C application registrations. Therefore you have to instead create an App Registration through the normal Azure AD Blade instead.
https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-apps#current-limitations
Then the App Service must accept tokens from 2 different authorities, which App Services cannot do with EasyAuth (Authentication enabled at the App Service configuration menu).
You would instead need to use a library that can accept tokens from multiple authorities. There is an example here:
Use multiple JWT Bearer Authentication
I've spent hours to find a proper solution.
This solution: https://stackoverflow.com/a/48657826/11721142 doesn't work with mine B2C setup (is almost ideal :) ). I had to change original:
"additionalLoginParams": [
"response_type=code id_token",
"resource=<AAD-app-id-for-your-webapi-webapp>"
]
To:
"additionalLoginParams": [
"scope="scope=https://xxx.onmicrosoft.com/{Guid}/all+openid+offline_access""
]
Where
https://xxx.onmicrosoft.com/{Guid}/all is your scope identifier defined in B2C API permisions
Then... finally I can call {frontend-app-domain}/.auth/login/aad and... see: access-token, id-token and refresh-token after {frontend-app-domain}/.auth/me
You can also provide required scopes like that: {frontend-app-domain}/.auth/login/aad?scope=<see scopes above>
Not sure if I understand it correctly, but it seems you are using a URL as scope. It works if you set the scope to the application id of the app service (you can find an enterprise application with the name of your app service in azure AD) instead of using the URL. (format: /.default)
I am still trying to figure out if it is possible to use the URL as scope...