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

Vivek Sasidharan

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

Nan Yu

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

如果使用的是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")]

这样,在身份服务器端,您可以通过查询字符串获取所需的身份提供信息:

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登录过程。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当提供者是组的一部分时,返回组总成员身份的计数

在内容提供者中搜索字符串的一部分

如何在Paw中将文件作为多部分请求的一部分上载?

如何传递会话ID作为Soap请求的一部分?

如何在Flask中返回图像作为GET请求响应的一部分?

如何指定间距约束作为超级视图尺寸的一部分?

作为哈希子分区的一部分,如何为键指定多个列?

Owin OAuth提供者“实体类型IdentityUser不是当前上下文模型的一部分”

Gatling - 将授权标头设置为请求的一部分

ZF2:如何将安全图像作为网页的一部分提供

身份列作为主键的一部分

如何(使用 RSpec)测试在 Rails 中发送的 HTTP 请求(作为单元测试的一部分)?

如何指定空格作为通配符字符串的一部分以批量重命名文件

如何在接口块内指定模块变量作为伪参数声明的一部分?

如何修复“查询不包含指定的表达式‘credit usd’作为聚合函数的一部分”?

作为 FROM 的一部分,在 postgres 中提供 tsvector 以进行完整搜索

将cookie作为node.js请求的一部分传递

Grails发送版本作为PUT请求的一部分

Github - 在合并作为拉取请求的一部分后清理分支

如何将JSON作为多部分POST请求的一部分发送

如何从分支的一部分创建请求请求?

Python:如何获取JSON请求但获得请求的一部分?

如何获得JSON请求但获得请求的一部分?

Promise 作为 redux 状态的一部分

使用变量作为语句的一部分

块作为块的一部分

if 条件作为 GIT 命令的一部分

UiSegmentedControl作为UILabel子类的一部分

将标题作为CURL的一部分