dark-loop / functions-authorize

An ASP.NET Core based authentication and authorization middleware for HTTP triggered Azure Functions (In-Proc and Isolated)
Apache License 2.0
35 stars 4 forks source link

Any example for in-process .NET 8? #58

Open josbol opened 1 month ago

josbol commented 1 month ago

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?

artmasa commented 1 month ago

@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 commented 1 month ago

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

artmasa commented 1 month ago

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

josbol commented 1 month ago

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!

artmasa commented 1 month ago

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

josbol commented 1 month ago

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!

Wotee commented 3 days ago

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.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?

helgeu commented 1 day ago

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

artmasa commented 14 hours ago

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 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.