MVC 5 OWIN - IsAuthenticated在外部登录时为false(QQ Connect)

JBu*_*uus 7 asp.net-mvc oauth-2.0 owin asp.net-mvc-5

我希望有人可以帮我解决这个问题 - 这让我很生气!:)

我正在尝试使用tinysnake的QQ Connect提供商通过QQ Connect(OAuth 2.0)进行外部登录:https://github.com/tinysnake/microsoft-owin-security-qq

一切似乎都很好 - 我可以通过我的QQ帐户登录,然后通过相应的声明等回复到我的ExternalLoginCallBack方法.我使用这些值通过IAuthenticationManager签署用户 - 一切顺利.但是 - 当我将用户重定向到另一个页面并检查他是否已登录时 - 我从IsAuthenticated值中得到一个错误的值...而我无法读取我之前设置的任何声明.

这可能是一个简单的修复 - 但我现在看不到它:)

一些代码:

AuthConfig:

public static void ConfigureAuthentication(IAppBuilder app)
{
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    // Normal cookie sign in
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        AuthenticationMode = AuthenticationMode.Active
    });

    // QQ CONNECT
    app.UseQQConnectAuthentication(
        appId: "XXXXXX",
        appSecret: "XXXXXXXXXXXXXXXXX");
}
Run Code Online (Sandbox Code Playgroud)

的AccountController:

//
// POST: /Account/ExternalLogin
[System.Web.Mvc.HttpPost]
[System.Web.Mvc.AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
    // Request a redirect to the external login provider
    return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}

//
// GET: /Account/ExternalLoginCallback
[System.Web.Mvc.AllowAnonymous]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var ctx = Request.GetOwinContext();
    var result = ctx.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie).Result;
    var claims = result.Identity.Claims.ToList();
    var name = claims.First(i => i.Type == "urn:qqconnect:name");

    claims.Add(new Claim(ClaimTypes.AuthenticationMethod, "QQ"));
    claims.Add(new Claim(ClaimTypes.Name, name.Value));

    var ci = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ExternalCookie);
    ctx.Authentication.SignIn(ci);

    // DO OTHER STUFF HERE

    return Redirect("~/");
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切似乎都进展顺利......

HomeController的:

public ActionResult Index()
{
    var model = new HomeViewModel();

    var ctx = Request.GetOwinContext();
    if (ctx.Authentication.User.Identity.IsAuthenticated)  // <-- THIS RETURNS FALSE
    {
        var claimsIdentity = User.Identity as ClaimsIdentity;
        model.Name = claimsIdentity.FindFirst(ClaimTypes.Name).Value;
        model.IsAuthenticated = true;
    }

    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

当我检查ctx.Authentication.User.Identity.IsAuthenticated时,我得到一个错误的值...我也无法检索任何声明.

我错过了什么吗?

任何帮助将不胜感激 :)

UPDATE

我通过在AccountController中执行此操作来获取代码:

public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var ctx = Request.GetOwinContext();
    var result = ctx.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie).Result;

    if (result.Identity.IsAuthenticated)
    {
        // Signed in successfully
        var claims = result.Identity.Claims.ToList();
        var name = claims.First(i => i.Type == "urn:qqconnect:name");

        //claims.Add(new Claim(ClaimTypes.AuthenticationMethod, "QQ"));
        claims.Add(new Claim(ClaimTypes.Name, name.Value));

        var id = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
        var authenticationManager = ctx.Authentication;
            authenticationManager.SignIn(id);

    }

    return Redirect("~/");
}
Run Code Online (Sandbox Code Playgroud)

但是我看到它的方式 - 在这里我使用ApplicationCookie而不是ExternalCookie进行登录......或者我完全错过了什么?这个解决方案对我有用 - 但我想知道这是否是正确的方法呢?

ste*_*kil 1

据我了解,您所经历的情况是预期的。极其简单化:

  1. 应用程序获取外部信息并使用它来创建外部cookie
  2. 外部 cookie 发送到您的应用程序,假设它只是一个临时 cookie,将用于查找有关用户的任何其他本地信息,然后转换为本地 [应用程序] cookie

有关更彻底的细分,请参阅UseCookieAuthentication 与 UseExternalSignInCookie 。