Added support for drifts in JWT refresh tokens. This can happen if the user refreshes the browser during the login.

This commit is contained in:
Kenneth Skovhede
2024-08-31 11:22:10 +02:00
parent 47e8e9847e
commit bc9ed71ff8
2 changed files with 5 additions and 2 deletions
@@ -17,6 +17,7 @@ public record JWTConfig
public int RefreshTokenDurationInMinutes { get; init; } = 60 * 24 * 30;
public int SigninTokenDurationInMinutes { get; init; } = 5;
public int SingleOperationTokenDurationInMinutes { get; init; } = 1;
public int MaxRefreshTokenDrift { get; init; } = 1;
public SymmetricSecurityKey SymmetricSecurityKey() => new(Encoding.UTF8.GetBytes(SigningKey));
public static JWTConfig Create() => new()
@@ -1,10 +1,11 @@
using Duplicati.Library.Logging;
using Duplicati.Server.Database;
using Duplicati.WebserverCore.Abstractions;
using Duplicati.WebserverCore.Middlewares;
namespace Duplicati.WebserverCore.Services;
public class LoginProvider(ITokenFamilyStore repo, IJWTTokenProvider tokenProvider, Connection connection) : ILoginProvider
public class LoginProvider(ITokenFamilyStore repo, IJWTTokenProvider tokenProvider, JWTConfig jwtConfig, Connection connection) : ILoginProvider
{
private static readonly string LOGTAG = Log.LogTagFromType<LoginProvider>();
@@ -29,7 +30,8 @@ public class LoginProvider(ITokenFamilyStore repo, IJWTTokenProvider tokenProvid
var tokenFamily = await repo.GetTokenFamily(refreshToken.UserId, refreshToken.TokenFamilyId, ct)
?? throw new UnauthorizedAccessException("Invalid refresh token");
if (tokenFamily.Counter != refreshToken.Counter)
var counterDiff = tokenFamily.Counter - refreshToken.Counter;
if (counterDiff < 0 || counterDiff > jwtConfig.MaxRefreshTokenDrift)
{
Log.WriteWarningMessage(LOGTAG, "TokenFamilyReuse", null, $"Invalid refresh token counter: {tokenFamily.Counter} != {refreshToken.Counter}");
await repo.InvalidateTokenFamily(tokenFamily.UserId, tokenFamily.Id, ct);