How to retrieve all Claims from multiple schemes?

50 Views Asked by At

There is a need to do multistage authentications. For example, first login as a plain user with scheme1 (longer enough lifespan of cookie) and an additional login as a super user with scheme2 (short lived cookie).

Consider the following trivial example to simulate the problem. Navigating to /info just produces Claim from scheme1 instead of from both schemes (that I expect).

enter image description here

using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
const string scheme1 = "cookie1";
const string scheme2 = "cookie2";
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(scheme1)
                .AddCookie(scheme1)
                .AddCookie(scheme2);
var app = builder.Build();
app.UseAuthentication();
app.MapGet("/info", (HttpContext ctx) => string.Join(", ", ctx.User.Claims.Select(c => $"[{c}]")));
app.MapGet("/login", async (HttpContext ctx) =>
{
    await ctx.SignInAsync(scheme1, new (new ClaimsIdentity([new("key1", "val1")], "id1")));
    await ctx.SignInAsync(scheme2, new (new ClaimsIdentity([new("key2", "val2")], "id2")));
    return "multistage login simulation";
});
app.Run();
1

There are 1 best solutions below

0
On BEST ANSWER
builder.Services.AddAuthentication(scheme1)

The call to AddAuthentication here configures the default AuthN scheme as scheme1. Without further configuration, the UseAuthentication call/middleware uses only this scheme, and so only its claims (key1 => value) are populated.

To configure a specific endpoint to use both AuthN schemes, you can configure an AuthZ policy and apply that to the endpoint. Here's an example of how to configure the policy:

builder.Services.AddAuthorizationBuilder().AddPolicy(
    "Multistage",
    o => o.AddAuthenticationSchemes(scheme1, scheme2)
          .RequireAuthenticatedUser());

Here's an example of how to apply the policy to your /info endpoint:

app.MapGet(
        "/info",
        (HttpContext ctx) => string.Join(", ", ctx.User.Claims.Select(c => $"[{c}]")))
    .RequireAuthorization("Multistage");