7
votes

I have been looking at the official Authenticating to Azure AD in daemon apps with certificates sample for Azure Active Directory on GitHub. The Web API service seems to have no knowledge of the client whatsoever.

  1. You are not told to log into Azure and add permission for the daemon client to access the Web API using the "Permissions to other applications" section.
  2. The Web API controller actions don't check the claims of the caller to ensure that it is the client app. It does have this code though which I don't entirely understand:
public IEnumerable Get()
{
    //
    // The Scope claim tells you what permissions the client application has in the service.
    // In this case we look for a scope value of user_impersonation, or full access to the service as the user.
    //
    Claim scopeClaim = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/scope");
    if (scopeClaim != null)
    {
        if (scopeClaim.Value != "user_impersonation")
        {
            throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.Unauthorized, ReasonPhrase = "The Scope claim does not contain 'user_impersonation' or scope claim not found" });
        }
    }

    // A user's To Do list is keyed off of the NameIdentifier claim, which contains an immutable, unique identifier for the user.
    Claim subject = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier);

    return from todo in todoBag
           where todo.Owner == subject.Value
           select todo;
}

Am I correct in thinking that any client registered with my Azure AD can access the Web API, with the way this sample is setup.

1

1 Answers

3
votes

Good question, this is admittedly misleading. The answer is yes - any web client registered in your Azure AD tenant can get a token to access the Web API using the client credentials flow described in the code sample.

If you do not want this behavior, you have 2 options:

  1. Define at least one application role for your Web API by editing the application manifest (see this sample). You might define something meaningful like "admin" or something more generic like "full_access". In your Web API code, you can then check for the existence of the corresponding role claim before authorizing the request. If you choose this strategy, the Azure AD tenant admin will be able to grant access to individual clients using the Permissions to Other Applications section, as you expected.
  2. The other strategy is to simply check the claims of the incoming token against some sort of ACL or whitelist. A common practice is to check the appid claim for a particular well-known client ID.

The sample code is indeed misleading with its use of the scope claim. The API was written to work with clients that access the API both on behalf of a user (delegated tokens) and using the application's identity (client credentials). That's why you see the scope claim in there.

At runtime, the validation logic you reference will find that scopeClaim == null. It will then use the ClaimTypes.NameIdentifier claim (a.k.a. the sub claim) to identify the client application and POST or GET todo's that belong to that particular application.

This sample does not restrict which clients in the Azure AD tenant can access the Web API whatsoever.

Hope this helps.