2

I'm trying to write a Restful service which has more than one endpoints like

Assume each endpoint call is secured by a role.

  1. GetEmployees (Role/Claim = Employee.Readonly or Employee.Edit or Employee.Admin)
  2. AddEmployee (Role/Claim = Employee.Edit or Employee.Admin)
  3. UpdateEmployee (Role/Claim = Employee.Edit or Employee.Admin)
  4. DeleteEmployee (Role/Claim = Employee.Admin)

With Implicit flow, it is pretty straight forward just check roles claim and we are done.
My confusion is for client credential flow, how to map scopes to roles here?

akhileshcoer
  • 162
  • 10

1 Answers1

0

Lets assume that you have the following situation for the Client Credentials approach:

var client = new TokenClient(
            BaseAddress + "/connect/token",
            "clientId",
            "clientSecret");

var result = client.RequestClientCredentialsAsync(scope: "my.api").Result;

var accessToken = result.AccessToken;

var client = new HttpClient();
client.SetBearerToken(accessToken);
var result = client.GetStringAsync("https://protectedapiaddress/api/data/getdata").Result;

Where BaseAddress is your IDS address.

Of course you will have to register your client in the IDS clients list with the appropriate flow (Client Credentials), and the scope is just optional, but I guess you will need one.

Then on the API side you can use the newly Policy-based authorization.

API method:

[HttpGet]
[Authorize(Policy = "AdminUser")]
[Route("getdata")]
public Data GetData()
{
  // some code here
}

And the Authorization Requirement:

public class AdminUserRequirement : AuthorizationHandler<AdminUserRequirement>, IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AdminUserRequirement requirement)
    {
        if (!context.User.HasClaim(<'Your rule'>))
        {
            context.Fail();
        }
        else
        {
            context.Succeed(requirement);
        }
        return Task.FromResult(0);
    }
}

In the claims you will have

    {
       "scope" : "my.api"
       "clientId" : "clientId"
    }

and more. And then you can apply the rules.

EDIT: Forgot to mention - you have to register the policies in your Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services
            .AddMvcCore()
            .AddAuthorization(options =>
            {
                    options.AddPolicy("AdminUser",
                    policy => policy.Requirements.Add(new AdminUserRequirement()));
            });

    // More code here

}
m3n7alsnak3
  • 3,026
  • 1
  • 15
  • 24
  • Using Policy or Role is just change of syntax. How does scope "my.api" translate into policy? If we go by your way and merge my example I'll have 3 kinds of policy i.e. ReadOnly, User, AdminUser. In the requirement class I'll look for exact claims but how scope translated into policy? – akhileshcoer Jan 04 '18 at 01:27
  • 1
    I'm not saying that scope translates into policy. I'm just saying that you will have the scope and the clientid in the claims, and since with client credentials flow all you have is this, you can use them into the policies to allow/deny access. Look on policies more like a custom authorize attribute. And yes - if you go by this way, you will need a different policy for every different role. Many people don't like it, it is kind of an overhead, but Microsoft... – m3n7alsnak3 Jan 04 '18 at 16:18