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

时间:2015-10-11 16:33:54

标签: c# asp.net oauth owin jwt

我无法在我的控制器方法中进行身份验证,这是我的confirm-user-signup工作流程的一部分,我正在寻找一些指导,我的实现是正确的。

我的控制器方法有以下代码;我已确认用户已填充(作为FindById来电的一部分),但在SignIn之后;未设置this.Authentication.User.IdentityName为空,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进行身份验证时,我可以看到它提供了正确的响应,然后可以访问受保护的端点(使用Authorize属性)。

因此,通过中间件进行身份验证确实有效,但从控制器方法内部进行身份验证的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

对于它的价值,我认为我会分享我提出的解决方案。

  

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

请点击此处参考: https://gist.github.com/chrismoutray/159e6fd74f45d88efd12

总结 - 在AccountController ConfirmSignUp方法中;我使用用户管理器生成我称为GRANT-ACCESS的自定义令牌,然后使用uri中的用户名和令牌重定向到我的confirm-signup页面。 我的角度应用程序将ui路由解析为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);
}