1

我对此很陌生..所以任何帮助将不胜感激。我有一个使用 OAUTH 令牌和刷新令牌身份验证的 WebApi 服务。目前一切正常:

step1:我发送用户和密码,它会生成一个身份验证令牌和一个刷新令牌。刷新令牌保存在数据库中。

第2步。我现在可以使用刷新令牌并收到身份验证令牌和新的刷新令牌。我想要一种方法来使用我发送的相同刷新令牌而不是重用一个新令牌。

这是我的刷新令牌代码:

public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
{
    public async Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        RefreshTokensRepository _repo = new RefreshTokensRepository();

        var clientid = context.Ticket.Properties.Dictionary["as:client_id"];

        //HERE I regenerate the token, but I have no idea how to retrieve the already sent one.
        var refreshTokenId = Guid.NewGuid().ToString("n");

        //saving in BD:
        var refreshTokenLifeTime = context.OwinContext.Get<string>("as:clientRefreshTokenLifeTime"); 

        var token = new RefreshTokens()
        {
            Id = Helper.GetHash(refreshTokenId),
            ClientId = clientid,
            Subject = context.Ticket.Identity.Name,
            IssuedUtc = DateTime.UtcNow,
            ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime))
        };

        context.Ticket.Properties.IssuedUtc = DateTime.UtcNow;
        context.Ticket.Properties.ExpiresUtc = DateTime.UtcNow.AddMinutes(Convert.ToDouble(refreshTokenLifeTime));

        token.ProtectedTicket = context.SerializeTicket();
        var result = _repo.Add(token);
        if(!string.IsNullOrEmpty(result))
            context.SetToken(refreshTokenId);
    }

    public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
    {
        var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin");
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        string hashedTokenId = Helper.GetHash(context.Token);

        RefreshTokensRepository _repo = new RefreshTokensRepository();
        var refreshToken = _repo.FindById(hashedTokenId);
        if (refreshToken != null)
        {
            //Get protectedTicket from refreshToken class
            context.DeserializeTicket(refreshToken.ProtectedTicket);
            _repo.Remove(hashedTokenId);
        }
    }

    void IAuthenticationTokenProvider.Create(AuthenticationTokenCreateContext context)
    {
        throw new NotImplementedException();
    }

    void IAuthenticationTokenProvider.Receive(AuthenticationTokenReceiveContext context)
    {
        throw new NotImplementedException();
    }
}   

我的代码基于以下示例: http ://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/

我想使用相同的已发送刷新令牌,但我不知道如何在这种情况下使用已发送的刷新令牌。有任何想法吗?

4

1 回答 1

0

免责声明:我不容忍重复使用刷新令牌。但是,这确实为每个人提供了一个很好的机会来提高对该过程如何工作的了解,并且在某些情况下可能有充分的理由重用过去的刷新令牌。我的回答基于:

  1. 问题:“我想要一种方法来使用我发送的相同刷新令牌,而不是重复使用新令牌。”
  2. 代码注释,“//在这里我重新生成了令牌,但我不知道如何检索已经发送的令牌。”

伪代码步骤:

  • 将用户标识符作为属性存储在 GrantResourceOwnerCredentials() 方法的 AuthenticationProperties 中。从示例代码中,您可能已经使用“userName”执行此操作:

    var props = new AuthenticationProperties(new Dictionary<string, string> { { "as:client_id", (context.ClientId == null) ? string.Empty : context.ClientId },{ "userName", context.UserName } });

  • 在您的 IAuthenticationTokenProvider 实现的 CreateAsync() 方法中检索用户标识符(例如,在您的情况下为“SimpleRefreshTokenProvider”)。这看起来像:

public async Task CreateAsync(AuthenticationTokenCreateContext context) { var userName = context.Ticket.Properties.Dictionary["userName"]; ...

  • 仍然在 CreateAsync() 方法中使用用户标识符来查找现有的刷新令牌。这看起来像:

var existingRefreshToken = await _repo.FindRefreshTokenByUserNameAsync(userName);

注意:您需要将上述方法从示例代码写入您的 AuthRepository 类。“FindRefreshTokenByUserNameAsync(userName) 实现可能包括类似这样的内容,如果您使用的是实体框架并且有一个“RefreshToken”表用于持久化授予的刷新令牌:

var existingToken = RefreshToken.Where(r => r.UserName == userName).SingleOrDefault();

  • 此时,您拥有现有令牌,并且应该能够重新使用该刷新令牌值而不是 Guid.NewGuid():

var refreshTokenId = existingToken.Token;

但是,查看本教程的示例代码表明,正在使用 HashAlgorithm 来存储刷新令牌的值。这可能会使您的事情变得有点复杂,因为存储散列值是更好的安全性,但这里的散列过程是单向的。

如果您真的想在您保留的只是散列令牌时重用原始令牌值,则需要在 ReceiveAsync() 方法中实现捕获非散列令牌值的代码。它必须将非散列值临时保留足够长的时间,以便您在 CreateAsync() 方法中使用它。换句话说,您必须在 ReceiveAsync() 中保存/保留“context.Token”,将其与您的用户名相关联(来自 context.Ticket.Properties.Dictionary["userName"]),然后在 CreateAsync 中使用它() 方法。它很老套,我不喜欢它,但你可以在 ReceiveAsync() 中围绕这行代码来做:

string hashedTokenId = Helper.GetHash(context.Token);

于 2019-06-28T17:07:36.710 回答