Identity Server 4 add parameter to Login page

Viewed 575

I have a requirement to send an extra parameter from my MVC client to my Identity Server 4 UI when a user needs to authenticate. I've tried following these two articles I found which explain the concept which seems quite simple, but either method I try and use the parameter seems to get added as a parameter to the returnUrl parameter rather then the named parameter on the Login endpoint.

MVC Controller

[AllowAnonymous]
public IActionResult Register()
{
    var properties = new AuthenticationProperties() { RedirectUri = "/" };

    var connection = "YEPPERS";
    if (!string.IsNullOrEmpty(connection))
    {
        properties.Items.Add("connection", connection);
    }

    return new ChallengeResult("OpenIdConnect", properties);
}

MVC Setup.cs

.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    // SNIP OIDC SETTINGS

    options.Events = new OpenIdConnectEvents
    {
        OnRedirectToIdentityProvider = context =>
        {
            if (context.Properties.Items.ContainsKey("connection"))
            {
                context.ProtocolMessage.SetParameter("connection",
                    context.Properties.Items["connection"]);
            }

            return Task.FromResult(0);
        }
    };
});

Identity Server 4 UI Controller

[HttpGet]
public async Task<IActionResult> Login(string returnUrl, string connection)
{
    var vm = await BuildLoginViewModelAsync(returnUrl);

    return View(vm);
}

returnUrl parameter from above endpoint

enter image description here

As you can see the added parameter (connection) is in the returnUrl parameter, rather than populating the connection parameter as is what I thought would happen according to the previously mentioned articles.

1 Answers

Why wouldn't parsing the returnUrl seem right? First thing BuildLoginViewModelAsync does is parse the returnUrl in order to get some context.

private async Task<LoginViewModel> BuildLoginViewModelAsync(string returnUrl)
{
    var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

All you have to do is expand the LoginViewModel with a Connection property and get the value from the parameter:

var vm = new LoginViewModel
{
    EnableLocalLogin = local,
    ReturnUrl = returnUrl,
    Username = context?.LoginHint,
    Connection = context?.Parameters["connection"],
};
Related