Multiple Identities in ASP.NET Core 2.0

Multiple Identities in ASP.NET Core 2.0

After looking through the ASP.NET Core source code on github, a second identity could be added using this extension method:

using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Text;

namespace Whatever
{
public static class IdentityExtensions
{
public static IdentityBuilder AddSecondIdentity<TUser, TRole>(
this IServiceCollection services)
where TUser : class
where TRole : class
{
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
services.TryAddScoped<UserManager<TUser>, AspNetUserManager<TUser>>();
services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();
services.TryAddScoped<RoleManager<TRole>, AspNetRoleManager<TRole>>();

return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
}
}
}

How to add more than one identity store in aspnet core identity?

After looking through the ASP.NET Core source code on github, a second identity could be added using this extension method:

using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Text;

namespace Whatever
{
public static class IdentityExtensions
{
public static IdentityBuilder AddSecondIdentity<TUser, TRole>(
this IServiceCollection services)
where TUser : class
where TRole : class
{
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
services.TryAddScoped<UserManager<TUser>, AspNetUserManager<TUser>>();
services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();
services.TryAddScoped<RoleManager<TRole>, AspNetRoleManager<TRole>>();

return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
}
}
}

https://stackoverflow.com/a/47434573/8006943

Can I Combine Identities from two Authentication Schemes in ASP.NET Core 3?

Further research and tinkering has led me to a solution. First, I discovered that I needed the two authentication schemes to write to separate cookies. I then made sure the DocuSign scheme used the new cookie as its SignInScheme.

.AddCookie("DSCookie")
.AddOAuth("DocuSign", options =>
{
options.SignInScheme = "DSCookie";
//further DocuSign options
}

I also learned that the Authorize tag works as an OR statement (if you have CAS OR DocuSign, you are authorized for this action), yet it will pass along all valid identities permitted by the scheme (You have CAS and you have DocuSign? Bring both Identities in with you). Thus, the second part of my solution has a single action that requires DocuSign authentication, prompting the necessary challenge. Then, I move to actions that have both authentication schemes, and both Identities are brought along properly.

EDIT: To elaborate per Dmitriy's request

[Authorize(AuthenticationSchemes = "DocuSign")]
public ActionResult Index()
{
return RedirectToAction("Control");
}

[Authorize(AuthenticationSchemes = "DocuSign,CAS")]
public ActionResult Control()
{
//relevant code
}

I click on a link to go to the Index action. Since I currently do not have a valid DocuSign Identity, it performs the necessary prompt and takes me to the sign in screen. If I linked directly to Control, Authentication would see that I currently had a valid CAS Identity, so would approve my access, even though I did not yet have the DocuSign Identity.

After the sign in, when I arrive at the Index function, only the DocuSign Identity is currently available. I then redirect to Control. That function verifies I have at least one of the specified Identities, grants me access, and passes along any of the listed Identities I currently possess. Thus, inside Control, I can grab information from both CAS and DocuSign.

Application without identity but added later now secondary authentication is not working

You are trying to add identity service twice in your Startup.cs which is incorrect. So the quick solution is you have to remove either of one which will remove the exception you are having with.

So remove services.AddDefaultIdentity which you have added earlier so it will work accordingly.

Note: Deleting either of the addDefaultIdentities will work. You just can't have it in both locations in your case its creating the
issue.

.Net Core 2 OpenID Connect Authentication and multiple Identities

An important thing to know when using the OpenID Connect scheme is that the scheme will never work on its own. In pretty much every example you can find you will see it combined with the cookie scheme. The reason for this is very simple: OIDC is for authenticating the user with an external authentication provider. But that authentication is only temporary. In order to store it locally within your application, you need to sign in your user. This is usually done with the cookie authentication scheme (although it could be done in other ways).

The authentication flow for an application that uses OIDC and cookies usually works like this:

  1. User accesses your application.
  2. Authentication: The cookie scheme, the default authentication scheme, will attempt to authenticate the user. If there is no cookie, the handler will challenge the authentication.
  3. Challenge: The OIDC scheme, the default challenge scheme, will challenge the user and redirect to the external authentication provider.
  4. The user will authenticate with the external authentication provider and will get redirected back to the application.
  5. Challenge callback: The OIDC scheme will take the response from the external authentication provider, complete the challenge and create a claims principal.
  6. Sign-in: The OIDC scheme will sign in that principal with its configured sign-in scheme (the cookie scheme).
  7. The cookie scheme will sign in the user and create a cookie that is persisted in the user’s browser.
  8. On a subsequent request to your application, the user will include a valid cookie, so the cookie schem can successfully authenticate the user, without having to challenge the OIDC scheme again.

So assuming that everything worked properly, the OIDC scheme will not be involved again in the authentication. Instead, the identity from the cookie will be used every time.

You can use this for your purpose to expand the principal that the OIDC scheme created with additional claims, before it is signed in and persisted by the cookie scheme. You could do this using a custom sign-in scheme that sits between the OIDC and cookie schemes, or you could simply attach to an authentication event of the OIDC scheme that is invoked after the challenge is completed but before the sign-in occurs.

You can use the TicketReceived event for this purpose:

public void ConfigureServices(IServiceCollection services)
{
// …

services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
// …

options.Events.OnTicketReceived = OnOpenIdConnectTicketReceived;
});
}

public static Task OnOpenIdConnectTicketReceived(TicketReceivedContext context)
{
if (context.Principal.Identity is ClaimsIdentity identity)
{
identity.AddClaim(new Claim("foo", "bar"));
}

return Task.CompletedTask;
}

Add ASP.NET CORE Identity to existing multi-project solution

Yes I can migrate now after removing the unnecessary statement in the Up() and Down() methods. If there are multiple projects in the solution, the project that would not be compiled successfully can be unloaded, so that EF Migration would be able to compile the solution to migrate.

Extending IdentityUser in Asp.Net Core Identity 2.0 when it's a NuGet package

that blog is specifically talking about UI elements, whereas you seem to be asking about back-end code...

If you just want to add some custom stuff to the User model, this is already supported:
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-2.2

Basically you can create a custom class which derives (inherits from) IdentityUser, add custom properties to this, then when setting up Identity you can use this rather than the stock IdentityUser.



Related Topics



Leave a reply



Submit