Asp.net web api Web API身份验证-返回相同的OAUTH刷新令牌

Asp.net web api Web API身份验证-返回相同的OAUTH刷新令牌,asp.net-web-api,oauth,refresh-token,Asp.net Web Api,Oauth,Refresh Token,我对这个很陌生。。因此,任何帮助都将不胜感激。 我有一个WebApi服务,它使用OAUTH令牌和刷新令牌身份验证。 目前一切都运转良好: 步骤1:我发送用户和密码,它生成一个身份验证令牌和一个刷新令牌。刷新令牌保存在数据库中 第二步。我现在可以使用刷新令牌,并接收身份验证令牌和新的刷新令牌。我想要一种方法来使用我发送的相同刷新令牌,而不是重用新令牌 这是我的刷新令牌代码: public class SimpleRefreshTokenProvider : IAuthenticationToken

我对这个很陌生。。因此,任何帮助都将不胜感激。 我有一个WebApi服务,它使用OAUTH令牌和刷新令牌身份验证。 目前一切都运转良好:

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

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

这是我的刷新令牌代码:

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();
    }
}   
公共类SimpleRefreshTokenProvider:IAAuthenticationTokenProvider
{
公共异步任务CreateSync(AuthenticationTokenCreateContext上下文)
{
RefreshTokensRepository_repo=新的RefreshTokensRepository();
var clientid=context.Ticket.Properties.Dictionary[“as:client_id”];
//在这里,我重新生成令牌,但我不知道如何检索已发送的令牌。
var refreshtTokenId=Guid.NewGuid().ToString(“n”);
//在BD中保存:
var refreshtTokenLifetime=context.OwinContext.Get(“as:clientrefreshtTokenLifetime”);
var token=新的刷新令牌()
{
Id=Helper.GetHash(refreshTokenId),
ClientId=ClientId,
主题=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(refreshtTokenLifetime));
token.ProtectedTicket=context.SerializeTicket();
var结果=_repo.Add(令牌);
如果(!string.IsNullOrEmpty(结果))
SetToken(refreshTokenId);
}
公共异步任务ReceiveAsync(AuthenticationTokenReceiveContext上下文)
{
var allowedOrigin=context.OwinContext.Get(“as:clientAllowedOrigin”);
context.OwinContext.Response.Headers.Add(“访问控制允许来源”,新[]{“*”});
字符串hashedTokenId=Helper.GetHash(context.Token);
RefreshTokensRepository_repo=新的RefreshTokensRepository();
var refreshToken=_repo.FindById(hashedTokenId);
if(刷新令牌!=null)
{
//从refreshToken类获取protectedTicket
DeserializeTicket(refreshtToken.ProtectedTicket);
_回购移除(hashedTokenId);
}
}
void IAAuthenticationTokenProvider.Create(AuthenticationTokenCreateContext上下文)
{
抛出新的NotImplementedException();
}
void IAAuthenticationTokenProvider.Receive(AuthenticationTokenReceiveContext上下文)
{
抛出新的NotImplementedException();
}
}   
我的代码基于以下示例:

我想使用相同的已发送刷新令牌,但我不知道如何在此上下文中使用已发送的令牌。
有什么想法吗

免责声明:我不允许重复使用刷新令牌。 然而,这确实为每个人提供了一个很好的机会,让他们更好地了解这个过程是如何工作的,并且在某些场景中有很好的理由重用过去的刷新令牌。我的回答基于:

  • 问题:“我想要一种使用我发送的相同刷新令牌而不是重用新令牌的方法。”
  • 代码注释:“//这里我重新生成令牌,但我不知道如何检索已发送的令牌。”
  • 伪代码步骤:

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

      var props=新的AuthenticationProperties(新字典)
      {
      { 
      “as:client_id”,(context.ClientId==null)?string.Empty:context.ClientId
      },{ 
      “用户名”,context.userName
      }
      });

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

    公共异步任务CreateAsync(AuthenticationTokenCreateContext上下文)
    {
    var userName=context.Ticket.Properties.Dictionary[“userName”];
    …

    • 仍然在CreateAsync()方法中,使用用户标识符查找现有刷新令牌。这类似于:
    var existingRefreshToken=wait _repo.FindRefreshTokenByUserNameAsync(userName);

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

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

    • 此时,您已拥有现有令牌,并且应该能够重新使用该刷新令牌值,而不是Guid。NewGuid()
    var refreshttokenid=existingToken.Token;

    然而,看看本教程的示例代码,就会发现正在使用哈希算法来存储刷新令牌的值。这可能会使事情变得复杂一些,因为存储哈希值更安全,但这里的哈希过程是单向的

    如果您确实希望在保留的只是哈希标记的情况下重用原始标记值,则需要实现在ReceiveAsync()方法中捕获非哈希标记值的代码。它必须临时保留非哈希值足够长的时间,以便您在CreateAync()方法中使用它。换句话说,您需要