在实现Identity 2.1 + owinoauth JWT承载令牌时,如何从Web API控制器端点进行身份验证

本文关键字:Web API 控制器 身份验证 端点 Identity 实现 owinoauth 令牌 JWT | 更新日期: 2023-09-27 18:17:13

我无法从我的控制器方法中进行身份验证,作为我的确认用户注册工作流的一部分,我正在寻找一些指导,我的实现是正确的。

我的控制器方法有以下代码;我已经确认用户被填充(作为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进行身份验证时,我可以看到它给出了正确的响应,然后可以访问安全的端点(使用Authorise属性)。

所以认证通过中间件的工作,但什么是正确的方式来认证从控制器方法内部?

在实现Identity 2.1 + owinoauth JWT承载令牌时,如何从Web API控制器端点进行身份验证

考虑到它的价值,我想我应该分享一下我的解决方案。

简短答案;我创建了一个临时的一次性密码(令牌),用于第一次对用户进行身份验证

要点如下:https://gist.github.com/chrismoutray/159e6fd74f45d88efd12

To Summaries -在AccountController ConfirmSignUp方法中;我使用用户管理器生成一个自定义令牌,我将其称为GRANT-ACCESS,然后使用uri中的用户名和令牌重定向到我的confirm-signup页面。我的angular应用会解析到confirm-signup的ui路由,并执行登录,传递令牌作为密码。

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);
}