Always enter credentials without “prompt=login” in IdentityServer4

亡梦爱人 提交于 2020-01-22 02:09:08

问题


This is similar to IdentityServer4 Force User to re-enter credentials, but the solution there says to use prompt=login query string in the /authorize URL, which works, but also allows for sneaky users to remove it. Also, seeing as I'm not using .AddOpenIdConnect() the suggestion to use OnRedirectToIdentityProvider doesn't apply to me.

So how can we force the user to always enter credentials without relying on the prompt=login in the query string?


Here's my basic IdentityServer4 setup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    var builder = services.AddIdentityServer()
        .AddInMemoryIdentityResources(Config.GetIdentityResources())
        .AddInMemoryApiResources(Config.GetApis())
        .AddInMemoryClients(Config.GetClients());

    builder.AddDeveloperSigningCredential();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseHttpsRedirection();
    app.UseFileServer();
    app.UseIdentityServer();
    app.UseMvc();
}

Where my login page only has an "OK" and "Cancel" button (I don't care which user logs on yet, only that authentication was OK or not), and the controller does the following when it is authenticating the user:

public async Task<IActionResult> Post(AuthenticateViewModel model, string button)
{
    var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

    if (button == "authCancel")
    {
        if (context != null)
        {
            await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);
            return Redirect(model.ReturnUrl);
        }

        return Redirect("~/");
    }

    if (button == "authOk" && ModelState.IsValid)
    {
        if (context != null)
        {
            await _events.RaiseAsync(new UserLoginSuccessEvent("provider", "userId", "subjectId", "name"));
            await HttpContext.SignInAsync("subject", "name", new AuthenticationProperties());
            return Redirect(model.ReturnUrl);
        }
    }

    return Redirect("~/");
}

回答1:


An option could be to stick to prompt=login for all requests or based on some client setting, or a http header.

It is easy to look into the default request validator and implement your customization like the following:

public class YourCustomAuthorizeRequestValidator:ICustomAuthorizeRequestValidator
{
  public Task ValidateAsync(CustomAuthorizeRequestValidationContext context)
  {
    var request = context.Result.ValidatedRequest;    
    if (string.IsNullOrWhiteSpace(request.Raw["prompted"]))
    {
      request.Raw.Add("prompted", "true");
      request.PromptMode = OidcConstants.PromptModes.Login;
    }
    else if (request.Subject.IsAuthenticated())
    {
      request.PromptMode = OidcConstants.PromptModes.None;
    }
    return Task.CompletedTask;
  }
}

and then in your Identityserver startup:

services.AddIdentityServer()
  .AddCustomAuthorizeRequestValidator<YourCustomAuthorizeRequestValidator>();



回答2:


You should be able to achieve desired behaviour by overriding the default cookie scheme that AddIdentityServer() registers internally:

services.AddIdentityServer()...

services.AddAuthentication("CustomScheme")
    .AddCookie("CustomScheme", options =>
    {
        options.ExpireTimeSpan = ...;
    });

Make sure you add the override scheme after AddIdentityServer(), the sequence here is important due to the way ASP.Net Core DI works.



来源:https://stackoverflow.com/questions/56327921/always-enter-credentials-without-prompt-login-in-identityserver4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!