IdentityServer SSO-受信任的应用程序 [英] IdentityServer SSO - Trusted application

查看:201
本文介绍了IdentityServer SSO-受信任的应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要对来自我的应用程序(使用ASPNET会话状态的身份提供程序)的用户进行SSO(单点登录),并将其重定向到我的另一个应用程序(服务提供程序),该应用程序配置为对IdentityServer4使用隐式流.我需要在不要求用户重新登录且不提供用户密码的情况下实现这一目标.

I need to SSO (single sign on) a user coming from an application of mine (identity provider using ASPNET Session State) and redirect them to another application of mine (service provider) that is configured to use implicit flow with IdentityServer4. I need to achieve this without requiring the user to log back in and without providing the user's password.

我最初的想法是,我可以使用身份提供商的客户端机密,以访问令牌作为查询参数将用户重定向到IdentityServer4身份验证端点,然后使用自定义验证程序或扩展授权来颁发身份令牌与服务提供商应用程序一起使用时无需提供用户密码.

My initial thought was that I could use a client secret for the identity provider to redirect the user to the IdentityServer4 authentication end point with the access token as a query parameter and then use a custom validator or extension grant to issue an identity token for use with the service provider application without needing to also provide the user's password.

我设法向身份提供者发出访问令牌,然后将用户重定向到IdentityServer4,但是事实证明,发行身份令牌对我来说很困难.我已经仔细阅读了样本和文档,至少可以说我很困惑.

I've managed to issue an access token to the identity provider and then redirect the user to IdentityServer4, but issuing an identity token has proven difficult for me. I've poured over the samples and documentation and I'm confused to say the least.

我正在寻找有关此方案的适当方法的指导,也许是C#中的综合示例.我了解到我可以使用混合流来发布访问令牌和身份令牌.我认为我最大的挣扎是如何重定向用户,并基于访问令牌向用户颁发身份令牌(即使这是可接受的方法).

I'm looking for direction on the appropriate approach to this scenario and perhaps a comprehensive example in C#. I've come to understand I can use a hybrid flow to issue an access token as well as an identity token. I think my biggest struggle is how to redirect the user and, based on the access token, issue the user an identity token (and if this is even an acceptable approach).

简而言之:我想基于对身份提供者的信任(通过客户端机密?)将用户从Application A重定向到IdentityServer4,再重定向到Application B.

Simply put: I'd like to redirect the user from Application A to IdentityServer4 to Application B based on trust with the identity provider (via client secret?).

注意:我知道这可以看作是一个基于意见的问题,但是根据我的研究,我认为只有一个最佳实践,这就是我要的.

Note: I understand this could be considered an opinion-based question, but based on my research I believe there is one single best practice and that's what I'm asking for.

推荐答案

我设法通过以下流程使它起作用:

I managed to get this working by the following flow:

  1. 在应用程序A(身份提供者)中授权用户
  2. 通过令牌端点和共享密钥从Identity Server 4获取访问令牌.
  3. 将访问令牌添加为查询字符串参数,因为标头不会在重定向时保留.
  4. 将用户重定向到接受诸如用户名之类的识别信息的Account Controller方法.此方法受定制的中间件类保护,该类检查查询字符串中是否有访问令牌参数.如果令牌存在,则将其添加到身份验证标头中;否则,将其添加到身份验证标头中.这授权用户使用此控制器方法.
  5. 然后,控制器方法将登录用户并将其重定向到/connect/authorize/login端点.
  6. 最后,登录端点将设置cookie并将用户重定向到应用程序B(服务提供商),该应用程序的URL是通过redirect_uri查询参数指定的.
  1. Authorize the user in Application A (Identity Provider)
  2. Obtain Access Token from Identity Server 4 via Token Endpoint and shared secret.
  3. Add access token as a query string parameter since headers are not preserved on redirect.
  4. Redirect the user to an Account controller method that accepts identifying information such as username. This method is protected by a custom middleware class that checks the query string for an access token parameter. If the token exists, it is added to the authentication header; this authorizes the user to hit this controller method.
  5. The controller method will then sign the user in and redirect them to the /connect/authorize/login endpoint.
  6. Finally, the login endpoint sets the cookie and redirects the user to Application B (Service Provider), whose URL is specified via the redirect_uri query parameter.

共享机密的配置:

向客户端添加适当的授予类型,机密和新作用域名称.新的作用域将有助于调试日志中的访问令牌问题(尤其是当您有多个应用程序在ID4服务器上运行时).另外,请确保将服务提供商的URL添加到客户端RedirectUris,否则您将收到无效的重定向"错误.

Add appropriate grant type, secret and new scope name to the client. The new scope will help in debugging Access token issues in your logs (especially if you have multiple applications hitting your ID4 server). Also make sure to add the Service Provider's URL to the client RedirectUris, otherwise you'll receive an "invalid redirect" error.

            AllowedGrantTypes = new List<string> { GrantType.Implicit, GrantType.ClientCredentials },
            ClientSecrets = new List<Secret> {
                new Secret(_clientSecrets.ExternalIdpSecret.Sha256(), clientID)
            },
            AllowedScopes = new List<string>
            {
                "newScopeName"
            },
            RedirectUris = new List<string>
            {
                $"http://localhost:<portnumber>"
            }

接下来,添加您的自定义中间件.

Next, add your custom middleware.

public class QueryStringOAuthBearerMiddleware
{
    private readonly RequestDelegate next;

    public QueryStringOAuthBearerMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        this.BeginInvoke(context);
        await this.next.Invoke(context);
        this.EndInvoke(context);
    }

    private void BeginInvoke(HttpContext context)
    {
        if (context.Request.Query.ContainsKey("accesstokenparametername"))
        {
            var accessToken = context.Request.Query.First(p => p.Key == "accesstokenparametername");

            if (!string.IsNullOrEmpty(accessToken.Value))
            {
                context.Request.Headers.Add("Authorization", "Bearer " + accessToken.Value);
            }
        }
    }

    private void EndInvoke(HttpContext context)
    {
    }
}

并将中间件添加到您的配置中.

And add the middleware to your configuration.

        app.UseMiddleware<QueryStringOAuthBearerMiddleware>();

创建您的登录方法.

    [HttpGet]
    [Authorize]
    public async Task<IActionResult> Login2(string userName, string returnURL)
    {
        await _httpContextWrapper.SignInAsync(userName);

        return Redirect(returnURL);
    }

客户端应用程序(IDP)的配置:

您的客户端代码应如下所示:

Your client side code should look like this:

var disco = await DiscoveryClient.GetAsync("http://localhost:<portnumber>");
var tokenClient = new TokenClient(disco.TokenEndpoint, "clientIdentifier", "IUsedAGuidHere");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("newScopeName");

var redirectURL = string.Format("http://localhost:2228/account/Login2?userName=<UserIDValue>&returnURL={1}&accesstokenparametername={0}",
            tokenResponse.AccessToken,
            Server.UrlEncode(
                string.Format("/connect/authorize/login?client_id={3}&redirect_uri={2}&response_type=id_token%20token&scope=<ImplicitFlowScopes>&state={0}&nonce={1}",
                CryptoRandom.CreateUniqueId(),
                CryptoRandom.CreateUniqueId(),
                Server.UrlEncode("http://localhost:<PortNumber>"),
                "ClientIdentifier")));

Response.Redirect(redirectURL, false);

注意:请理解您将无法按原样使用此代码并使其正常工作.我已经对其进行了大量修改,以保护我的资源的安全性.

Note: Please understand you won't be able to take this code AS-IS and make it work. I've heavily modified it to protect the security of my resources.

这篇关于IdentityServer SSO-受信任的应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆