实施 Identity 2.1 + OWIN OAuth JWT 不记名令牌时如何从 Web API 控制器端点进行身份验证
Posted
技术标签:
【中文标题】实施 Identity 2.1 + OWIN OAuth JWT 不记名令牌时如何从 Web API 控制器端点进行身份验证【英文标题】:How to authenticate from Web API controller endpoint when implementing Identity 2.1 + OWIN OAuth JWT bearer token 【发布时间】:2016-01-09 02:57:04 【问题描述】:我无法在我的控制器方法中进行身份验证,这是我的确认用户注册工作流程的一部分,我正在寻找一些指导来证明我的实施是正确的。
我的控制器方法有以下代码;我已经确认用户已被填充(作为FindById
调用的一部分)但在SignIn
之后; this.Authentication.User.Identity
未设置(Name
为空白,IsAuthenticated
为假):
this.Authentication.SignOut("JWT");
ApplicationUser user = await this.AppUserManager.FindByIdAsync(userId);
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(this.AppUserManager, "JWT");
this.Authentication.SignIn(new AuthenticationProperties() IsPersistent = true , oAuthIdentity);
这是在使用 OWIN OAuth 时自动登录的正确方法吗?
完整的控制器方法可以在这里看到: https://gist.github.com/chrismoutray/8a8e5f6a7b433571613b
作为参考,我一直在关注名为 Bit of Tech 的博客中的一组文章,这些文章允许我使用 JWT 不记名令牌设置 OWIN OAuth。
第 3 部分特别讨论了 JWT(共 5 个):http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/
从我创建自定义 OAuth 提供程序的文章中,该提供程序继承自 OAuthAuthorizationServerProvider
并实现 GrantResourceOwnerCredentials
,当我的客户端代码 (AngularJS) 尝试使用端点 /oauth/token
进行身份验证时,我可以看到它提供然后可以访问正确的响应和受保护的端点(使用授权属性)。
所以通过中间件进行身份验证确实有效,但从控制器方法内部进行身份验证的正确方法是什么?
【问题讨论】:
克里斯,我不清楚你为什么要实现 OAuthProvider。你是发行代币还是消费? @BrentSchmaltz - 我考虑了我的方法并从不同的角度解决了这个问题。所以现在,不要尝试使用 Authentication.SignIn(..) 从控制器方法内部登录。我创建了一个临时的一次性密码(令牌),客户端应用程序将使用该密码首次对用户进行身份验证。 【参考方案1】:我想我会分享我想出的解决方案。
简短的回答;我创建了一个临时的一次性密码(令牌),用于首次验证用户身份
这里的要点供参考: https://gist.github.com/chrismoutray/159e6fd74f45d88efd12
到摘要 - 在AccountController ConfirmSignUp
方法中;我使用用户管理器生成一个自定义令牌,我称之为GRANT-ACCESS
,然后使用 uri 中的用户名和令牌重定向到我的confirm-signup
页面。
我的 Angular 应用程序将 ui-route 解析为 confirm-signup
并执行登录,将令牌作为密码传递。
var tokenResult = this.AppUserManager.GenerateUserTokenAsync("GRANT-ACCESS", userId);
string token = tokenResult.Result;
Uri redirectLocation = new Uri(
string.Format("http://localhost:45258/#/confirm-signup?user=0&token=1",
Uri.EscapeDataString(user.UserName), Uri.EscapeDataString(token)));
return Redirect(redirectLocation);
最后对GrantResourceOwnerCredentials
进行了修改,如果FindAsync
(通过用户名和密码)没有返回用户,那么我再试一次,但这次将context.Password
视为GRANT-ACCESS
用户要验证的令牌。如果令牌有效,那么我会返回 JWT 身份验证票,就像用户使用有效密码登录一样。
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
... code obmitted
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
user = await userManager.FindByNameAsync(context.UserName);
... null checks obmitted
string token = context.Password;
bool result = await userManager.VerifyUserTokenAsync(user.Id, "GRANT-ACCESS", token);
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, "JWT");
var ticket = new AuthenticationTicket(oAuthIdentity, null);
context.Validated(ticket);
【讨论】:
以上是关于实施 Identity 2.1 + OWIN OAuth JWT 不记名令牌时如何从 Web API 控制器端点进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章
没有 OWIN 和 AspNet.Identity 的基于 Asp.Net Web Api 令牌的授权
ASP.NET (OWIN) Identity:如何从 Web API 控制器获取 UserID?
MVC Owin Identity 2 CheckPasswordAsync() 不会执行