New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization now includes code configured policy support. #22

Closed
blowdart opened this Issue May 8, 2015 · 15 comments

Comments

Projects
None yet
@blowdart
Member

blowdart commented May 8, 2015

ASP.NET authorization now supports code based policies. We provide implementations to support claims based authorization and the ability to express your own policies in code. An authorization policy must contain one or more requirements.

Policy configuration is done within ConfigureServices(...) within Startup.cs.

A simple policy to check for the presence of a claim would be configured as follows

services.ConfigureAuthorization(options =>
{
    options.AddPolicy("MustBeGroot", policy => policy.RequireClaim("IAmGroot"));
}

and would be applied as [Authorize(Policy="MustBeGroot")].

You can also specify a list of comma separated values as part of the claim requirement, for example

options.AddPolicy("MustBeGroot", policy => policy.RequireClaim("Permissions", "Read,Update"));

which would pass authorization if the Permissions claim had a value or either Read or Update.

A more complicated requirement would involve implementing IAuthorizationRequirement and an AuthorizationHandler. For example if your identity had a DateOfBirth claim and you wanted to implement a minimum age requirement it could look like

public class MinimumAgeRequirement : AuthorizationHandler<MinimumAgeRequirement>, IAuthorizationRequirement
{
    public MinimumAgeRequirement(int age)
    {
        MinimumAge = age;
    }

    protected int MinimumAge { get; set; }

    public override void Handle(AuthorizationContext context, MinimumAgeRequirement requirement)
    {
        if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth))
        {
            return;
        }

        var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth).Value);

        int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
        if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
        {
            calculatedAge--;
        }

        if (calculatedAge >= MinimumAge)
        {
            context.Succeed(requirement);
        }
    }
}

You could then configure it

options.AddPolicy("Over21", 
    policy => policy.Requirements.Add(new Authorization.MinimumAgeRequirement(21)));

and apply it via [Authorize(Policy="Over21")].

Finally you can use policy to limit the authentication schemes checked during authorization, for example

options.AddPolicy("WebApi", policy =>
{
     policy.ActiveAuthenticationSchemes.Add("Bearer");
     policy.RequireAuthenticatedUser();
});

would only allow requests which provide an identity to Bearer middleware to access the resource behind them.

@timmydo

This comment has been minimized.

timmydo commented May 8, 2015

you mean [Authorize(Policy="MustBeGroot")]?

@blowdart

This comment has been minimized.

Member

blowdart commented May 8, 2015

I did. Corrected. Thanks. More formal documentation will be coming in the next few weeks.

@sandorfr

This comment has been minimized.

sandorfr commented May 9, 2015

You mentioned that a policy can contain one or more requirement, but I'm under the impression that it is a must.

@blowdart

This comment has been minimized.

Member

blowdart commented May 9, 2015

And this is why I don't do off the cuff documentation, corrected, thank you.

@leastprivilege

This comment has been minimized.

leastprivilege commented May 9, 2015

How do I set a global authZ policy? e.g. all controller require an authenticated user

@aggieben

This comment has been minimized.

aggieben commented May 9, 2015

@leastprivilege I'm doing it like this:

var policyBuilder = new AuthorizationPolicyBuilder(OAuth1AuthenticationDefaults.AuthenticationScheme);
var policy = policyBuilder.Build();

services.ConfigureMvc(options => {
   options.Filters.Add(new AuthorizeFilter(policy));
});
@leastprivilege

This comment has been minimized.

leastprivilege commented May 9, 2015

This nulls the Identity property on User if the request is anonymous. So this is either a bug - or that is not the right way of installing a global authZ policy.

@leastprivilege

This comment has been minimized.

leastprivilege commented May 9, 2015

@crozone

This comment has been minimized.

crozone commented Aug 21, 2015

How can you manually check whether a User meets a given AuthorizationPolicy, outside of the AuthorizeAttribute?

Given that AuthorizationOptions can be injected, is there something like bool allowed = AuthorizationOptions.GetPolicy("SomePolicy").Evaluate((ClaimsPrincipal)User) ?

@damccull

This comment has been minimized.

damccull commented Aug 26, 2015

Is it possible for a controller/action to use multiple policies? Like "Bearer" and "MinimumAgeRequirement"?

@XplMarcel

This comment has been minimized.

XplMarcel commented Sep 29, 2015

If an Authorize attribute on a Controller has Roles ( [Authorize(Roles = "MyRole"] ), the RolesAuthorizationRequirement gets added automatically to the defaultPolicy.
Would it be possible to replace that requirement with my own RolesRequirement class ?

@Eilon

This comment has been minimized.

Member

Eilon commented Sep 29, 2015

@XplMarcel please log an issue in the https://github.com/aspnet/Security/ repo.

@khellang

This comment has been minimized.

khellang commented Feb 15, 2016

Can we please lock this issue and refer to https://github.com/aspnet/Security/ instead?

@MaximRouiller

This comment has been minimized.

MaximRouiller commented Feb 15, 2016

Is it possible to add a discussion thread and lock this?

@blowdart

This comment has been minimized.

Member

blowdart commented Feb 15, 2016

This is 9 months old, long before the lock and discuss. I'd hope discussion is done now, so locking.

@blowdart blowdart closed this Feb 15, 2016

@aspnet aspnet locked and limited conversation to collaborators Feb 15, 2016

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.