Azure Functions out-of-process and authentication with Azure AD

5 minute read

Last year I managed to get Microsoft.Identity.Web running with Azure Functions. During the time, Microsoft released a new model for hosting Functions on .NET called out-of-process . This is used to run Functions in .NET 5.0, will be available with 6.0 and will be the only model available since .NET 7.0 as per roadmap. The out-of-process model comes with numerous differences, so I am going to go through those and show you, how to get authentication via Azure AD running there (and mimick some of the MIW functionality).

Differences between out-of-process and in-process

The major difference, which prevents us to use Microsoft.Identity.Web is the lack of HttpContext. At the moment, the out-of-process model uses HttpRequestData. It is quite different from HttpContext (part of HttpRequest) which MIW heavily depends upon.

There are other differences which are not super relevent for authentication, but you can find the full list in Microsoft’s docs.

A slight issue with in-process and Microsoft.Identity.Web

After some time running MIW in Functions (in-process) I noticed an issue - in your Azure Portal you might end up with Azure Functions Runtime is unreachable error when trying to work with it in the portal. The issue is caused by the built-in authentication providers being somehow overriden by the Dependency Injection extension. I haven’t managed to get deeper into this to figure out what exactly is happening, but the docs state that you shouldn’t override the host services, which is sort of what happens.

This issue doesn’t prevent your Functions from working, however you won’t be able to use Function keys (you don’t need them since you are using Azure AD anyways, right?) for authentication or the portal integration like mentioned above. The support for modifying authentication providers was requested in both Functions host and Microsoft.Identity.Web repos. In the MIW repo, there has been a nice discussion about this, and Valks came out with a solution which involves restoring the providers via a reflection (because you can’t access the AddArmToken, AddScriptAuthLevel and AddScriptJwtBearer methods from your code due to the nature of how Functions runtime works).

Note: I am mentioning this issue because the out-of-process model avoids the conflicts with the host.

Authenticating in out-of-process

I am assuming here that you are going to be using Azure Functions as an API (eg. calling it with Authorization: Bearer <token> header).

Easy way with Easy Auth

I love simply EasyAuth! It works out of box and provides token validation and bunch of others things. It still works in out-of-process, is simple and you just read the information from headers in HttpRequestData. Some basic sample (not out-of-process related can be found here).

The more complex way with MSAL (Microsoft.Identity.Web-like)

Earlier this month, a new feature request appeared in Microsoft.Identity.Web repo for support of .NET 5.0 Functions. I have done some slight assessment of the issue already, but generally I think the implementation should wait until there is some further clarification from Microsoft on HttpContext support in the .NET worker.

So how to approach this now? Since the Microsoft.AspNetCore.Authentication.JwtBearer won’t work in the out-of-process model (since it again depends on HttpContext and ASP.NET Core pipeline) you will need to handle the token validation yourself. I am not going to go too deep into this because Christos and Damien both did an awesome job describing what is required to get this work.

I have just made some slight modifications to the code to support the HttpRequestData and a few optimizations to cache the OIDC configuration. Now that the user is authenticated, we might want to get a token to call a downstream API, right? This is usually handled via ITokenAcquisition implementation, so I borrowed the method name (GetAccessTokenForUserAsync) and implemented it to run in out-of-process! Thanks to it, we can now make calls to Microsoft Graph or any other API which the user consented to!

You can find the sample code on my GitHub: https://github.com/hajekj/azure-functions-dotnet-worker-miw

Note: Once again, the code is really dirty, I just put the pieces together to get it working for a demo. You can easily make it work with B2C by switching the authority and providing the flow name.


Update:

Since the out-of-process model supports using custom middlewares, I started to implement the authentication one. However, there seem to be quite a few limitations which I described in a GitHub issue, hoping that someone will help out or provide guidance.

Comments

Wenham Dorsett

Hi Jan,

This was a great post. Thank you. Unfortunately, I ran into an issue where 0 functions were found when I ran this. I’m using Visual Studio so I had to use the Core Tools to start up the function. Any ideas?

Wenham Dorsett

It actually happens when I open the project in visual studio or vs code. 0 functions are found.

Jan Hajek

Can you please reach out via LinkedIn/Twitter or something so I can take a deeper look? Eventually with screenshots or something? I am unable to reproduce it on my end. What is the version of azure-functions-core-tools? This sounds more like an incompatible version of the Functions host.

Leave a Comment

Your email address will not be published. Required fields are marked *

Loading...