IdentityServer4:如何指定身份提供者作为授权请求的一部分?

时间:2019-03-20 06:13:06

标签: asp.net-core .net-core identityserver4

我已经在项目中使用外部提供程序实现了IdentityServer4。现在,当请求一个受限制的页面时,该用户将被重定向到我的IdentityServer登录页面,他可以在其中输入用户名和密码,或者使用Google或Facebook登录。如何从客户端指定要使用哪个身份提供者,以便我的身份服务器将直接重定向到特定提供者,而无需显示登录页面?

1 个答案:

答案 0 :(得分:1)

您可以将自定义参数传递给授权端点。

如果使用的是OpenID Connect中间件,则可以将值添加到OnRedirectToIdentityProvider函数的授权请求的查询字符串中:

options.Events.OnRedirectToIdentityProvider = async n =>
            {
                var headerValue = n.HttpContext.Request.Headers["X-idp"];

                n.ProtocolMessage.SetParameter("X-idp", headerValue.ToString());

                await Task.FromResult(0);
            };

您可以创建自定义CustomAuthorizeAttribute来传递您要登录的身份提供者:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    private readonly string _idp;

    public CustomAuthorizeAttribute(string idp)
    {
        _idp = idp;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        context.HttpContext.Request.Headers.Add("X-idp", _idp);
    }
}

在您的控制器中:

[CustomAuthorizeAttribute("AAD")]

因此,在Identity Server端,您可以通过查询字符串获取所需的Identity提供信息:

AccountController.cs(ASP.Net身份):

[Authorize]
[Route("[controller]/[action]")]
public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IEmailSender _emailSender;
    private readonly ILogger _logger;
    private readonly IIdentityServerInteractionService _interaction;

    public AccountController(
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        IEmailSender emailSender,
        ILogger<AccountController> logger, IIdentityServerInteractionService interaction)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
        _logger = logger;
        _interaction = interaction;
    }

    [TempData]
    public string ErrorMessage { get; set; }

    [HttpGet]
    [AllowAnonymous]
    public async Task<IActionResult> Login(string returnUrl = null)
    {

        var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
        var idp = context.Parameters["X-idp"];

        var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
        var properties = _signInManager.ConfigureExternalAuthenticationProperties(ipd, redirectUrl);
        return Challenge(properties, idp);

        //var customId = HttpContext.Request.Query["X-CustomId"].ToString();
        //var queryString = HttpContext.Request.Query["returnUrl"].ToString();
        //// Clear the existing external cookie to ensure a clean login process
        //await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

        //ViewData["ReturnUrl"] = returnUrl;
        //return View();
    }

    .....
}

在上面的代码示例中,如果您具有像这样的外部提供程序,它将使用IIdentityServerInteractionService方法GetAuthorizationContextAsync来获取值。

services.AddAuthentication()
   .AddOpenIdConnect("AAD", "Azure Active Directory", options =>
   {
       options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
       options.SignOutScheme = IdentityServerConstants.SignoutScheme;
       options.Authority = "https://login.microsoftonline.com/xxxx.onmicrosoft.com";
       options.ClientId = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
       options.Scope.Add("openid");

   });

它将通过名称AAD找到该身份验证架构,并启动Azure AD登录过程。