Skip to content

ClaimsPrincipal.IsInRole doesn't work with AAD application roles #3898

@johndowns

Description

@johndowns

When using the EasyAuth ClaimsPrincipal binding with an Azure AD token with an application role, the ClaimsPrincipal.IsInRole() method always returns false even when the token has the role included.

Investigative information

  • Timestamp: From December 4 until now (December 17), 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 tested centralus and australiasoutheast

Repro steps

  1. Create a new function app. Enable EasyAuth through the portal.
  2. Update the app registration in Azure AD to add a new app role to the app's manifest, such as:
{
    "allowedMemberTypes": [
        "Application"
    ],
    "description": "Administrators can manage the Surveys in their tenant",
    "displayName": "SurveyAdmin",
    "id": "c20e145e-5459-4a6c-a074-b942bbd4cfe1",
    "isEnabled": true,
    "value": "SurveyAdmin"
}
  1. Create a client app in the same AAD tenant, create a key, assign the role from step 2 to the client app, and grant the permission.
  2. Create a function in the portal with the following 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}'");
        }
    }

    var isInRole = principal.IsInRole("SurveyAdmin");
    log.LogInformation($"Principal is {(isInRole ? "" : "NOT")} in the SurveyAdmin role.");

    return new OkResult();
}
  1. Obtain an Azure AD token. Observe that the token includes the roles claim, which is a string array with a single item (SurveyAdmin).
  2. Send a request to the function, attaching the token. Observe that the role claim is included in the enumerated list of claims logged out, but the log also includes Principal is NOT in the SurveryAdmin role. since the IsInRole method has returned false.

Expected behavior

The roles claim contains the roles associated with that principal. It should be honoured when evaluating the IsInRole method. (Also, on the main EasyAuth issue, @ConnorMcMahon indicated that this specific scenario should work.)

Actual behavior

The IsInRole method returns false.

Known workarounds

By manually inspecting the claims associated with the identity, we can perform our own version of the IsInRole logic.

Related information

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions