如何将 MVC 应用程序配置为仅 OAuth 登录

How do I configure an MVC-application to be OAuth-login only

我正在尝试将 MVC 5 应用程序配置为仅使用 Steam 登录,即没有用户注册等。我对 ASP.NET MVC 5 和 Owin 完全陌生,所以我有点吃力了解我的基本流程应该是什么。

我正在使用通过 NuGet 安装的 Owin.Security.Providers.Steam

下面列出了我的 Startup.Auth.cs 和 AccountController。您会注意到我已经实现了自定义 UserManager 和 SignInManager 以及自定义用户存储。这部分工作正常,但是当我完成用户登录后,User.Identity.IsAuthenticated 仍然是错误的。为了解决这个问题,我尝试将 cookie 身份验证添加到我的 Startup.Auth.cs,但是当我这样做时,我在我的 ExternalLoginCallback 中收到以下异常:

Line 79:             var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();

[InvalidOperationException: Sequence contains more than one element]
System.Linq.Enumerable.SingleOrDefault(IEnumerable`1 source) +4098162
Microsoft.Owin.Security.<AuthenticateAsync>d__8.MoveNext() +358

这是我的 Startup.Auth.cs:

app.CreatePerOwinContext<SteamUserManager>(SteamUserManager.Create);
app.CreatePerOwinContext<SteamSignInManager>(SteamSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
    LoginPath = new PathString("/Account/Login")
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseSteamAuthentication("XXXXXXXXXXXXXXXXXXXXX"); // My Steam key

AccountController.cs:

[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
    return ExternalLogin("Steam", returnUrl);
}

[HttpPost]
[AllowAnonymous]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
    return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
}

[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction("Login");
    }

    var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
    switch (result)
    {
        case SignInStatus.Success:
            return RedirectToLocal(returnUrl);
        case SignInStatus.Failure:
        default:
            // If the user does not have an account, then prompt the user to create an account
            return await CreateFirstTimeUser(loginInfo, returnUrl);
        }
    }
}

答案很简单。 CookieAuthenticationOptions 上的 AuthenticationType 应该是 ApplicationCookie 而不是 ExternalCookie。

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login")
});