We have an API hosted in Azure as an Azure Web App that we need to trigger via http on a schedule.
Our API requires a valid Azure AD Access Token be sent with each request.
Azure Logic Apps gives us the option to authenticate our request with Azure AD. However, we do not see the option of including scope in the request. If we send a request without specified scope or role, we get the following error:
System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.
How can we authenticate an http request from an Azure Logic App when scope/role is required in the access token by the API?
Thanks to #Skin for the suggestion!
Here is what worked for future visitors to this question:
Navigate to your Logic App in the Azure Portal > Select "Logic App Code View" > Add the following to "authentication":
audience: "api://<your api's clientId>"
clientId: "<your logic app's clientId>"
scope: "api://<your api's clientId>/.default" (this piece is not available in the interface)
secret: "the secret you generated for your logic app in your aad app
registration"
tenant: "your tenant id"
Parameter "Audience" is the scope. Depending on how you built your target api and what is expected there as audience in token you could probably have there somehting like: api://<yoru_app_id>/.default, but you should know it best.
E.g. when you call Graph MS your scope/resource/audience here is: https://graph.microsoft.com/.default, but different APIs have different needs for scopes.
Related
The situation
I have a backend API and frontend SPA app both hosted in Azure. I have protected both these app services with Azure AD Easy Auth using the same app registration. This works - if I try and visit the frontend application I am redirected to the Microsoft login page where I can login and if I visit the API I am returned a 401 (I can login to it interactively via /.auth/login/aad). In both applications, I can visit /.auth/me to retrieve the id_token and access_token among other things. My SPA app will query this endpoint to retrieve the id_token. It then uses this token to communicate with the API via a Bearer token. This communication works and I can successfully call endpoints in this way.
The problem I am facing is that after some time, the id_token stored and sent by the frontend becomes invalid. I assumed the frontend would ask the use to login again which would refresh the id_token but this does not seem to be the case. I did some digging and apparently I should be sending the access_token up instead of the id_token. However, my API rejects that with:
{
"code": 401,
"message": "IDX10511: Signature validation failed. Keys tried: '[PII is hidden]'. \nkid: '[PII is hidden]'. \nExceptions caught:\n '[PII is hidden]'.\ntoken: '[PII is hidden]'."
}
https://jwt.io also fails to verify the access token.
I am having a lot of trouble in finding resources/documentation for an SPA app and API which both use Easy Auth and how to get them to talk to each other.
Things already tried
Removing any Microsoft Graph permissions from the app registration
Changing the manifest "accessTokenAcceptedVersion" to 2 for the app registration
Enabling both "ID tokens" and "Access tokens" for "Implicit grant and hybrid flows" for the app registration in the Azure portal
Using cookie auth (sending up the cookie with requests from the SPA)
Exposing an API and adding a permission for it
What is the standard way of authenticating a frontend and a backend when both are protected by Azure Easy Auth? Should I be using the access_token or id_token to authenticate? If the latter, how do I refresh it?
Looks like you are receiving access token for graph .
Please make sure scope is created for the backend web api .
Note:User.Read is for graph api access and may have nonce in token
generated which may make the signature invalidated for you web api.
So please create a new scope in the portal that identifies your backendapi i.e ; modify your app to acquire an access token for your API.
Your spa App > Expose an API > Add Scope.
(Create a new scope: say name = access_as_user)
In API permissions: Add a new permission for registered application and scope access_as_user. something like api://<app id>/ scope name
Make sure you place this name of scope where ever you are using in your app scope ( remove user.read if present and add scope of your api) and grant admin consent .
Now try again and check the token in https://jwt.io .
If there is further error saying audience invalid:
Go to Manifest: Change entry "accessTokenAcceptedVersion" from (null or 1) to 2
And try .If not successful ,try by removing api:// prefix from your app configuration scope.
References:
Tutorial: Authenticate users E2E - Azure App Service | Microsoft
Docs
azure - Setting additionalLoginParams with auth v2 - Stack Overflow
IDX10511 -issue (github.com)
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've been trying to expose an API through azure API Management and I can't figure out what I'm doing wrong. Here's the situation:
My API is going to be called from an external application
They don't have an Azure Account in the same tenant
I want to enable external calls for my API by just using a subscription key (hence, why I'm using API Management), but also want to keep my actual API secured with Azure AD.
I have an API which is secured with Azure AD using OAuth2 and published into a Windows AppService
I have an App registration for that API, which i use to authenticate (it works from postman, for example)
app registration
I have Managed Identities turned on and permissions set.
I have added the API in API management
I added the authentication-managed-identity inbound rule, used the API Id Uri of the app registration as the resource value for it.
Api Management Config
When testing an endpoint from the APIM interface, I can successfully get a bearer token, but I get a 500 exception from the API which says: Neither scope or roles claim was found in the bearer token
bearer response
Here is the decoded bearer token, it doesn't have a scp attribute
bearer decoded
I'm not sure where I can specify a scope. If I use the full scope uri (api://guid/access.api.management) it will fail when trying to get a bearer token (The resource principal named api://guid/access.api.management was not found in the tenant).
I've even tried adding the Owner role to the APIM Identity for the AppService.
Maybe I'm not using this correctly, I'm pretty new at using Azure cloud and API Management so any suggestions are welcome.
Thanks.
You have expose an api protected by Azure, and currently you have an api application. Next, you need to create another application that represents the client, and then add the client application to the api application.
Next, go to the client application.
Under 'API permissions' click on 'Add permission', then click on the 'My APIs' tab.
Find your api application and select the appropriate scope.
Click 'Add permissions'.
Grant admin consent for your APIs.
Next, you need to use the auth code flow to obtain an access token,which requires you to log in to the user and obtain the authorization code, and then use the authorization code to redeem the access token.
1.Request an authorization code in the browser.
https://login.microsoftonline.com/{tenant id}/oauth2/v2.0/authorize?
client_id={client app client id}
&response_type=code
&redirect_uri={redirect_uri}
&response_mode=query
&scope=api://{api app client id}/{scope name}
&state=12345
2.Redeem token.
Parse the token:
I managed to get it working using the client credentials flow and storing the client secret in key vault.
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...
I have an AspNetCore 2.0 MVC web API secured by an Azure Active Directory B2C tenant. I have been able to use Postman to test the API end points by following this SO posting: Request Access Token in Postman for Azure AD B2C (in particular, the Microsoft documented steps referenced in SpottedMahn's comments:
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/azure-ad-b2c-webapi#use-postman-to-get-a-token-and-test-the-api )
Now, I am working on a serverless version of the above - the app is pretty much identical expect that the endpoints have been implemented by Azure functions in an Azure Functions App
The Functions App has Authentication on, Log in with Azure Active Directory and the following settings:
This is how i have set up the Application in the Azure B2C tenant:
If I access the functions endpoint via a browser, I get successfully routed to the Azure AD B2C login page and can log in, then see the results from the API endpoint. So I'm pretty confident all is good w.r.t. the Azure AD B2C <-> Function App configuration.
However, I can't use the Request Access Token technique linked above to get a token and inspect the endpoint in Postman
If I take the token obtained after authentication (for example by using fiddler and observing the id_token being returned), and in Postman I choose Bearer authentication and supply that id_token, then Postman successfully hits my endpoint. However, if I follow the steps in the linked document above, I do get the "login" popup and then do get a valid [looking] token, but when I click Use Token and run the request, I get
You do not have permission to view this directory or page.
I'd really like to be able to request an access token from postman just like I can with my aspnetcore 2.0 app (really just for the consistency so I don't have to remember lots of different techniques). Is that possible for Azure Function Apps and if so, any clues what I'm doing wrong in the above?
Ah I stumbled upon it. I fixed it by adding the Postman API client id (note: the postman API client id, not the postman App client id) [those references will make sense in the context of the Microsoft how-to linked above], under "ALLOWED TOKEN AUDIENCES" (visible in screenshot in question above).