Azure Functions v2 & Google Auth - azure

I've set up my Azure Functions 2 in the manner described in this post https://blogs.msdn.microsoft.com/stuartleeks/2018/02/19/azure-functions-and-app-service-authentication/
I can call the /.auth/login/google endpoint with the Google token and get back the easy auth token.
And I can call the /.auth/me endpoint and get back my profile info.
But in my code, the Thread.CurrentPrincipal.Identity is null. I can't seem to find any solution to this. I have verified my request has the x-zumo-auth header set to the easy auth token retrieved from the login endpoint. And of course the function is set to anonymous.
I hope I'm missing something simple. Thanks for your help.

Since November 28th 2018, this feature is now in preview. This capability is only available to the Functions 2.x runtime. It is also currently only available for .NET languages.
The ClaimsPrincipal is available as part of the request context as
shown in the following example:
using System.Net;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
public static IActionResult Run(HttpRequest req, ILogger log)
{
ClaimsPrincipal identities = req.HttpContext.User;
// ...
return new OkResult();
}
Alternatively, the ClaimsPrincipal can simply be included as an
additional parameter in the function signature:
using System.Net;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Newtonsoft.Json.Linq;
public static void Run(JObject input, ClaimsPrincipal principal, ILogger log)
{
// ...
return;
}
Reference: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook#working-with-client-identities

Found the answer but still I'm surprised there is such a lack of clarity.
https://learn.microsoft.com/en-us/azure/app-service/app-service-authentication-overview
For Azure Functions, ClaimsPrincipal.Current is not hydrated for .NET code, but you can still find the user claims in the request headers.
But there's countless examples I'm seeing where people reference that in Azure Functions as if it should be hydrated.
I am indeed finding the claims as expected in the headers and will work with that, but I feel like there's still something that I'm missing...

Related

How to use AD authentication while developing Azure Functions through Visual Studio 2019 using .NET Core 3.1

I'm developing Azure Functions using Visual Studio 2019 in .NET Core 3.1. I have to implement Azure AD authentication for these functions. I'm aware of how to use AD authentication in an ASP.NET Core 3.1 web app. But as there is no startup class provided by default in an Azure Function, how to implement the same logic?
I'm using this code in an ASP.NET Core 3.1 web app:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration, "AzureAd");
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAuthentication();
app.UseAuthorization();
}
and adding [Authorize] tags in controller methods. But, I'm not able to figure out how to implement the same in an Azure Function. Here, I've currently set the authorization level as Anonymous like below
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger log)
{
}
How to implement the Azure AD authentication here?
----UPDATE----
After adding the configurations suggested by Tiny-wa, still not able to figure out why is the Api responding with a 401 when I send a bearer token with it
I have a function contains an http trigger in it, before I enable authentication for the function, I can get response directly by calling url.
And I follow this document to enable the azure ad authentication for it.
Choose your function -> press into Authentication/Authorization tab -> check 'On'.
Then choose 'Log in with azure ad', click azure ad as Authentication providers, jump to a new page, choose express and create a new ad application.
After saving all configurations, it asks me to sign in when I call the url methoned above.
===============================UPDATE====================================
Http trigger can set different auth level by adding configuration and those are setting a different level as Anonymous, we need to add parameter in the request url. This document offers a sample and this one from microsoft offers detail.
=============================update2=============================
I have found another solution which may suitable for you. Here's the sample.
After adding authenticate module in function code, you can expose the function as an api in azure ad. This makes your function app called with an access token. Of course I have tried the sample, here's my experience.
First, modify the configuration in Constants.cs, then create an azure ad app and expose an api. Next, add api permiss which exposed just now. Finally add client secret which is used to generate access token. Below are some screenshot about my action.

Refresh the function token of the Azure Function

I've an Azure function with an HTTP trigger. On that trigger there is an webhook linked. For security I would use function tokens for that, but they must change on every call. Then the webhook from the third party tool must be updated with the new token. The result would be that every token only could be use once. Pseudo code below:
[FunctionName("GetData")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequestMessage req, TraceWriter log)
{
// 1. Do the action
// 2. Refresh the token
// 3. Update the webhook with the new token
}
But how could I refresh the function token of the Azure Function? I've searched on the internet but didn't find anything.
Azure function keys can be get and set via the key management API.
https://github.com/Azure/azure-functions-host/wiki/Key-management-API
Your function can use this app to get and set function keys. To use the key management API, you will need an authorization jwt access token.
It can then use that access token to access the key management API to get and set new keys. Those keys can then be posted/shared with your third party application.
So, your process will look like
// 1. Do the action
// 2. Get jwt
// 2. Refresh the token
// 3. Update the webhook with the new token
Have a look at this question here, which has several answers with examples with code.
Get Azure Function keys from an Azure Function at deployment time?
Also take a look at this answer here which demonstrates how to use the Microsoft.Azure.Management.Fluent library to achieve this.
https://stackoverflow.com/a/46463971/2048857

Azure Maps API workaround for unsupported regions

I am using Azure Maps API to for geocode reversal. Sometimes, it works and sometimes it doesn't. While researching I found a document- https://learn.microsoft.com/en-us/azure/azure-maps/about-azure-maps. It says that the API is currently not supported for below countries-
Argentina
China
India
Morocco
Pakistan
South Korea
I am looking for a workaround. Is there any way I can use the API from India?
One option is to use a VPN into a supported region. Note, if you do this, don't share the map publicly as it will show things that don't align with the views of these countries and can get your company into some trouble. Many of these countries will likely be unblocked in early 2019.
Here's a workaround which I figured out.
Create a function app in Azure and make an Http call to the Azure maps API. Make sure the app is hosted in a region where the Azure maps API is allowed (e.g. Central US).
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System.Net.Http;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
string lattlong = req.Query["lattlong"];
HttpClient httpClient = new HttpClient();
string location = httpClient.GetStringAsync("https://atlas.microsoft.com/search/address/reverse/json?api-version=1.0&subscription-key=<secret_key>&query=" + lattlong).Result;
dynamic data = Newtonsoft.Json.Linq.JObject.Parse(location);
return lattlong != null
? (ActionResult)new OkObjectResult(data.addresses[0].address.municipality + ", " + data.addresses[0].address.country)
: new BadRequestObjectResult("Failed to get location.");
}
The function app should take the lattidue and longitude as parameters and make the Http call.
https://<function_app>.azurewebsites.net/api/GetLocation?code=1/<function_secret_key>&lattlong=13.097045900000001,77.59058569999999
The response from the Azure Maps API is returned successfully by the function app.

Azure Function 2.x - Get Current User's Claims

I have an Azure Function 2.x (Asp.net Core) and am authenticating with Azure AD. I'm trying to access the logged-in user's Claims after authentication. Previously using Azure Functions 1.x we would get the Claims using ClaimsPrincipal.Current, as seen in the code below:
using System.Net;
using System.Collections.Generic;
using System.Security.Claims;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
public static HttpResponseMessage Run(HttpRequestMessage req, out object document, TraceWriter log)
{
string name = ClaimsPrincipal.Current.FindFirst("name").Value;
log.Info($"name is {name}");
return req.CreateResponse(HttpStatusCode.OK, "Done");
}
Any guidance on how we access Claims in Azure Functions 2.x using .Net Core?
This feature is now supported in C# in Azure Functions 2.0. You can now add ClaimsPrincipal as a parameter to your HttpTrigger function's signature, or you can access it on the HttpRequest object via req.HttpContext.User.
Support should be coming soon to JavaScript, and eventually all languages should support this feature.
Let me just post a code example here, see where ClaimsPrincipal parameter is:
[FunctionName("MyFunctionName")]
public static HttpResponseMessage Run(
[HttpTrigger(
AuthorizationLevel.Anonymous,
"get", "post",
Route = "MyFunctionName")]HttpRequestMessage req,
ILogger log,
ClaimsPrincipal claimsPrincipal)
{
// My function code here...
}

How to implement Authorization in ASP.NET Web API using Windows Azure

I have sample ASP.NET Web API with get method, I have prefixed a [Authorize] attribute on top of the method. Can I please know how should I call this method from browser or fiddler? Also, I am hosting these API's on Windows Azure
public class ValuesController : ApiController
{
// GET api/values
[Authorize]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
Depending on the type of authorization you are using there might be different ways. But if you are using default routing you could call your method at the following url:
/api/values
You might of course need to pass additional headers depending on the authorization mechanism you choose. The [Authorize] attribute doesn't do anything unless you have configured some authorization. You may take a look at the following article for an example of how you could use tokens to authenticate your users.

Resources