Skip to content
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

Multiple Authentication Scheme including Client Certificate and Identity User #29

Closed
akhterm opened this issue Jun 4, 2019 · 2 comments

Comments

@akhterm
Copy link

akhterm commented Jun 4, 2019

After doing Client Certificate X.509 authentication, how to authenticate Client Certificate-Id against AspNetUsers table in Database.

If I put SignInManager with OnValidateCertificate, it is getting called on every request and SignInManager is signing User on every request.

Please advise how to call SignInManager only once for authentication with AspNetUsers. Please note Client Certificate-Id is stored as UserName in AspNetUsers.
Apologize if its annoying you

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddDefaultIdentity<ApplicationUser>()
        .AddRoles<IdentityRole>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
        .AddCertificate(options =>
        {
            options.Events = new CertificateAuthenticationEvents
            {
                OnValidateCertificate = context =>
                {
                    var claims = new[]
                    {
                        new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer),
                        new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer)
                    };

                    context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
                    context.Success();

                    return Task.CompletedTask;
                }
            };
        });

    services.AddMvc(config =>
    {
        var policy = new AuthorizationPolicyBuilder()
                         .RequireAuthenticatedUser()
                         .Build();
        config.Filters.Add(new AuthorizeFilter(policy));
    });
}`
@blowdart
Copy link
Owner

blowdart commented Jun 5, 2019

Oh interesting. Is there a reason that the certificate can't contain the user information and you need to go to a database to replace the generated principal? Identity wasn't meant to be used outside of cookie auth.

The problem you have here is that yes, certificate validation is called on every request. It's an unfortunate side effect of trying to make this cross compatible, and configurable in the normal asp.net core style.

The only thing I can think of is to cache the user information you get back from identity's signin manager in redis or other in memory cache, and use the sha256 hash of the raw data of the certificate as the key, then you'd miss the database hit. You'd have to clear the cache after a while if you want to reflect changes of course.

@akhterm
Copy link
Author

akhterm commented Jun 5, 2019

Barry Sir, Thanks for your valuable suggestion & time.
Implementing Caching of User Information as suggested.
I don't know specific reason why certificates do not contains User Information.

@akhterm akhterm closed this as completed Jun 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants