等待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上找到。
更新
这里有一个更好的解决方法。我实现了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);
}