等待SignInManager.ExternalSignInAsync上的ArgumentNullException(l

本文关键字:ArgumentNullException 上的 SignInManager ExternalSignInAsync 等待 | 更新日期: 2023-09-27 18:20:24

我正在使用带有ASP.NET Identity的facebook身份验证。我可以通过facebook进行身份验证,但当我调用SignInManager.ExternalSignInAsync()时,当它向身份添加声明时,我会得到ArgumentNullException。这是堆栈跟踪:

[ArgumentNullException: Value cannot be null.
Parameter name: value]
   System.Security.Claims.Claim..ctor(String type, String value, String valueType, String issuer, String originalIssuer, ClaimsIdentity subject, String propertyKey, String propertyValue) +10798181
   System.Security.Claims.Claim..ctor(String type, String value) +34
   Microsoft.AspNet.Identity.<CreateAsync>d__0.MoveNext() +759
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   Microsoft.AspNet.Identity.Owin.<SignInAsync>d__2.MoveNext() +199
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   Microsoft.AspNet.Identity.CultureAwaiter.GetResult() +23
   Microsoft.AspNet.Identity.Owin.<SignInOrTwoFactor>d__23.MoveNext() +1279
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   Microsoft.AspNet.Identity.Owin.<ExternalSignInAsync>d__1d.MoveNext() +794
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24
   SteamAchievements.Web.Controllers.<ExternalLoginCallback>d__2.MoveNext() in C:'projects'facebooksteamachievements'SteamAchievements.Web'Controllers'AccountController.cs:48
   System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93
   System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52
   System.Web.Mvc.Async.TaskAsyncActionDescriptor.EndExecute(IAsyncResult asyncResult) +84
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeAsynchronousActionMethod>b__36(IAsyncResult asyncResult) +17
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
   System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d() +50
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
   System.Web.Mvc.Async.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f() +225
   System.Web.Mvc.Async.<>c__DisplayClass33.<BeginInvokeActionMethodWithFilters>b__32(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
   System.Web.Mvc.Async.<>c__DisplayClass2b.<BeginInvokeAction>b__1c() +26
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +100
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallEndDelegate(IAsyncResult asyncResult) +10
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +49
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +13
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +39
   System.Web.Mvc.Controller.<BeginExecute>b__15(IAsyncResult asyncResult, Controller controller) +12
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +29
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +21
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.End() +54
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +31
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
   System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +129

据我所知,我已经正确配置了所有内容。最棒的是,没有一个声明的类型或名称为null。这是我在StartUp.Auth:中的配置

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    LoginPath = new PathString("/Account/Login"),
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
if (!string.IsNullOrEmpty(Settings.Default.FacebookAppId))
{
    var options = new FacebookAuthenticationOptions
    {
        Provider = new FacebookAuthenticationProvider
        {
            OnAuthenticated = context =>
            {
                context.Identity.AddClaim(new Claim("AccessToken", context.AccessToken));
                return Task.FromResult(0);
            }
        },
        AppId = Settings.Default.FacebookAppId,
        AppSecret = Settings.Default.FacebookAppSecret
    };
    app.UseFacebookAuthentication(options);
}

这是ExternalLoginCallback操作。这很简单。如果外部登录成功,则在不存在用户的情况下创建一个用户,在不存在的情况下添加一个登录。

[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction("Login");
    }
    var user = await UserManager.FindByNameAsync(loginInfo.Login.ProviderKey);
    if (user == null)
    {
        long facebookId = Convert.ToInt64(loginInfo.Login.ProviderKey);
        user = new steam_User {UserName = loginInfo.Login.ProviderKey, FacebookUserId = facebookId};
        var createResult = await UserManager.CreateAsync(user);
        if (!createResult.Succeeded)
        {
            AddErrors(createResult);
            return View("ExternalLoginFailure");
        }
    }
    var logins = await UserManager.GetLoginsAsync(user.Id);
    if (!logins.Any())
    {
        var addResult = await UserManager.AddLoginAsync(user.Id, loginInfo.Login);
        if (!addResult.Succeeded)
        {
            AddErrors(addResult);
            return View("ExternalLoginFailure");
        }
    }
    // here's where the exception is thrown
    await SignInManager.ExternalSignInAsync(loginInfo, true);
    return RedirectToLocal("~/");
}

如果我能进入ExternalSignInAsync(),那就太好了,但我做不到。弄清楚如何做到这一点将是一个良好的开端。

我错过了什么?

如果更多的源代码有帮助,那么该项目是开源的,可以在GitHub上找到。

等待SignInManager.ExternalSignInAsync上的ArgumentNullException(l

更新

这里有一个更好的解决方法。我实现了ClaimsIdentityFactory,并且我的实现没有抛出ArgumentNullException

private class ApplicationIdentityFactory : ClaimsIdentityFactory<steam_User, int>
{
    public async override Task<ClaimsIdentity> CreateAsync(UserManager<steam_User, int> manager, steam_User user, string authenticationType)
    {
        var claims = new[]
                     {
                         new Claim(UserIdClaimType, user.Id.ToString()),
                         new Claim(UserNameClaimType, user.UserName)
                     };
        var identity = new ClaimsIdentity(claims, authenticationType, UserNameClaimType, RoleClaimType);
        if (manager.SupportsUserRole)
        {
            var roles = await manager.GetRolesAsync(user.Id);
            identity.AddClaims(roles.Select(r => new Claim(RoleClaimType, r)));
        }
        if (manager.SupportsUserClaim)
        {
            identity.AddClaims(await manager.GetClaimsAsync(user.Id));
        }
        return identity;
    }
} 

这是我的解决方法。我不喜欢它,但它有效。如果ExternalSignInAsync失败,它将依靠使用FormsAuthentication api创建身份验证cookie。

try
{
    await SignInManager.ExternalSignInAsync(loginInfo, true);
}
catch (Exception)
{
    // For now, here's my work around
    FormsAuthentication.SetAuthCookie(user.UserName, true);
}
相关文章:
  • 没有找到相关文章