我正在使用承载令牌为OAuth 2配置AspNet.Identity,我已经看到了实现 OAuthAuthorizationServerProvider.GrantRefreshToken
方法的多个示例,其中作者演示了向 new ClaimsIdentity
添加声明的功能,如下所示 .
我试图在我的单服务器(即我的Web API项目是授权资源服务器)的上下文中理解这一点,如果需要,我可以在以后将其拆分为单独的服务器 .
public override Task GrantRefreshToken(OAuthGrantRefreshTokenContext context)
{
var originalClient = context.Ticket.Properties.Dictionary["as:client_id"];
var currentClient = context.ClientId;
if (originalClient != currentClient)
{
context.SetError("invalid_clientId", "Refresh token is issued to a different clientId.");
return Task.FromResult<object>(null);
}
// Change auth ticket for refresh token requests
var newIdentity = new ClaimsIdentity(context.Ticket.Identity);
// CONSIDER: I don't know why you would add a claim here, but here's an example.
//var newClaim = newIdentity.Claims.Where(c => c.Type == "newClaim").FirstOrDefault();
//if (newClaim != null)
//{
// newIdentity.RemoveClaim(newClaim);
//}
//newIdentity.AddClaim(new Claim("newClaim", "newValue"));
var newTicket = new AuthenticationTicket(newIdentity, context.Ticket.Properties);
context.Validated(newTicket);
return Task.FromResult<object>(null);
}
“应用程序必须调用context.Validated指示Authorization Server中间件根据这些声明和属性发出 access token . ”
我不明白这一点 . 我以为我们正在分发刷新令牌,而不是访问令牌 .
此外,“对context.Validated的调用可以被赋予不同的AuthenticationTicket或ClaimsIdentity,以便控制哪些信息从刷新令牌流向访问令牌 . ”
我认为所有声明都存储在我的签名和加密访问令牌中,该令牌传递为 Authorization: Bearer XXXXXX
. 但是,我对 ClaimsIdentity
和 AuthenticationTicket
与OAuth 2.0流程中的任何内容实际相关的方式都有一个细微的把握 .
我最好的猜测是 GrantRefreshToken
需要采用已经过身份验证和授权的身份( context.Ticket.Identity
),并通过调用context.Validated验证是否应该向其添加刷新令牌 .
1 回答
OAuth2中的刷新令牌只是另一种类型的授权:获取新的
access_token
的另一种方法 .因此,必须验证
RefreshToken
以便为用户发出新的access_token
.将刷新令牌持久保存到底层存储(例如数据库)时,必须将整个用户身份与其一起存储(通常使用
AuthenticationTokenCreateContext
对象的SerializeTicket()
方法) . 这意味着在第一代产品期间获得的索赔中的任何更改都不会默认使用RefreshToken
授权传播到其他排放(如果您需要在access_token
中更新这些索赔,则需要重新加载这些索赔) .我相信这是许多示例显示如何在
GrantRefreshToken
方法内的新标识中添加/替换声明的主要原因 .我将尝试进一步澄清在支持_391754时通常会发生什么:
用户使用任何类型的支持授权对自己进行身份验证(例如
ResourceOwnerCredentials
);我们创建一个与此特定用户绑定的标识(我们可以在此处添加声明)并使用它创建一个新的
AuthenticationTicket
(我们通过在特定的context
对象上调用Validated(ticket)
来验证)将用于创建access_token
;框架在提供的
IAuthenticationTokenProvider
上生成一个新的刷新令牌,调用CreateAsync
. 在此方法中,我们必须检索票证并将其存储到某种持久性存储(例如数据库)以及唯一的Id
和一些有用的元数据中 . 这个Id
是用户观点的refresh_token
.我们向用户返回
access_token
(其中包含用户的序列化声明)和refresh_token
(这只是一个参考) .一段时间后,用户必须再次进行身份验证(例如
access_token
已过期),因此他将使用refresh_token
向令牌 endpoints 发送请求 .我们从持久存储中检索
refresh_token
记录,并反序列化将用于创建新标识的票证 . 此票证包含我们在第一次身份验证时添加的所有声明(这几乎是第一次身份验证的精确副本):如果在当前时刻和第一次身份验证之间的间隔期间更改了任何声明(例如,添加了新角色)用户,电子邮件已更改等 . )我们现在有机会修改新标识并添加/替换这些声明,以便新的access_token
将反映更改 .流程通过验证故障单(如前所述)并生成一对
access_token
和refresh_token
以发送给用户来继续 .