azure-functionsopenid-connectaccess-token.net-8.0azure-functions-isolated

Azure Functions + .NET8(Isolated Mode) + OIDC - How to validate an Access Token received in the Header of every request to my Azure Function?


Currently, I'm studying a little about Azure Functions with .NET 8 and OpenId Connect, so I'm currently using a Function [Get] whose response is just an object indicating any valid return (Ex.: Protected Route, 200). What I need to do is for the Access Token (JWT) added in the request Header to be validated so that the request can be processed. Could anyone help me with examples, valid links?

Thank you very much in advance...

I looked for a way to develop Middleware to validate the access token, but I didn't find anything on the internet or in the community that would help me with this or any other way to solve the problem.


Solution

  • Follow below steps to validate an Access Token received in the Header in the Isolated Azure functions.

    enter image description here

    Redirect URI:

    https://localhost:<port_number>/.auth/login/aad/callback
    

    Install the packages in the Azure function:

    Microsoft.AspNetCore.Authentication.OpenIdConnect
    Microsoft.AspNetCore.Authorization
    Microsoft.Identity.Web
    

    Use below code to validate the access token:

    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .ConfigureServices(services =>
        {
            services.AddApplicationInsightsTelemetryWorkerService();
            services.ConfigureFunctionsApplicationInsights();        
            services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
           .AddOpenIdConnect(options =>
            {
              options.Authority = "https://your-openid-connect-provider.com/Tenant_ID/V2.0";
              options.ClientId = "client-id";
              options.ClientSecret = "client-secret";
              options.ResponseType = "code";
              options.Scope.Add("openid");
              options.Scope.Add("profile");
              options.Scope.Add("email");
              options.SaveTokens = true;
              options.GetClaimsFromUserInfoEndpoint = true;
              options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                };
            });
        })
        .Build();
    host.Run();
    

    Code to validate access token:

    var openIdConnectHandler = new OpenIdConnectHandler();
    
    await openIdConnectHandler.InitializeAsync(request);
    await openIdConnectHandler.ValidateTokenReceptionAsync(request);
    await openIdConnectHandler.HandleRemoteAuthenticateAsync(request);
    await openIdConnectHandler.HandleAuthenticationAsync();
    

    Function.cs:

    var claimsPrincipal = executionContext.GetHttpContext().User;
    
    if (!claimsPrincipal.Identity.IsAuthenticated)
    {
        return new UnauthorizedResult();
    }
    
    var name = claimsPrincipal.FindFirst(ClaimTypes.Name)?.Value;
    var email = claimsPrincipal.FindFirst(ClaimTypes.Email)?.Value;
    
    return new OkObjectResult(new
    {
        Name = name,
        Email = email
    });