如何更改刷新令牌和不记名身份验证中的声明值
How to change claim values in refresh tokens and bearer authentication
我想通过刷新令牌更改声明的值。我的刷新令牌提供者是这样的:
public class MyRefreshTokenProvider : AuthenticationTokenProvider
{
public override void Create(AuthenticationTokenCreateContext context)
{
...
var claim = context.Ticket.Identity.FindFirst(ClaimTypes.UserData);
if (claim != null)
{
context.Ticket.Identity.RemoveClaim(claim);
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.UserData, "New Value"));
}
context.SetToken(context.SerializeTicket());
}
public override void Receive(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
并且在启动时class:
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
...
RefreshTokenProvider = new MyRefreshTokenProvider()
});
刷新令牌请求完成且没有错误。但是当我使用新的访问令牌时,声明值仍然是旧的。
我的做法对吗?或者如何更改 Bearer 身份验证中的声明值?
我终于找到了解决办法。我必须扩展 AccessTokenProvider
OAuthAuthorizationServerOptions
而不是 RefreshTokenProvider
:
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
...
AccessTokenProvider = new MyAccessTokenProvider(),
RefreshTokenProvider = new MyRefreshTokenProvider()
});
public class MyAccessTokenProvider : AuthenticationTokenProvider
{
public override void Create(AuthenticationTokenCreateContext context)
{
...
var claim = context.Ticket.Identity.FindFirst(ClaimTypes.UserData);
if (claim != null)
{
context.Ticket.Identity.RemoveClaim(claim);
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.UserData, "New Value"));
}
context.SetToken(context.SerializeTicket());
}
public override void Receive(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
public class MyRefreshTokenProvider : AuthenticationTokenProvider
{
public override void Create(AuthenticationTokenCreateContext context)
{
context.SetToken(context.SerializeTicket());
}
public override void Receive(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
根据OAuthAuthorizationServerHandler
class在Microsoft.Owin.Security.OAuth
中AccessTokenProvider
只能更新刷新令牌。要更改声明,应扩展 AccessTokenProvider
:
private async Task InvokeTokenEndpointAsync()
{
...
var accessTokenContext = new AuthenticationTokenCreateContext(
Context,
Options.AccessTokenFormat,
ticket);
await Options.AccessTokenProvider.CreateAsync(accessTokenContext);
string accessToken = accessTokenContext.Token;
if (string.IsNullOrEmpty(accessToken))
{
accessToken = accessTokenContext.SerializeTicket();
}
DateTimeOffset? accessTokenExpiresUtc = ticket.Properties.ExpiresUtc;
var refreshTokenCreateContext = new AuthenticationTokenCreateContext(
Context,
Options.RefreshTokenFormat,
accessTokenContext.Ticket);
await Options.RefreshTokenProvider.CreateAsync(refreshTokenCreateContext);
string refreshToken = refreshTokenCreateContext.Token;
var memory = new MemoryStream();
byte[] body;
using (var writer = new JsonTextWriter(new StreamWriter(memory)))
{
writer.WriteStartObject();
writer.WritePropertyName(Constants.Parameters.AccessToken);
writer.WriteValue(accessToken);
writer.WritePropertyName(Constants.Parameters.TokenType);
writer.WriteValue(Constants.TokenTypes.Bearer);
if (accessTokenExpiresUtc.HasValue)
{
TimeSpan? expiresTimeSpan = accessTokenExpiresUtc - currentUtc;
var expiresIn = (long)expiresTimeSpan.Value.TotalSeconds;
if (expiresIn > 0)
{
writer.WritePropertyName(Constants.Parameters.ExpiresIn);
writer.WriteValue(expiresIn);
}
}
if (!String.IsNullOrEmpty(refreshToken))
{
writer.WritePropertyName(Constants.Parameters.RefreshToken);
writer.WriteValue(refreshToken);
}
...
我想通过刷新令牌更改声明的值。我的刷新令牌提供者是这样的:
public class MyRefreshTokenProvider : AuthenticationTokenProvider
{
public override void Create(AuthenticationTokenCreateContext context)
{
...
var claim = context.Ticket.Identity.FindFirst(ClaimTypes.UserData);
if (claim != null)
{
context.Ticket.Identity.RemoveClaim(claim);
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.UserData, "New Value"));
}
context.SetToken(context.SerializeTicket());
}
public override void Receive(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
并且在启动时class:
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
...
RefreshTokenProvider = new MyRefreshTokenProvider()
});
刷新令牌请求完成且没有错误。但是当我使用新的访问令牌时,声明值仍然是旧的。
我的做法对吗?或者如何更改 Bearer 身份验证中的声明值?
我终于找到了解决办法。我必须扩展 AccessTokenProvider
OAuthAuthorizationServerOptions
而不是 RefreshTokenProvider
:
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
...
AccessTokenProvider = new MyAccessTokenProvider(),
RefreshTokenProvider = new MyRefreshTokenProvider()
});
public class MyAccessTokenProvider : AuthenticationTokenProvider
{
public override void Create(AuthenticationTokenCreateContext context)
{
...
var claim = context.Ticket.Identity.FindFirst(ClaimTypes.UserData);
if (claim != null)
{
context.Ticket.Identity.RemoveClaim(claim);
context.Ticket.Identity.AddClaim(new Claim(ClaimTypes.UserData, "New Value"));
}
context.SetToken(context.SerializeTicket());
}
public override void Receive(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
public class MyRefreshTokenProvider : AuthenticationTokenProvider
{
public override void Create(AuthenticationTokenCreateContext context)
{
context.SetToken(context.SerializeTicket());
}
public override void Receive(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
根据OAuthAuthorizationServerHandler
class在Microsoft.Owin.Security.OAuth
中AccessTokenProvider
只能更新刷新令牌。要更改声明,应扩展 AccessTokenProvider
:
private async Task InvokeTokenEndpointAsync()
{
...
var accessTokenContext = new AuthenticationTokenCreateContext(
Context,
Options.AccessTokenFormat,
ticket);
await Options.AccessTokenProvider.CreateAsync(accessTokenContext);
string accessToken = accessTokenContext.Token;
if (string.IsNullOrEmpty(accessToken))
{
accessToken = accessTokenContext.SerializeTicket();
}
DateTimeOffset? accessTokenExpiresUtc = ticket.Properties.ExpiresUtc;
var refreshTokenCreateContext = new AuthenticationTokenCreateContext(
Context,
Options.RefreshTokenFormat,
accessTokenContext.Ticket);
await Options.RefreshTokenProvider.CreateAsync(refreshTokenCreateContext);
string refreshToken = refreshTokenCreateContext.Token;
var memory = new MemoryStream();
byte[] body;
using (var writer = new JsonTextWriter(new StreamWriter(memory)))
{
writer.WriteStartObject();
writer.WritePropertyName(Constants.Parameters.AccessToken);
writer.WriteValue(accessToken);
writer.WritePropertyName(Constants.Parameters.TokenType);
writer.WriteValue(Constants.TokenTypes.Bearer);
if (accessTokenExpiresUtc.HasValue)
{
TimeSpan? expiresTimeSpan = accessTokenExpiresUtc - currentUtc;
var expiresIn = (long)expiresTimeSpan.Value.TotalSeconds;
if (expiresIn > 0)
{
writer.WritePropertyName(Constants.Parameters.ExpiresIn);
writer.WriteValue(expiresIn);
}
}
if (!String.IsNullOrEmpty(refreshToken))
{
writer.WritePropertyName(Constants.Parameters.RefreshToken);
writer.WriteValue(refreshToken);
}
...