asp.net-coreasp.net-core-mvcadfsasp.net-core-identityasp.net-roles

Implementing roles with custom storage provider for Identity


Recently, I was able to successfully implement authentication (SSO with ADFS using WS-Federation) for an app. Now, I am trying to understand and get authorization working, so this question may be unclear.

I'm using this topic to implement roles with custom storage provider for Identity without entity framework.

I've got custom User and Role models set up, along with the custom UserStore and RoleStore that implement the appropriate interfaces. There's also tables for roles ready to be used.

I run into issues when trying to access either an [Authorized] or [Authorized(Roles = "RoleName")]. As expected, the actions require me to authenticate with ADFS, but when I submit correct credentials the login loops a few times and displays the ADFS error page. This problem with ADFS is not present without the role implementation. UserStore and RoleStore does not implement code yet, but the app never tries uses any of their methods.

I tried implementing different options in Startup.cs, some of which I have commented out, and reordering services. Inserting dummy code into the RoleStore didn't help either. Basically, I just want to be able to add role checks from custom storage using Identity. I can get the username of the user at any time after they log in to find their role.

Startup.cs ConfigureServices method is where it's most unclear for me, and probably the most likely place where something is set up incorrectly.

Startup.cs ConfigureServices():

public void ConfigureServices(IServiceCollection services)
{
    // Add identity types
    services.AddIdentity<User, Role>()
        //.AddUserManager<UserManager<User>>() // some other settings I've tried ...
        //.AddRoleManager<RoleManager<Role>>()
        //.AddUserStore<UserStore>()
        //.AddRoleStore<RoleStore>()
        //.AddRoles<Role>()
        .AddDefaultTokenProviders();

    // Identity Services
    services.AddTransient<IUserStore<User>, UserStore>();
    services.AddTransient<IRoleStore<Role>, RoleStore>();
    //for SQL connection, I'll be using a different one (not the one from the link to topic)

    //dependency injection
    services.AddScoped<ISomeService, SomeService>();

    services.AddAuthentication(sharedOptions =>
    {
        // authentication options...
    })
    .AddWsFederation(options =>
    {
        // wsfed options...
    })
    .AddCookie(options =>
    {
        options.Cookie.Name = "NameOfCookie";
        //options.LoginPath = "/Access/Login"; //app function the same without this
        options.LogoutPath = "/Access/Logout";
        options.AccessDeniedPath = "/Access/AccessDenied";
        options.ExpireTimeSpan = TimeSpan.FromMinutes(120);
        options.SlidingExpiration = true;
    });

    services.AddControllersWithViews();
}

Solution

  • Another way of doing this is to add a custom attribute store to ADFS.

    Then the roles etc. that you require from the custom attribute store can be configured as claims.