Azure Function App Binding ClaimsPrincial Doesn't Set Claims From JWT - azure

I'm developing a SPA that uses a Azure Function App for the API and Azure Active Directory for the auth. adal.access.token is set in local storage after the user logs in, but the claims are not set properly in the bound ClaimsPrincipal parameter, nor are they set within the HttpRequest parameter. The claims principal object looks the same whether or not the Authorization: Bearer ... header is set. How can I configure my Function App to use AAD and the ClaimsPrincipalbinding? I verified that the claims are set in the access token by using the token debugger at jwt.io.
public static MyFunction {
[FunctionName("MyFunction")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "some-path")],
ClaimsPrincipal principal
){
// principal does not contain the claims, or any of the token info
}
}
Then I send the request:
curl -X GET -H "Authorization: Bearer ..." http://localhost:7071/api/some-path
But the claims principle only has one claim, `http://schemas.microsoft.com/2017/07/functions/claims/authlevel: Admin`
UPDATE:
It appears the principal variable is set as expected when invoked in Azure, but is not set when developing locally.

i assume you created the app registration by using the function service app control panel by activating authentication with azure ad with express or something. doing so creates the app registration and puts the app function as the reply url,
so if you run it locally on your development environment, and try to log in, it will never send the token to your local machine as its not a source url.
basically you have to go to the app registration in azure ad, go to authentication and add an additional reply / redirect url, to point to your localhost address of your app, whatever that is. http://localhost:youriisexpressport sorta thing. then it will work locally as well.

Related

How to properly use "get_token" of "ManagedIdentityCredential" of azure identity

I am trying to use managed identity of Azure function to access AAD protected web app, which requires a custom flow instead of using different clients. So the first step is to obtain an access token:
credential = DefaultAzureCredential()
scope = "https://graph.microsoft.com/.default"
token = credential.get_token(scope)
I am able to get a token successfully.
Then access the AAD protected web app:
uri = "https://my-web-app-1.azurewebsites.net/"
headers = {
'Authorization': 'Bearer ' + token.token
}
api_response = requests.get(uri, headers=headers)
However, this step returns error:
{"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]'."}
So I suspect I used a wrong scope to get the token. So I am confused which scope to use here?
------context-----
I have an azure function which has been enabled system identity which has been enabled to access my web app my-web-app-1.azurewebsites.net/. The web app my-web-app-1.azurewebsites.net/ is AAD protected.
Here is the API permissions under my AAD application which I used for the web app authentication. The mistake here is I set API permissions for web app instead of Azure functions which in case has no way to set (because Functions have a system identity instead of AAD application where we can set API permissions.)
Try to set scope as {your-api-client-id}/.default to get access token. Replace your-api-client-id with the client id/application id for your API app in Azure AD.

Azure B2C callback after user signs up: Basic credentials specified for 'PreUserWriteRestful' are invalid

We have B2C tenant. After the user signs up, we want to set some custom claims. For this, we want to trigger azure function. I was following this tutorial.
My signin-up policy looks like this:
"Validate auth code" is API connection:
I don't understand what Username and Password to provide? Moreover, I do not understand how can I call azure function since it's secured with AAD like this:
In the end, I have this error while signing up:
Basic credentials specified for 'PreUserWriteRestful' are invalid. Check that the credentials are correct and that access has been granted by the resource.
The azure function is very simple (but for sure it's not called):
/// <summary>
/// API call, that is triggered by a sign-up user flow.
/// </summary>
[FunctionName("ValidateAuthCode")]
public async Task<IActionResult> ValidateAuthCode(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
ClaimsPrincipal principal, ILogger log)
{
foreach (var c in principal.Claims)
{
log.LogInformation($"Claim type: {c.Type} ; claim value: {c.Value}");
}
return new OkObjectResult(new { version = "1.0.0", action = "ShowBlockPage", userMessage = "Auth code issue." });
}
The Username and Password is reference Basic Authentication via a REST call.
"Basic secures the REST API with HTTP basic authentication. Only
verified users, including Azure AD B2C, can access your API. The
username and password are stored in Azure AD B2C policy keys. Learn
how to secure your RESTful services by using HTTP basic
authentication."
Reference
The information above is talking about custom policies but it's protocol specific so it's still relevant to user flows.
Azure Functions supports different type of programming language - but in general you need to look up a sample for the HTTP basic auth for a Web API. I suggest starting with Microsoft's documentation on Web APIs https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-app-types?toc=/azure/active-directory-b2c/TOC.json&bc=/azure/active-directory-b2c/bread/toc.json#web-apis
From there, locate a sample for Web API based on what you are using with the Azure Function.

Blazor standalone client calling a function via Azure B2C

Is there a good example or a walkthrough of a Blazor standalone app calling a function app via an Azure Active Directory B2C passing in a claim with an identity to the function?
I have been working my way through the documentation,
Secure an ASP.NET Core Blazor WebAssembly standalone app with Azure Active Directory B2C and
ASP.NET Core Blazor WebAssembly additional security scenarios but cannot get past 404 result.
So what am I trying to achieve? I want to put together a couple of POCs. The first is a Blazor standalone client app, authenticating via B2C, then passing an authorisation token claims token to an azure function, where I can unpack the user id and email address. The second is same as above, but with Api Management between the Blazor client and the functions api. Because of the nature of the project I am using the consumption plan for both the functions and api management.
So just concentrating on the first case (Blazor - B2C - Function), on the assumption if I get that to work, the api will follow…
I have a B2C client tenant with 2 applications: a front end app authorised for the scopes of a 2nd B2C application for the api. My Function app has authentication/authorisation set to 'Login with Active Directory' with the client ID set to the Front end app's client id, the issuer uri set to the B2C's pocsignupsignin Userflow and the 'Allowed Token Audiences' set to the client id of the Api in B2C.
I can get a JWT token via a browser and using postman successfully call a function in my function app passing a bearer token.
My Blazor app can log in to B2C. If I have no authorisation configured for the web app, then my function call is successful.
But once I turn authorisation I run into CORS 404 - origin 'https://localhost:44389' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. But I have CORS configured with 'Enable Access-Control-Allow-Credentials' and my client url configured.
What am I missing?
I also suspect that the token with the id will not be passed correctly.
From Program.cs
builder.Services.AddHttpClient("ServerAPI",
client => client.BaseAddress = new Uri(functionURI))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAdB2C", options.ProviderOptions.Authentication);
options.ProviderOptions.DefaultAccessTokenScopes.Add(readScopeURI);
options.ProviderOptions.DefaultAccessTokenScopes.Add(writeScopeURI);
Console.WriteLine($"options.ProviderOptions.DefaultAccessTokenScopes {options.ProviderOptions.DefaultAccessTokenScopes}");
});
From CustomAuthorizationMessageHandler
public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
NavigationManager navigationManager)
: base(provider, navigationManager)
{
ConfigureHandler(
authorizedUrls: new[] { B2CClientUrl },
scopes: new[] { "read", "write" });
}
}
From appsettings
"AzureAdB2C":
{
"Authority": B2C signupsignin uri,
"ClientId": B2C frontend client,
"ValidateAuthority": false
}
Function call
async Task GetFromDedicatedFunctionClient(string subUrl)
{
try
{
var client = ClientFactory.CreateClient("ServerAPI");
Console.WriteLine($"client.BaseAddress {client.BaseAddress}");
result =
await client.GetStringAsync(subUrl);
}
catch …
}

Azure Functions secured with Azure AD - Getting HTTP 401 when calling from native app

My goal is to secure my Azure Functions with Azure AD and call them from a WPF application.
I have an Azure Function with the following definition :
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
HttpRequest req,
ILogger log,
ExecutionContext context,
ClaimsPrincipal claimsPrincipal)
I registered an Azure AD App and configured the settings for Native App Authentication :
I configured my app in the "Expose an API" bladd
I also added an API Permissions
I associated my app in my Azure Functions App in the Authentication / Authorization blade.
I am getting a token from Azure AD like this in a WPF app (using the Microsoft.Identity.Client library)
string applicationID = "***"; // My AppID Guid
PublicClientApp = PublicClientApplicationBuilder.Create(applicationID)
.WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
.Build();
var listScopes = new List<string>
{
//"user.read" - Removed based on #tony-yu recommendation
$"api://{applicationID}/MyScope"
};
var authResult = await PublicClientApp.AcquireTokenInteractive(listScopes)
.ExecuteAsync();
var myToken = authResult.AccessToken;
I can authenticate without any problem and I am successfully getting a token but whenever I call my function and I provide my token in the Authorization header (Authorization = Bearer ****), I get :
401 - You do not have permission to view this directory or page.
Here's how I call it (Postman) :
Here is the WWW-Authenticate header content when the call returns
When I check the token I got, it seems legit
Any idea what I am doing wrong?
The scope is not correct. As you want to access your function which is protected by ad, you need to use
var listScopes = new List<string>
{
"{applicationID}/.default"
};
instead.
user.read is the permission for Microsoft Graph API.
So I finally made it work thanks to this SO article here by ambrose-leung

Azure App Services Twitter Authentication Web API

How do you use Azure App Services to authenticate a Web API Route?
What do I need to send to the /api/test/auth route to return a 200!?
The /api/test/noauth route works fine without the [Authorize] attribute.
[Authorize]
[HttpGet]
[Route("auth")]
public IActionResult TestAuth()
{
return new ObjectResult("This requires authentication.");
}
[HttpGet]
[Route("noauth")]
public IActionResult TestNoAuth()
{
return new ObjectResult("This doesn't require authentication.");
}
I've set it up so when you hit the /.auth/login/twitter route, it will redirect to the Twitter login page, which returns to the callback URL with a Bearer token, but my bearer token is not working??
Send with Bearer Token
This returns a 401 Unauthorized error? Do I need to set up something in my code to handle Twitter Authorization?
In your twitter application,first click on Settings and change the Application Type to "Read, Write and Access direct messages".Then once your Twitter application has been updated to "Read, Write and Access direct messages", click on the Home tab, and "create your access token". If you have already created the token, regenerate it.
Also Regenerate Consumer Key and Consumer Secret.
Microsoft released adal.js to handle the grunt work of handling the tokens from authentication services. I'm struggling with the same problem using AzureActiveDirectory authentication for an App Service web api. There is a sample leveraging it with Angular, but it will need to be modified for use in an ajax call. https://github.com/AzureAD/azure-activedirectory-library-for-js

Resources