Base solution for your next web application
Open Closed

Bad performance in AbpUserStore.IsTokenValidityKeyValidAsync — loads the user's entire token collection to validate one key #12674


User avatar
0
npdevs created

On every authenticated request that misses the token-validity cache, JWT validation calls UserManager.IsTokenValidityKeyValidAsync, which delegates to AbpUserStore.IsTokenValidityKeyValidAsync:

public virtual async Task<bool> IsTokenValidityKeyValidAsync(
    TUser user, string tokenValidityKey, CancellationToken cancellationToken = default)
{
    return await _unitOfWorkManager.WithUnitOfWorkAsync(async () =>
    {
        cancellationToken.ThrowIfCancellationRequested();
        Check.NotNull(user, nameof(user));
        await UserRepository.EnsureCollectionLoadedAsync(user, u => u.Tokens, cancellationToken);
        return user.Tokens.Any(t => t.LoginProvider == TokenValidityKeyProvider &&
                                    t.Name == tokenValidityKey &&
                                    t.ExpireDate > DateTime.UtcNow);
    });
}

EnsureCollectionLoadedAsync(user, u => u.Tokens) issues SELECT * FROM AbpUserTokens WHERE UserId = @id and materializes every token row for that user. The LoginProvider / Name / ExpireDate filter then runs in memory (client-side) via .Any(...) — it is never translated to SQL.

So, is there a reason the existence check is done by loading the full collection rather than a filtered query? Would the team consider changing the framework implementation to a server-side existence query?

Thanks.

Markdown is supported
Copy & paste or drag & drop images (max 30 MB per image)

1 Answer(s)
  • User Avatar
    0
    oguzhanagir created
    Support Team

    Hi @npdevs

    Thank you for reporting this. We have created an issue to track the performance problem and will work on a fix as soon as possible.

    Markdown is supported
    Copy & paste or drag & drop images (max 30 MB per image)