Using Multiple Authentication Schemes In ASP.NET Core 3.1?

Solution:

After doing some research, I found the solution in ASP.NET core Authorization documentation in an article with the title “Authorize with a specific scheme in ASP.NET Core”.

Based on the mentioned article in Microsoft ASP .NET core documentation, In some scenarios, such as Single Page Applications (SPAs), it’s common to use multiple authentication methods. For example, the app may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests.

An authentication scheme is named when the authentication service is configured during authentication. For example:

public void ConfigureServices(IServiceCollection services)
{
    // Code omitted for brevity

    services.AddAuthentication()
        .AddCookie(options => {
            options.LoginPath = "/Account/Unauthorized/";
            options.AccessDeniedPath = "/Account/Forbidden/";
        })
        .AddJwtBearer(options => {
            options.Audience = "http://localhost:5001/";
            options.Authority = "http://localhost:5000/";
        });

.....

In the preceding code, two authentication handlers have been added: one for cookies and one for the bearer.

Selecting the scheme with the Authorize attribute

[Authorize(AuthenticationSchemes = 
    JwtBearerDefaults.AuthenticationScheme)]
public class MixedController : Controller

In the preceding code, only the handler with the “Bearer” scheme runs. Any cookie-based identities are ignored.

This is the solution that solved my problem and I thought it would be good to share it with you guys for those who need this.

 

Multiple Authentication Schemes in .Net Core 3.1 or .Net 5.0

Startup.cs

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                    .AddCookie(x =>
                    {
                        x.LoginPath = "/";
                        x.ExpireTimeSpan = TimeSpan.FromMinutes(Configuration.GetValue<int>("CookieExpiry"));
                    })
                    .AddJwtBearer(x =>
                    {
                        x.RequireHttpsMetadata = false;
                        x.SaveToken = true;
                        x.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuerSigningKey = true,
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetValue<string>("JWTSecret"))),
                            ValidateIssuer = false,
                            ValidateAudience = false
                        };
                    });

            services.AddAuthorization(options =>
            {
                var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme);
                defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
                options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
            });

....

/api/auth/login

public async Task<AuthenticationResult> Login([FromForm] string userName, [FromForm] string password, [FromHeader] string authmode = "")
{
    if (userName != "demo" || password != "demo")
        return new AuthenticationResult { HasError = true, Message = "Either the user name or password is incorrect." };

    var claims = new Claim[]
    {
        new Claim(ClaimTypes.Name, userName)
    };
    

    if(authmode?.ToLower() == "token")
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(_config.GetValue<string>("JWTSecret"));
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(claims, "JWT"),
            Expires = DateTime.UtcNow.AddMinutes(_config.GetValue<int>("JWTExpiry")),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        var jwt = tokenHandler.WriteToken(token);
        return new AuthenticationResult { Token = jwt };
    }
    else
    {
        ClaimsPrincipal princ = new ClaimsPrincipal(new ClaimsIdentity(claims, "COOKIE"));
        await HttpContext.SignInAsync(princ);
        return new AuthenticationResult();
    }
}

OUTPUT

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories