简体   繁体   中英

Identity Server 4 Adding claims after authentication from a UI

I'm implementing Identity Server 4 in an MVC Core app. I have Azure Active Directory as an external provider and all this is so far working fine. I've also implemented the QuickStart UI (as per https://github.com/IdentityServer/IdentityServer4.Quickstart.UI#quickstart-ui-for-identityserver4 )

I want to add a step in this process, before redirecting back to the client, where a user interface presents a list of options to select from, with the result of this being added as a claim that is then available in the client. The way I see this is by deferring the Redirect that occurs at line 143 in the ExternalController ( https://github.com/IdentityServer/IdentityServer4.Quickstart.UI/blob/main/Quickstart/Account/ExternalController.cs )

I have tried redirecting to a custom action and taking user input, like below:

[HttpGet]
public async Task<IActionResult> MakeAChoice(string returnUrl)
{
     //simple view model to maintain the returnUrl
     var vm = BuildMakeAChoiceViewModel(returnUrl);
     return View(vm);
}

[HttpPost]
public async Task<IActionResult> MakeAChoice(MakeAChoiceViewModel model, string choice)
{
     //method one:
     HttpContext.User.Claims.Append(new Claim("chosen_value", choice));

     //method two:
     HttpContext.User.Identities.FirstOrDefault().AddClaim(new Claim("chosen_value", choice));
     return Redirect(model.ReturnUrl);
}

The Redirect works just fine, so i'm able to interrupt the overall process and still complete the chain and return to the client app without a problem. Unfortunately, this Claim does not make it's way back to the client.

The reason for wanting this UI driven step is that the app with Identity Server implemented, contains it's own DB with details the app needs, but is only accessible to those who can be authenticated by Azure first. The data for this additional Claim is also wildly subject to change, which is why the user choice here is important.

EDIT: The answer provided got me past that one hurdle, unfortunately I was still unable to retrieve the custom Claim in the client. It turns out that from .net core 2.0 onwards, most of the claim types are automatically stripped out to save on bloat. You have to specifically map the ones you're after in the client's OpenID Connect setup. See this topic: https://github.com/aspnet/Security/issues/1449

Just manipulating the current user like you do it here:

HttpContext.User.Identities.FirstOrDefault().AddClaim(new Claim("chosen_value", choice));

Will not affect the signed-in user or its token/cookies. You need to add your own claims before you call:

await HttpContext.SignInAsync(isuser, props);

As an alternative, if the claims you want to add is specific to one of or a few clients, you could do this client-side by adding your own OnTicketReceived event-handler, like:

options.Events = new OpenIdConnectEvents
{
    OnTicketReceived = e =>
    {
        if (!e.Principal.HasClaim(c => c.Type == "bonuslevel"))
        {
            //Lookup bonus level.....
            e.Principal.Identities.First().AddClaim(new Claim("bonuslevel", "12345"));
        }
        return Task.CompletedTask;
    }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM