尝试请求身份验证令牌时发生 ArgumentNullException
ArgumentNullException occurring when trying to request authentication token
所以我正在尝试使用 OWIN 在 ASP.NET 中实现一个非常基本的 oauth 授权服务器。
这是我的来源:
public class AuthorizationConfig {
private const string WebClientId = "WebClient";
private const string WebClientSecret = "WebClientSecret";
public static void Configure(IAppBuilder app) {
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions() {
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(8),
AllowInsecureHttp = true,
Provider = new OAuthAuthorizationServerProvider() {
OnValidateClientAuthentication = context => {
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret))
{
if (clientId == WebClientId && clientSecret == WebClientSecret)
{
return Task.FromResult(context.Validated(clientId));
}
}
context.SetError("invalid_client", "Client credentials provided are invalid.");
return Task.FromResult<object>(null);
},
OnGrantResourceOwnerCredentials = context => {
var userName = context.UserName;
var password = context.Password;
var clientId = context.ClientId;
//validate resource owner credentials
if (userName == "admin" && password == "password" && clientId == WebClientId)
{
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim("username", userName));
identity.AddClaim(new Claim("clientId", clientId));
return Task.FromResult(context.Validated(identity));
}
context.SetError("invalid_grant", "Resource owner credentials are invalid.");
return Task.FromResult<object>(null);
}
}
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
现在每次我尝试向 host/token 发送 post 时,我可以在调试时看到代码成功执行了 context.Validated 方法,但在 return响应,我得到一个 ArgumentNullException:值。还有其他人遇到这个问题吗?
编辑:这是我得到的堆栈跟踪
[ArgumentNullException: Value cannot be null.
Parameter name: value]
System.IO.BinaryWriter.Write(String value) +11937097
Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer.Write(BinaryWriter writer, AuthenticationTicket model) +97
Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer.Serialize(AuthenticationTicket model) +161
Microsoft.Owin.Security.DataHandler.SecureDataFormat`1.Protect(TData data) +45
Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext.SerializeTicket() +16
Microsoft.Owin.Security.OAuth.<InvokeTokenEndpointAsync>d__22.MoveNext() +4114
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +25
Microsoft.Owin.Security.OAuth.<InvokeAsync>d__0.MoveNext() +1109
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Security.Infrastructure.<Invoke>d__0.MoveNext() +383
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__5.MoveNext() +187
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Security.Infrastructure.<Invoke>d__0.MoveNext() +561
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__5.MoveNext() +187
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<DoFinalWork>d__2.MoveNext() +185
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +69
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +64
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +380
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
我通过使用 AuthenticationType 初始化 ClaimsIdentity 解决了这个问题。不确定这究竟是如何解决堆栈跟踪的,但我不再遇到运行时错误。
对于那些在尝试通过构造函数(来自 ClaimsIdentity 和 手动创建 AuthenticationTicket 时遇到相同问题的人AuthenticationProperties),正如 MS 样板代码在 ApplicationOAuthProvider.cs 中所做的那样:
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
在我的例子中,AuthenticationProperties 是从字典创建的:
public static AuthenticationProperties CreateProperties(UserInfoViewModel userInfo)
{
IDictionary<string, string> data = userInfo.ToDictionary();
return new AuthenticationProperties(data);
}
事实证明,字典中有 key/value 对 null 值,这破坏了 Owin 管道中的令牌序列化。从字典中删除这些项目解决了这个问题。
所以我正在尝试使用 OWIN 在 ASP.NET 中实现一个非常基本的 oauth 授权服务器。
这是我的来源:
public class AuthorizationConfig {
private const string WebClientId = "WebClient";
private const string WebClientSecret = "WebClientSecret";
public static void Configure(IAppBuilder app) {
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions() {
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromHours(8),
AllowInsecureHttp = true,
Provider = new OAuthAuthorizationServerProvider() {
OnValidateClientAuthentication = context => {
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret))
{
if (clientId == WebClientId && clientSecret == WebClientSecret)
{
return Task.FromResult(context.Validated(clientId));
}
}
context.SetError("invalid_client", "Client credentials provided are invalid.");
return Task.FromResult<object>(null);
},
OnGrantResourceOwnerCredentials = context => {
var userName = context.UserName;
var password = context.Password;
var clientId = context.ClientId;
//validate resource owner credentials
if (userName == "admin" && password == "password" && clientId == WebClientId)
{
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim("username", userName));
identity.AddClaim(new Claim("clientId", clientId));
return Task.FromResult(context.Validated(identity));
}
context.SetError("invalid_grant", "Resource owner credentials are invalid.");
return Task.FromResult<object>(null);
}
}
});
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
现在每次我尝试向 host/token 发送 post 时,我可以在调试时看到代码成功执行了 context.Validated 方法,但在 return响应,我得到一个 ArgumentNullException:值。还有其他人遇到这个问题吗?
编辑:这是我得到的堆栈跟踪
[ArgumentNullException: Value cannot be null.
Parameter name: value]
System.IO.BinaryWriter.Write(String value) +11937097
Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer.Write(BinaryWriter writer, AuthenticationTicket model) +97
Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer.Serialize(AuthenticationTicket model) +161
Microsoft.Owin.Security.DataHandler.SecureDataFormat`1.Protect(TData data) +45
Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext.SerializeTicket() +16
Microsoft.Owin.Security.OAuth.<InvokeTokenEndpointAsync>d__22.MoveNext() +4114
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +25
Microsoft.Owin.Security.OAuth.<InvokeAsync>d__0.MoveNext() +1109
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Security.Infrastructure.<Invoke>d__0.MoveNext() +383
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__5.MoveNext() +187
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Security.Infrastructure.<Invoke>d__0.MoveNext() +561
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<RunApp>d__5.MoveNext() +187
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.<DoFinalWork>d__2.MoveNext() +185
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +69
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +64
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +380
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
我通过使用 AuthenticationType 初始化 ClaimsIdentity 解决了这个问题。不确定这究竟是如何解决堆栈跟踪的,但我不再遇到运行时错误。
对于那些在尝试通过构造函数(来自 ClaimsIdentity 和 手动创建 AuthenticationTicket 时遇到相同问题的人AuthenticationProperties),正如 MS 样板代码在 ApplicationOAuthProvider.cs 中所做的那样:
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
在我的例子中,AuthenticationProperties 是从字典创建的:
public static AuthenticationProperties CreateProperties(UserInfoViewModel userInfo)
{
IDictionary<string, string> data = userInfo.ToDictionary();
return new AuthenticationProperties(data);
}
事实证明,字典中有 key/value 对 null 值,这破坏了 Owin 管道中的令牌序列化。从字典中删除这些项目解决了这个问题。