functions-authorize icon indicating copy to clipboard operation
functions-authorize copied to clipboard

Any example for in-process .NET 8?

Open josbol opened this issue 1 year ago • 28 comments
trafficstars

Hi,

Now that a stable version of .NET 8 for in-process azure functions is out, we are updating everything to this version. Everything seems to work, except when using AAD authentication. The same old story of version conflicts.... We are still trying to see if there's a working combination of package versions, but so far without success.

Does anybody have a working example?

josbol avatar Aug 14 '24 13:08 josbol

@josbol, my sample application runs on 8, no problem. Now, version 7+ of ASP.NET Core has a problem in their security assemblies where they allow old dependencies from ModelIdentity. Update them to the latest version and I think you should be fine: <PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.0.1" /> Here is an issue open on that problem.

Please share more details on your problem if my answer is completely unrelated.

artmasa avatar Aug 16 '24 13:08 artmasa

I have created #59 to create different framework target versions of the package to force the load of the corresponding IdentityModel packages

artmasa avatar Aug 16 '24 13:08 artmasa

@josbol, any update on this? Is the answer above related to the issue you were having?

artmasa avatar Aug 19 '24 15:08 artmasa

Hi @artmasa, just including Microsoft.IdentityModel.Protocols.OpenIdConnect using the latest version didn't solve the problem, but using a standard AddJwtBearer configuration did the trick. I still have to test 4.1.1 to see if solves the problem without having to change the setup code. I have about 15 more projects to convert to .NET 8, most of them using AAD authentication, so plenty of test cases. I'll let you know asap!

josbol avatar Aug 19 '24 21:08 josbol

@josbol, are you not using AddFunctionsAuthentication method to configure your application? Are there any more details available about the actual exception you are getting?

artmasa avatar Aug 19 '24 22:08 artmasa

I don't have access to the source code at the moment, but I'm for sure calling AddFunctionsAuthentication. I'm using the following calls in this specific order:

AddFunctionsAuthentication (using the defaults of JwtBearerDefaults) AddWhateverNeeded(...) AddFunctionsAuthorization();

As soon as I can, I'll get a untouched project put all the information here!

josbol avatar Aug 20 '24 18:08 josbol

I tried to convert my functions to .NET8 in-process as well, and was somewhat struggling with it.

my sample application runs on 8, no problem.

I also tried to check the sample app in the repo, and that is currently .NET6. I followed the steps here to the sample app; updated the 4.4.0 of Microsoft.NET.Sdk.Functions and net8.0 framework image Copypasted the minimal local.settings.json from the same document image Then when I run the function locally, I can get the token from /api/GetTestToken without any problems, but /api/TestFunction I get the following error image

System.Private.CoreLib: Exception while executing function: TestFunction. SampleInProcFunctions.V4: Method not found: 'System.Collections.Generic.IList`1<Microsoft.IdentityModel.Tokens.ISecurityTokenValidator> Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions.get_SecurityTokenValidators()'.

Can you spot that I'm either doing something stupid here, or are there some problems still with the in-process support in .NET8?

Wotee avatar Sep 17 '24 14:09 Wotee

FWIW

Doing the same variant of testing with the isolated sample from this repo does indeed work. So not sure whats going on...

image

image

image

helgeu avatar Sep 20 '24 06:09 helgeu

I have been investigating this issue for the last couple weeks. I just setup a new PC and the tooling in VS got the latest version and I'm able to reproduce the error @Wotee has described above. The problem occurs because of the assemblies loaded by the functions CLI (func.exe).

If you notice, functions in-process is not based on an EXE, but a DLL; it is loaded in the same AppDomain of the hosting environment. I imagine this is the same tooling used to initialize the function apps in the Azure environment.

Even when the functions project specifies to use Microsoft.AspNetCore.Authentication.JwtBearer 8.0.0 which has a dependency on Microsoft.IdentityModel.Tokens 7.0.3. The Abstractions module on this project forces the dependencies to align .NET version for the Microsoft.IdentityModel... libraries by adding dependency on to MIcrosoft.IdentityModel.Protocols.OpenIdConnect (TargetFramework).

When you want to add the custom validator to options it bombs saying the SecurityTokenValidators property doesn't exist. Of course you can find it in every single version of the assembly even when is deprecated for versions 8.0.0+ The thing is that when assemblies are loaded this property has type IList<ISecurityTokenValidator v7.1.2>. 7.1.2 is the version the CLI loaded for Microsoft.IdentityModel.Tokens, but my code after compiling it is looking for property SecurityTokenValidators with type IList<ISecurityTokenValidator v8.0.0>.

If I change the package reference for IdentityModel.. libraries to align with the version used by the functions CLI everything works again. The problem is, how to make sure the libraries will always align once deployed to Azure as the CLI version might be different from the version used by the local tooling.

How to find the version in the CLI?:

  • If you know the tooling path just look for the IdentityModel and look at the properties
  • Or, you can throw an exception before adding you validator:
var assembly = options.GetType().GetProperties().Single(x => x.Name == "SecurityTokenValidators").PropertyType.GetGenericArguments().First().Assembly.FullName;
throw new Exception(assembly)

I'm looking for a way for these assembly clashes to not affect this project. The reason this has been so problematic is that the functions host also relies on the authentication modules to interact with your functions from the azure portal. Using Isolated mode is a better approach as everything you compile runs on a completely different process and what you compile is what gets loaded.

If you don't use a custom validator and you use an OpenID Connect compliant token (AAD, Google, Auth0, Facebook, etc...) you don't need this validator thing in the sample application since token validation relies on the key IDs referenced in token and the framework automatically interacts with the configured authority to obtain the key values to validate signature. The retrieval of keys happens once per key ID/authority pair for the life of the application. The values are cached to validate signature in tokens of subsequent requests matching cached keys.

artmasa avatar Sep 20 '24 19:09 artmasa

Our migration to .NET 8 was put on halt after the migration of two apps and both were running fine until yesterday. All of the sudden both apps went offline and the following error is shown in the Azure Portal. No deploys were made from our side. None of the apps that are still on 6 (also in-process) are affected.

Microsoft.Azure.WebJobs.Script: Error configuring services in an external startup class. DarkLoop.Azure.Functions.Authorization.InProcess: Could not load type 'Microsoft.Extensions.DependencyInjection.ArmAuthenticationExtensions' from assembly 'Microsoft.Azure.WebJobs.Script.WebHost, Version=4.837.0.0, Culture=neutral, PublicKeyToken=null'.

One is using DarkLoop.Azure.Functions.Authorization.InProcess Version 4.1.0 the other 4.1.3. Both are on .NET 8

Curiously, reverting the app back to .NET 6 (code and settings in the portal) and redeploying doesn't help either. We had to create a new function app (.net 6, in-process, windows) for the .net 6 version to work.

josbol avatar Jan 28 '25 13:01 josbol

Hi @josbol, Yes, I can confirm they have deprecated those methods in latest versions. It's very hard to keep track of what version they use for the actual azure hosts. I will remove this functionality and create a preview version. Maybe you can try deploying to a test environment once is available.

artmasa avatar Jan 28 '25 15:01 artmasa

Sure, I'll deploy it as soon as the test version is available!

The annoying thing is that I couldn't find any information of an update of the azure hosts (what I did find seems to be quite old), so I wasn't really sure if it was that or something else.

I guess having most apps still on 6 and 6 not receiving any more updates is a blessing in disguise in this case.

josbol avatar Jan 28 '25 15:01 josbol

@josbol, a new preview version is available

artmasa avatar Jan 28 '25 16:01 artmasa

Update the nuget package to the preview version (was 4.1.0), but it results in the following error. I checked the azure functions tooling and it is up to date.

System.IO.FileNotFoundException: 'Could not load file or assembly 'Microsoft.Azure.WebJobs.Script.WebHost, Version=4.1036.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.'

josbol avatar Jan 28 '25 16:01 josbol

I just tried going to 4.1.3 to see what the difference would be. At startup it doesn't complain but when executing a function it will cause the error that has been reported before:

System.MissingMethodException: Method not found: 'Microsoft.IdentityModel.Tokens.TokenValidationParameters Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerOptions.get_TokenValidationParameters()'.

josbol avatar Jan 28 '25 17:01 josbol

OK, downgrading webhost version close to the one you reported does not have the extension method any longer as not all WebHost packages are available from a package repo. PR: #76

artmasa avatar Jan 28 '25 17:01 artmasa

New version 4.2.0-preview-250128-5 is available.

artmasa avatar Jan 28 '25 17:01 artmasa

It works when published! The runtime version reported by the Azure Portal is 4.837.0.23524

However, when testing it locally I get:

System.IO.FileNotFoundException: 'Could not load file or assembly 'Microsoft.Azure.WebJobs.Script.WebHost, Version=4.834.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.'

The previous version I only tested locally btw.

josbol avatar Jan 28 '25 18:01 josbol

I see. Do you know what is the version when running locally? It has to be related to the Functions SDK running on VS or VS Code Mine is 4.35.4

Image

artmasa avatar Jan 28 '25 18:01 artmasa

Same here, the versions reported in the console are the following:

Core Tools Version: 4.0.6518 Commit hash: N/A +74ed9095fdd6c5326276aae6b8a7d41ccbdeb6aa (64-bit) Function Runtime Version: 4.35.4.23179

josbol avatar Jan 28 '25 18:01 josbol

I will have to downgrade it to this one to not affect development. It shouldn't affect once deployed as the version in the hosts is greater. Thanks for checking these builds as I don't have the bandwidth at the moment.

artmasa avatar Jan 28 '25 18:01 artmasa

Happy to help :)

josbol avatar Jan 28 '25 18:01 josbol

new preview available

artmasa avatar Jan 28 '25 19:01 artmasa

Working locally and on Azure! Thank you for fixing this so quickly!

josbol avatar Jan 28 '25 19:01 josbol

will move to release version

artmasa avatar Jan 28 '25 19:01 artmasa

Release 4.2.0 is now available. .NET 8 version dependencies should be aligned with the dependencies used by the Azure hosts at the moment. Need to find a way to track host versions in Azure better to ensure the alignment for In-Process package.

artmasa avatar Jan 28 '25 20:01 artmasa

just popping in to say:

Cudos!!!

Really like how you did chop away at this and solved it. Loved every update on email too!

helgeu avatar Jan 29 '25 17:01 helgeu

Thanks @helgeu! It felt like a true working session. And thanks @josbol for the live troubleshooting.

artmasa avatar Jan 29 '25 22:01 artmasa