fdm*_*ion 4 asp.net oauth bearer-token
我OAuthAuthorizationServer在 OWIN ASP.NET C# web API 中使用 OWIN库来生成和处理不记名令牌。
现在,我有一个端点(您在OAuthAuthorizationServerOptions结构中设置),它接受来自前端的grant_type,username和password字段。我创建了一个执行验证的提供程序类,然后相应地调用context.Validated()或context.SetError()。然后中间件处理生成令牌并将其返回给用户,并“接管”登录端点,在内部完成所有工作。
现在,我正在向我的 API 添加一个新功能,用户可以在其中更改他们的“角色”(例如,管理员可以将自己设置为普通用户以查看他们的工作结果,用户可以在多个角色中进行选择等)由于我已经通过不记名令牌处理了这个问题(我将用户的角色存储在那里,我的所有端点都使用不记名令牌来确定当前角色),我现在有理由从 API 后端更新不记名令牌的内容。
我想要做的是允许前端调用api/set_role将接受参数的端点(例如)。用户请求某个角色,他们当前的不记名令牌将伴随请求。然后服务器将检查是否允许相关用户使用该特定角色,如果允许,将生成一个新令牌并将其在响应正文中返回给用户。然后前端将在本地存储中更新其令牌。或者,当然,如果不允许用户切换到该角色,后端会返回适当的错误,前端会做出相应的反应。
为此,我基本上希望能够手动生成令牌。与我identity.AddClaim()在登录提供程序中的使用方式类似,我希望能够在 API 代码中的任意位置执行此操作。该方法将负责将任何必要的现有信息(例如用户的用户名)转移到新令牌中,因为它已经拥有现有的令牌。
我想要的伪代码:
if (!userCanUseRole(requestedRoleId)) return Request.CreateErrorResponse(...);
// we have a struct containing parsed information for the current token in the variable cToken
bearerToken newToken = new bearerToken();
newToken.AddClaim(new Claim("user", cToken.user));
newToken.AddClaim(new Claim("role", requestedRoleId));
string tokenToReturnToFrontend = newToken.getTokenString(); // string suitable for using in Authorization Bearer header
return Request.CreateResponse(new StringContent(tokenToReturnToFrontend));
Run Code Online (Sandbox Code Playgroud)
我对“刷新”令牌不太熟悉,但我现在使用它们的唯一方法是延长令牌到期时间。为此,前端明确请求刷新令牌并提供自己的刷新令牌,后端只需将其复制到新令牌并编辑到期时间。问题在于获取刷新令牌的方法只有一种,而且由于我现在至少有一个其他理由来刷新令牌(并且可能,未来的发展可能会增加更多的理由来在不同时间更改令牌内容),然后我必须处理在某处存储瞬态数据的问题(例如“当请求刷新令牌时,用户想要做的事情是什么?他们请求这样做已经太久了吗?等)。如果我可以简单地按需生成不记名令牌,那就容易多了以与OAuthAuthorizationServer本身相同的方式。(我知道它使用 MachineKey 来做到这一点,但我不确切知道它是如何做到的,也不知道我将如何去做我想做的事情。)
值得注意的是:在另一个项目中,我提供internal了对OAuthBearerAuthenticationOptions传递给授权服务器实例的类的访问权限,并且能够使用它来解码测试中的不记名令牌。我还没有看到任何明显的想法可以让我以这种方式编码不记名令牌。
编辑:我探索了(非常简洁,几乎是无用的文件)OWIN命名空间,发现AccessTokenFormat哪个阶级出现,它应该做我想做的。我写了这段代码:
Microsoft.Owin.Security.AuthenticationTicket at = new Microsoft.Owin.Security.AuthenticationTicket(new ClaimsIdentity
{
Label="claims"
}
, new Microsoft.Owin.Security.AuthenticationProperties
{
AllowRefresh=true,
IsPersistent=true,
IssuedUtc=DateTime.UtcNow,
ExpiresUtc=DateTime.UtcNow.AddMinutes(5),
});
at.Identity.AddClaim(new Claim("hello", "world"));
string token = Startup.oabao.AccessTokenFormat.Protect(at);
return Request.CreateResponse(HttpStatusCode.OK, new StringContent(token, System.Text.Encoding.ASCII, "text/plain"));
Run Code Online (Sandbox Code Playgroud)
这似乎应该有效。(我再次允许访问OAuthBearerAuthenticationOptions传递给OAuthAuthorizationServer实例的类。)但是,此代码引发ArgumentNull异常。堆栈跟踪表明它正在写入 BinaryWriter,但 OWIN 代码将空值传递给WriteBinaryWriter 上的方法。
还是没有解决办法。
我确实弄清楚了使这项工作的代码。有人可能会争辩说我“没有正确使用 OAuth”,但严格来说,这段代码将完成我想要的 - 在代码中的任意点生成一个令牌并获取字符串。
首先,正如我所说,我必须提供对OAuthBearerAuthenticationOptions类实例的访问。当 OAuth 服务器初始化时,我猜它会用所有用于令牌的各种对象填充这个类。关键是我们确实可以访问Protect并且Unprotect可以直接编码和解码不记名令牌。
此代码将生成一个令牌,假设它oabao是OAuthBearerAuthenticationOptions已传递给OAuthAuthorizationServer实例的类:
Microsoft.Owin.Security.AuthenticationTicket at = new Microsoft.Owin.Security.AuthenticationTicket(new ClaimsIdentity("Bearer", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"),
new Microsoft.Owin.Security.AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = true,
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.AddDays(1) // whenever you want your new token's expiration to happen
});
// add any claims you want here like this:
at.Identity.AddClaim(new Claim("userRole", role));
// and so on
string token = oabao.AccessTokenFormat.Protect(at);
// You now have the token string in the token variable.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3317 次 |
| 最近记录: |