azure-functions-host icon indicating copy to clipboard operation
azure-functions-host copied to clipboard

Azure Functions Authentication during Development / local testing

Open klyse opened this issue 2 years ago • 9 comments

Question

My Azure functions (mostly written in C#) require HTTP authentication (AuthorizationLevel.User). I found many resources on how to configure OpenID on Azure but could not find much on how to setup the authentication locally during development.

The function core tools have a dedicated --enableAuth flag. Adding the enableAuth flag to the run command (func start --enable-auth) results in some more services being injected in the DI container. As far as I understand this disables the local default behaviour where the function AuthorizationLevel is ignored and instead performs the authentication steps. I could not find any documentation how this authentication pipeline works locally? How can I define the OpenID provider and how can I pass the Bearer token (I assume with the Authentication header)?

In the end I need ClaimsPrincipal to contain relevant user information provided by the Auth Token (Bearer) so that I can access the user context during local development.

klyse avatar Jul 09 '22 09:07 klyse

Hi @klyse You may want to try this. Please let us know if it is helpful?

Ved2806 avatar Jul 12 '22 14:07 Ved2806

Hi @Ved2806, thanks for the answer but I am afraid this describes only how to configure the app service on Azure. I specifically asked on how to configure this locally for testing / debugging purposes.

klyse avatar Jul 12 '22 14:07 klyse

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

ghost avatar Jul 17 '22 16:07 ghost

Hi @Ved2806, this issue is not stale and I am still hoping for an answer🥹

klyse avatar Jul 18 '22 00:07 klyse

I've been working with .NET Azure Functions for some time and as far as I'm aware there is currently no way to run Azure App Service Plan Authentication (EasyAuth) while developing .NET Azure Functions locally.

When you enable EasyAuth for your Azure Functions in Azure (or any Azure Web App) all the HTTP traffic flows through dedicated sidecar process that authenticates all incoming HTTP requests with the configuration you provided in the Azure Portal and forwards the requests to Azure Function with all identity related information via specific HTTP request headers. Azure Functions is smart enough to extract all this identity data from the HTTP headers and populate the ClaimsPrincipal object for you.

All this works great in Azure but I don't believe there is any kind of local emulator for this critical sidecar process we call EasyAuth.

My current approach is to use a specific version 1.12.0 of Microsoft.Identity.Web library (specific version due to bug described here) and do all authentication and authorization work myself. I mostly call AuthenticateAzureFunctionAsync method at the beginning of the HTTP triggered function in order to authenticate the incoming HTTP request.

It's not so developer friendly because there are some weird edge cases (e.g. calling another API on-behalf-of the user) you have to debug and find workarounds yourself or in GitHub issues but so far it gets the job done for me. You might also want to enable EasyAuth in Azure anyway and use Microsoft.Identity.Web integration with EasyAuth to further bulletproof your solution (I haven't played around with this scenario yet).

All above mentioned tips I used with .NET6 v4 Azure Functions with in-process model.

There is an issue here that currently has Planned & Committed status which describes the need to align Azure Functions AuthN/AuthZ with existing ASP.NET patterns which I am really looking forward to because it is critical for Serverless Web APIs. I absolutely love Azure Functions but from my perspective the AuthN/AuthZ is not very developer friendly and requires a lot of work to setup which hopefully will be addressed in the future.

marcin-burak avatar Aug 03 '22 14:08 marcin-burak

Hi @marcinburak, thanks for the answer. Appreciate it. Your feedback confirms my long feared theory: it just doesn't work🥲 Authentication is so important it should work out of the box for a great experience imho.

By the way I found https://github.com/fmichellonet/AzureFunctions.Extensions.OpenIDConnect to handle authentication locally. Seems to work well.

klyse avatar Aug 04 '22 15:08 klyse

Library seems quite nice and should work, just a word of caution: the library uses FunctionInvocationFilterAttribute to invoke the authentication and authorization process of the incoming HTTP request. This attribute is known as a function filter concept but it has been in preview since 2018 so there is no guarantee if it will work in the future and giving the fact that we can use the isolated process model it will remain in preview indefinitely.

If you have no problem with using the isolated process model instead of in-process model, you can do the same exact thing using middleware which is GA and will be the new standard way of invoking authentication. Here is an example.

marcin-burak avatar Aug 04 '22 19:08 marcin-burak

Keep in mind that the library you linked only authenticates and authorizes the HTTP requests but if your Azure Functions need to call some other web API like Microsoft Graph on behalf of the user, then you will need to write some additional code yourself to achieve that.

marcin-burak avatar Aug 04 '22 19:08 marcin-burak

Thanks for another valuable feedback @marcinburak. I'll move away from HTTP triggered functions. Too many unresolved questions. Too many unknown variables for for me for now... I'll probably use Azure Container Apps and ASP.net core instead.

klyse avatar Aug 08 '22 06:08 klyse

Hi @Ved2806, don't think this issue is closed/completed. Bottom line is that it's difficult to handle authorization and that should change in the future. So I think some issue should track the problem and hopefully resolve this in future.

klyse avatar Sep 30 '22 11:09 klyse