【问题标题】:How to make ASP.NET create authenticated session with Owin OpenId Connect library?如何使 ASP.NET 使用 Owin OpenId Connect 库创建经过身份验证的会话?
【发布时间】:2017-07-10 08:29:47
【问题描述】:

在网上搜索了大量示例后,我正在努力解决似乎相当简单的要求。

我正在尝试扩展一个现有的使用表单身份验证的 ASP.NET 应用程序,以便它可以使用 OpenID Connect 进行身份验证以及来自身份提供者的一些角色信息。特别是我正在与我无法控制的现有托管身份提供程序集成。

我将 ASP.NET MVC 与 OpenIdConnect 的 Owin 组件一起使用。即,

Microsoft.Owin.Security
Microsoft.Owin.Security.Cookies
Microsoft.Owin.Security.OpenIdConnect

我成功地能够:

  1. 在 Web 浏览器中 - 导航到使用 [Authorize] 属性保护的控制器方法
  2. Owin 组件正确地将我重定向到身份提供程序,我可以在其中进行身份验证,然后我被重定向回我的应用程序(注意:我的身份提供程序要求传入 redirect_uri,因此我目前将其设置为OpenIdConnectAuthenticationOptions 启动配置的一部分。)
  3. 当重定向回我的应用程序时,我可以看到 access_token 和 id_token 作为查询字符串的一部分。此外,我已经能够使用 access_token 来调用用户信息端点并正确地获取有关使用该令牌的用户的信息。

到目前为止一切顺利!但是。

我未能掌握的内容以及我见过的大多数 Owin 示例似乎都无法解释:如果有的话,需要什么额外配置才能让 ASP.NET 在我的基于应用程序的应用程序中实际创建经过身份验证的会话从身份提供者重定向回我的应用程序。

我从文档中得到的一般感觉是,我不应该在 Owin 库中进行额外的配置——一旦我将系统配置为使用 cookie 身份验证和 OpenId Connect 库——它应该只是工作。然而,这似乎并不像看起来那么容易。我猜我错过了什么。

一些具体的考虑/观察:

  1. 我发现的许多示例不需要在 OpenIdConnectAuthenticationOptions 中设置 RedirectUri,但我的身份提供程序要求每次都设置此参数。
  2. 我发现很少有示例解释了由于 RedirectUri 被命中而触发的控制器方法是应该使用 [Authorize] 保护还是保持匿名。在我的测试中,如果我将其标记为 [Authorize],我将进入无限重定向循环。如果我保持匿名,我可以在请求信息中看到令牌,但永远不会创建 ASP.NET 会话。例如,Request.IsAuthenticated 始终为 false。
  3. 作为测试,我在几个 OpenIdConnectAuthenticationNotifications() 事件中设置了断点,目前我只看到我的代码中断了 RedirectToIdentityProvider 事件,而其他的似乎都没有命中 - 这让我相信我'没有配置这个权利。
  4. 根据我发现的建议,我已在 web.config 中以这种方式设置身份验证节点,但如果我排除此节点似乎没有什么区别。

    <system.web>
        <authentication mode="None" />
    </system.web>
    

总结一下:

  1. 我是否需要专门编写代码来处理来自身份提供程序的返回重定向,以便为给定用户手动设置 ASP.NET 会话(cookie 等)?和
  2. 如果是这样,此代码应该进入由于 RedirectUri 被命中而调用的控制器方法中,还是应该进入 OpenIdConnectAuthenticationNotifications() 中可用的“通知”事件之一?

最后,如果我不应该在从身份提供者重定向后手动设置经过身份验证的会话(如果它应该自动工作),对于此配置的常见错误有什么建议吗?

为了完整性:

My Owin pipeline 启动配置方法:

public void Configuration(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions());

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            //no problems on these as far as I can tell
            ClientId = "client_id_string",
            ClientSecret = "client_secret_string",
            Authority = "url_to_identity_provider",
            Scope = "email name etc",

            //I'm properly redirected to this URL but not sure 
            //if I should need to create the session manually
            RedirectUri = "http://mymachine/mymvcapp/authorize",

            //this causes the redirection to come with the access_token, 
            //which is valid
            ResponseType = "token",
            SignInAsAuthenticationType = "Cookies",
            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                RedirectToIdentityProvider = (context) =>
                {
                    //I'm able to break into this method
                    return Task.FromResult(0);
                },
                MessageReceived = (context) =>
                {
                    //doesn't seem to run this line
                    return Task.FromResult(0);
                },
                SecurityTokenReceived = (context) =>
                {
                    //doesn't seem to run this line
                    return Task.FromResult(0);
                },
                SecurityTokenValidated = (context) =>
                {
                    //doesn't seem to run this line
                    return Task.FromResult(0);
                },
                AuthorizationCodeReceived = (context) =>
                {
                    //doesn't seem to run this line
                    return Task.FromResult(0);
                },
                AuthenticationFailed = (context) =>
                {
                    //doesn't seem to run this line
                    return Task.FromResult(0);
                },
            },
        });
}

我正确启动登录流程的安全方法:

[Authorize]
public class HomeController : Controller
{
    //I'm sent to the login flow the first time this is hit
    public ActionResult Index()
    {
        return View();
    }
}

我在 RedirectUri 上的方法确实被调用但确实表明创建了 ASP.NET 身份验证会话:

public class AuthorizeController : Controller
{
    // [Authorize] -- currently this Authorize attribute is turned off 
    //so the method is anonymous. 

    //If I turn that back on, I get infininte redirect loops to 
    //the Identity Provider
    public ActionResult Index()
    {
        //the incoming request to this controller method from the 
        //identity provider DOES include valid access_token and id_token 
        //(which can be used against the user info endpoint) but does not 
        //create a valid ASP.NET session for my web app

        //Request.IsAuthenticated is always false

        //should there be a manual creation of the ASP.NET 
        //session/cookie information in this controller method?

        //note: to me it would make most sense if this attribute was not
        //anonymous since it's unlikely that the Request would ever appear
        //as IsAuthenticated == true, but if you read the entire question
        //it will be clear why I'm trying this method with anonymous access

        return View();
    }
}

【问题讨论】:

    标签: c# asp.net authentication owin openid-connect


    【解决方案1】:

    正如您所发现的,您不能将 [Authorize] 属性放在外部服务器用来通知您用户已授权的方法上 - 会话尚未授权,您只是被通知它 应该。

    幸运的是,创建该会话并不困难: How can I manually create a authentication cookie instead of the default method?

    (我很确定您必须自己使用基本的 Microsoft Owin 东西来完成这项工作 - 如果您愿意,您总是可以自己完成。)

    【讨论】:

      猜你喜欢
      • 2019-09-11
      • 2015-12-25
      • 2016-06-28
      • 2020-03-11
      • 2016-03-07
      • 1970-01-01
      • 2012-09-05
      • 2018-10-11
      • 2020-05-28
      相关资源
      最近更新 更多