Blazor - Securing using ADFS with local DB repository: how/when to hook into SQL

痞子三分冷 提交于 2021-02-11 13:38:17

问题


I have a Blazer Server app which now uses authentication from a local ADFS server. Having identified the user, I now need to load their permissions. We don't think this can be provided via claims from the ADFS server, so want to configure this in the DB, but need to understand how/when to get this information.

Regarding the hook into ADFS, my code is as follows (any suggestions on improvement most welcome)

App.razor

<CascadingAuthenticationState>
    <Router AppAssembly="@typeof(Program).Assembly">
        <Found Context="routeData">
            <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
                <NotAuthorized>
                    <h1>Sorry</h1>
                    <p>You're not authorized to reach this page.</p>
                    <p>You may need to log in as a different user.</p>
                </NotAuthorized>
            </AuthorizeRouteView>
        </Found>
        <NotFound>
            <LayoutView Layout="@typeof(MainLayout)">
                <h1>Sorry</h1>
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </NotFound>
    </Router>
</CascadingAuthenticationState>

appsettings.Development.json

{
  "DetailedErrors": "true",
  "ConnectionStrings": {
    "MyDB": "Data Source=x.x.x.x;Initial Catalog=xxxxx;user id=me;password=sshhh;Persist Security Info=False;"
  },
  "Ida": {
    "ADFSMetadata": "https://adfs.ourServer.com/FederationMetadata/2007-06/FederationMetadata.xml",
    "Wtrealm": "https://localhost:44323/"
  } 
}

Startup.cs (only showing security related code)

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.WsFederation;
public class Startup
{
    public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        .....
        app.UseAuthentication();
        app.Use(async (context, next) =>
        {
            context.Response.Headers.Add("X-Frame-Options", "DENY");
            var user = context.User;
            if (user?.Identities.HasNoItems(identity => identity.IsAuthenticated) ?? true)
            {
                await context.ChallengeAsync(WsFederationDefaults.AuthenticationScheme).ConfigureAwait(false);
            }

            if (next != null)
            {
                await next().ConfigureAwait(false);
            }
        });

        ....
    }

...

    public void ConfigureServices(IServiceCollection services)
    {
        var wtrealm = this.Configuration.GetSection("Ida:Wtrealm").Value;
        var metadataAddress = this.Configuration.GetSection("Ida:ADFSMetadata").Value;

        services
            .AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
            })
            .AddWsFederation(options =>
            {
                options.Wtrealm = wtrealm ;
                options.MetadataAddress = metadataAddress;
                options.UseTokenLifetime = false;
            })
            .AddCookie();
        ....
    }
}

Any suggestions regarding the above code? When the user enters our site (any page), they automatically get pushed to the ADFS server to authenticate. Seems okay, but prevents the user from logging out....

So, from ADFS we get several claims that identify the user, e.g. their UPNname. My thought is to go to the DB and load all the roles/permissions/rights that this user has.

  • Where in my code should I put such code
  • The DB is currently used by another application that uses the older "membership" tables. I want to use something a bit more up-to-date, the identity model? I can't risk breaking security for the other application. Should I store security in a new DB?

Any pointers would be most welcome...assume I'm a novice at this.


回答1:


The usual way to do this is to write a custom attribute provider for ADFS.

Then you can get the roles you want from the DB and they are added to the claims.




回答2:


After reading a lot around this area, I discovered a very clearly presented PluralSight course that solved it for me:

ASP.NET Core 2 Authentication Playbook: Chris Klug

Specifically, see the chapter:

Doing Claims Transformation

For details, watch the course. In summary:

  1. Create the Entity and Context for pulling your data from the DB. Register these in the Startup in the normal manner.
  2. Create a ProfileService (that has the logic to read the data from the Context). I also included a MemoryCache object so I could locally store the info.
  3. Then create a Claims Transformation class (implementing IClaimsTransformation) and register that as a service.
  4. Add these into your Blazor page's code-behind file as:

    [Inject] protected IClaimsTransformation ClaimsTransformation { get; set; } = null!;

    [CascadingParameter] protected Task AuthenticationStateTask { get; set; }

  5. Consume the data thus:

    AuthenticationState authState = await this.AuthenticationStateTask;

    ClaimsPrincipal user = authState.User;

    ClaimsPrincipal x = await this.ClaimsTransformation.TransformAsync(user);



来源:https://stackoverflow.com/questions/59108861/blazor-securing-using-adfs-with-local-db-repository-how-when-to-hook-into-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!