azure-functions-host: `ClaimsPrincipal` doesn't include identity when `authType` is `anonymous`

Investigative information

Please provide the following:

  • Timestamp: From December 4 through 6, 2018
  • Function App version (1.0 or 2.0): 2.0
  • Function App name: applies across multiple (every one I’ve tried)
  • Function name(s) (as appropriate): multiple
  • Invocation ID: N/A
  • Region: multiple; I’ve mostly tested australiasoutheast

Repro steps

Provide the steps required to reproduce the problem:

  1. Configure Azure AD authentication on a function app and disallow anonymous requests.
  2. Create an HTTP-triggered function (either C# script or precompiled C#) with a ClaimsPrincipal parameter.
  3. Include code within the function to enumerate and log the identities attached to the ClaimsPrincipal.
  4. Change the function authLevel to anonymous, instead of using a function key.
  5. Obtain an Azure AD token and send a request to the function.

Expected behavior

The ClaimsPrincipal.Identities property should be populated with the Azure AD identity, and all claims.

Actual behavior

The ClaimsPrincipal.Identities property does not include the Azure AD identity when authLevel is set to anonymous.

Known workarounds

Change the function’s authLevel to a different value.

Related information

Example function code:

#r "Newtonsoft.Json"

using System.Security.Claims;
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ClaimsPrincipal principal, ILogger log)
{
    log.LogInformation($"Found {principal.Identities.Count()} identities.");
    foreach (var identity in principal.Identities)
    {
        log.LogInformation($"Identity {identity.Name}:");
        log.LogInformation($"Auth type is {identity.AuthenticationType}");
        foreach (var claim in identity.Claims)
        {
            log.LogInformation($"Claim '{claim.Type}' = '{claim.Value}'");
        }
    }

    return new OkResult();
}

Example function.json:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in",
      "methods": [
        "get",
        "post"
      ]
    },
    {
      "name": "$return",
      "type": "http",
      "direction": "out"
    }
  ]
}

(Also note the documentation says that you should set the HTTP-triggered function authentication level to anonymous when using AAD authentication.)

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 16 (7 by maintainers)

Most upvoted comments

@matt-dib, we don’t actually populate ClaimsPrincipal.Current. In .NET Core, that is no longer the standard way of passing ClaimsPrincipal data. See here for more info on that.

Instead, we support passing in the ClaimsPrincipal as a parameter to your function, or grabbing it from the HttpRequest object via req.HttpContext.User;

You can see our documentation on the feature here.

I have a PR that addresses this issue (#3904).

@myusrn, we are planning on future integrations with EasyAuth, but we are still deciding whether we want to utilize the AuthorizationLevel.User field, or whether we want to do a more robust configuration that would allow users to do similar things to the Authorize attribute within the function.json/HttpTriggerAttribute.

  1. Correct. You can also track releases here: https://github.com/Azure/azure-functions-host/releases
  2. I would change it to AuthorizationLevel.Anonymous for now. Right now, AuthorizationLevel.User is an unused legacy value, and may remain so, as all of the other AuthorizationLevel values just have to do with Key-based authorization. This could be subject to change in the future, so it is best just to avoid using that until if/when we announce what we will use AuthorizationLevel.User for.