我想分享完成这项工作的必要条件,我从其他不同的帖子中收集了答案;您可以在此答案的末尾找到链接。
如果有人有任何意见或想法,请与我们分享。
用户注册为响应后,使用刷新令牌生成本地访问令牌。
作为Peter Hedberg 回答;我们需要在启动类中将 OAuthOptions 设为公开和静态:
public static OAuthAuthorizationServerOptions OAuthServerOptions { get; private set; }
然后我创建了帮助类来生成本地访问令牌并刷新
public async Task<JObject> GenerateLocalAccessToken(ApplicationUser user)
{
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
OAuthDefaults.AuthenticationType);
AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
//Create the ticket then the access token
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
ticket.Properties.IssuedUtc = DateTime.UtcNow;
ticket.Properties.ExpiresUtc = DateTime.UtcNow.Add(Startup.OAuthServerOptions.AccessTokenExpireTimeSpan);
var accessToken = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
//Create refresh token
Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext context =
new Microsoft.Owin.Security.Infrastructure.AuthenticationTokenCreateContext(
Request.GetOwinContext(),
Startup.OAuthOptions.AccessTokenFormat, ticket);
await Startup.OAuthOptions.RefreshTokenProvider.CreateAsync(context);
properties.Dictionary.Add("refresh_token", context.Token);
//create the Token Response
JObject tokenResponse = new JObject(
new JProperty("access_token", accessToken),
new JProperty("token_type", "bearer"),
new JProperty("expires_in", Startup.OAuthServerOptions.AccessTokenExpireTimeSpan.TotalSeconds.ToString()),
new JProperty("refresh_token", context.Token),
new JProperty("userName", user.UserName),
new JProperty(".issued", ticket.Properties.IssuedUtc.ToString()),
new JProperty(".expires", ticket.Properties.ExpiresUtc.ToString())
);
return tokenResponse;
}
在 SimpleRefreshTokenProvider CreateAsync 方法中使用基本 context.SerializeTicket 存在问题。来自Bit Of Technology的消息
好像在ReceiveAsync方法中,context.DeserializeTicket不是
在外部登录案例中完全返回身份验证票。
当我在调用之后查看 context.Ticket 属性时,它是空的。
与本地登录流程相比,DeserializeTicket 方法
将 context.Ticket 属性设置为 AuthenticationTicket。所以
现在的谜团是 DeserializeTicket 的行为如何不同
两个流动。创建数据库中受保护的票证字符串
在同一个 CreateAsync 方法中,不同之处仅在于我称之为
在 GenerateLocalAccessTokenResponse 中手动方法,与 Owin
middlware 正常调用它...... SerializeTicket 或
DeserializeTicket 抛出错误……
因此,您需要使用 Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer 对票证进行序列化和反序列化。它看起来像这样:
Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer serializer
= new Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer();
token.ProtectedTicket = System.Text.Encoding.Default.GetString(serializer.Serialize(context.Ticket));
代替:
token.ProtectedTicket = context.SerializeTicket();
对于 ReceiveAsync 方法:
Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer serializer = new Microsoft.Owin.Security.DataHandler.Serializer.TicketSerializer();
context.SetTicket(serializer.Deserialize(System.Text.Encoding.Default.GetBytes(refreshToken.ProtectedTicket)));
代替:
context.DeserializeTicket(refreshToken.ProtectedTicket);
请参考这个Qestion和这个Answer
谢谢lincx 和Giraffe