从Web API中的控制器返回OAuthAuthorizatioServer生成的JWT令牌

Mis*_*siu 9 c# asp.net .net-4.5 asp.net-identity

在@Taiseer Joudeh之后,我能够创建简单的Web API POC.我能够创建新帐户,然后登录并在向标头添加JWT令牌时调用安全Web API.

我想修改负责创建帐户的方法.
现在我正在返回带有新用户对象的Create(201)代码,但我想返回访问令牌.

我发现了类似的问题,但它需要创建HttpClient并向OAuthAuthorizatioServer TokenEndpointPath发出请求.

我发现的第二个问题需要生成返回到前端的临时令牌,但是前端必须向服务器发出额外请求以获得"真实"令牌.

我想做的是在创建用户帐户时返回登录响应(access_token,token_type和expires_in).我希望用户在创建帐户时进行身份验证.

我只使用Web API和JWT而没有任何cookie.

编辑:我的临时解决方案:
创建用户后我正在这样做:

var validTime = new TimeSpan(0, 0, 0, 10);
var identity = await UserManager.CreateIdentityAsync(user, "JWT");
var jwtFormat = new CustomJwtFormat(ApplicationConfiguration.Issuer);
var authenticationProperties = new AuthenticationProperties { IssuedUtc = DateTimeOffset.UtcNow, ExpiresUtc = DateTimeOffset.UtcNow.Add(validTime) };
var authenticationTicket = new AuthenticationTicket(identity, authenticationProperties);
var token = jwtFormat.Protect(authenticationTicket);

var response = new
{
    access_token = token,
    token_type = "bearer",
    expires_in = validTime.TotalSeconds.ToInt()
};

return Ok(response);
Run Code Online (Sandbox Code Playgroud)

其中,CustomJwtFormat来自这真棒文章.

Tre*_*ard 4

下面是一些类似于我在应用程序中所做的代码,它使用 Asp.Net Core 1.0。如果您不使用 Core 1.0,您的登录和用户注册将会有所不同。

public async Task<string> CreateUser(string username, string password)
    {
        string jwt = String.Empty;

        if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
        {
            Response.StatusCode = (int)HttpStatusCode.BadRequest;
        }

        var user = await _userManager.FindByNameAsync(username);
        if (user == null) // user doesn't exist, create user
        {
            var newUser = await _userManager.CreateAsync(new ApplicationUser() { UserName = username }, password); 
            if (newUser.Succeeded) //user was successfully created, sign in user
            {
                user = await _userManager.FindByNameAsync(username);
                var signInResult = await _signInManager.PasswordSignInAsync(user, password, false, true);
                if (signInResult.Succeeded) //user signed in, create a JWT
                {
                    var tokenHandler = new JwtSecurityTokenHandler();
                    List<Claim> userClaims = new List<Claim>();

                    //add any claims to the userClaims collection that you want to be part of the JWT
                    //...

                    ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(user.UserName, "TokenAuth"), userClaims);
                    DateTime expires = DateTime.Now.AddMinutes(30); //or whatever

                    var securityToken = tokenHandler.CreateToken(
                        issuer: _tokenOptions.Issuer,  //_tokenAuthOptions is a class that holds the issuer, audience, and RSA security key
                        audience: _tokenOptions.Audience,
                        subject: identity,
                        notBefore: DateTime.Now,
                        expires: expires,
                        signingCredentials: _tokenOptions.SigningCredentials
                        );

                    jwt = tokenHandler.WriteToken(securityToken);
                    Response.StatusCode = (int)HttpStatusCode.Created;
                    await _signInManager.SignOutAsync(); //sign the user out, which deletes the cookie that gets added if you are using Identity.  It's not needed as security is based on the JWT
                }
            }
            //handle other cases...
        }
    }
Run Code Online (Sandbox Code Playgroud)

基本上,用户被创建并自动登录。然后,我构建一个 JWT(添加您想要的任何声明)并将其返回到响应正文中。在客户端(MVC 和 Angular JS),我从响应正文中获取 JWT 并存储它。然后,它在每个后续请求的 Authorization 标头中传递回服务器。所有服务器操作的授权策略都基于 JWT 提供的一组声明。没有cookie,服务器上没有状态。

编辑:我想您甚至不需要在此过程中调用signIn方法,因为您只需创建用户、创建JWT并返回JWT即可。当用户根据未来的请求登录时,您将使用登录、创建令牌、注销方法。