• Claims and Policies

Claims and Policies

Description

For a good explanation on the new Claims based security with Asp.Net Core, read this blog which has a very good explanation on the use of claims. This article will deal primarily with creating and using Policies and Claims within the Plugin Manager.

Adding Authorization

The first step to adding authorization is to add and configure the required services, this example uses cookie authentication.

public class PluginInitialisation : IPlugin
{
    public void Configure(IApplicationBuilder appIHostingEnvironment env)
    {
        app.UseAuthentication();
    }
 
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication("DefaultAuthSchemeName")
            .AddCookie("DefaultAuthSchemeName"options =>
            {
                options.AccessDeniedPath = "/Error/AccessDenied";
                options.LoginPath = "/Login/";
                options.SlidingExpiration = true;
                options.Cookie.Expiration = new TimeSpan(7, 0, 0, 0);
            });
    }
 
    public void Finalise()
    {
 
    }
 
    public void Initialise(ILogger logger)
    {
 
    }
}

The authentication scheme, aptly named "DefaultAuthSchemeName" will be required later, when logging a user in and authenticating the user. It is also important to note that this step should be completed in the host application, prior to any other configuration setup.

Adding Policies

Each plugin module should be responsible for registering their own policies and claims, where a policy or claim is required to be shared then a common library can be used for configuration of the policy and the claims.

As routes are now authorized based on policies, a policy can rely on one or more claims, the following example creates two policies, the first is a simple claim that a user can add a blog, the second is for responding to a blog.

public void AfterConfigureServices(in IServiceCollection services)
{
    // Add blog specific policies
    services.AddAuthorization(options =>
    {
        options.AddPolicy(
            Constants.PolicyNameBlogCreate,
            policyBuilder => policyBuilder.RequireClaim(Constants.ClaimNameCreateBlog));
        options.AddPolicy(
            Constants.PolicyNameBlogRespond,
            policyBuilder => policyBuilder.RequireClaim(Constants.ClaimNameUsername)
            .RequireClaim(Constants.ClaimNameUserId)
            .RequireClaim(Constants.ClaimNameUserEmail));
    });
}

As can be seen, the add a blog policy requires only one claim, but in order to respond to a blog and leave a reply the user must have two claims, a user id and a username.

Route Policy Authorization

The next step is to specify a policy for a route, you only have to add the name of the policy as an attribute, the following example uses the above can add blog policy.

[Authorize(Policy = SharedPluginFeatures.Constants.PolicyNameBlogCreate)]
public IActionResult New()
{
    return View(nameof(Edit), GetEditBlogPostViewModel(new BlogItem()));
}

Now the route should be protected, and as long as the user fulfills the policies required they will have access to the route.

IClaimsProvider

Within the shared plugin features module is an interface called IClaimsProvider, this interface exposes two methods which are used to provide ClaimsIdentity classes for a user after the user logs in. The following example is hard coded, however, it demonstrates how to return claims for a user.

public class MockClaimsProvider : IClaimsProvider
{
    public List<ClaimsIdentityGetUserClaims(in long userId)
    {
        List<ClaimsIdentityResult = new List<ClaimsIdentity>();
 
        List<ClaimuserClaims = new List<Claim>();
        userClaims.Add(new Claim(Constants.ClaimNameUsername, "Administrator"));
        userClaims.Add(new Claim(Constants.ClaimNameUserEmail, "admin@nowhere.com"));
        userClaims.Add(new Claim(Constants.ClaimNameUserId, "123"));
        Result.Add(new ClaimsIdentity(userClaimsConstants.ClaimIdentityUser));
 
        List<ClaimblogClaims = new List<Claim>();
        blogClaims.Add(new Claim(Constants.ClaimNameCreateBlog, "true"));
        Result.Add(new ClaimsIdentity(blogClaimsConstants.ClaimIdentityBlog));
 
        return Result;
    }
 
    public AuthenticationProperties GetAuthenticationProperties()
    {
        return new AuthenticationProperties()
        {
            AllowRefresh = true,
            IsPersistent = true,
        };
    }
}

A true implementation of the above would use a database or similar methodology to retrieve claims for a user.

Plugins Requiring Claims

It is important to note at this point that both the Login and Blog plugins now require the use of Authentication.