From 84202336d55da121f861ca515e3935941850b0c5 Mon Sep 17 00:00:00 2001 From: James Gunn Date: Fri, 1 Dec 2023 14:35:28 +0000 Subject: [PATCH] Fix the isolation level for authentication state storage transactions (#771) --- .../State/DbAuthenticationStateProvider.cs | 51 +++++-------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/State/DbAuthenticationStateProvider.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/State/DbAuthenticationStateProvider.cs index ee2637455..b68213962 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/State/DbAuthenticationStateProvider.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/State/DbAuthenticationStateProvider.cs @@ -5,7 +5,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using Npgsql; -using Polly; using TeacherIdentity.AuthServer.Models; namespace TeacherIdentity.AuthServer.State; @@ -36,54 +35,30 @@ public DbAuthenticationStateProvider( { var userJourneyIds = GetUserJourneyIdsFromCookie(httpContext); - _transaction ??= await CreateTransaction(); - - var retryPolicy = Policy - .Handle(IsPostgresSerializationError) - .RetryAsync( - 3, - onRetryAsync: async (ex, retryCount) => - { - // Transaction will be aborted at this point - create a new one - await _transaction.DisposeAsync(); - _transaction = await CreateTransaction(); - }); + _transaction ??= await _dbContext.Database.BeginTransactionAsync(System.Data.IsolationLevel.ReadCommitted); if (httpContext.Request.Query.TryGetValue(AuthenticationStateMiddleware.IdQueryParameterName, out var asidStr) && Guid.TryParse(asidStr, out var journeyId) && userJourneyIds.Contains(journeyId)) { - return await retryPolicy.ExecuteAsync(async () => - { - using var suppressScope = SentryErrors.Suppress(IsPostgresSerializationError); + var dbAuthState = await _dbContext.AuthenticationStates.FromSqlInterpolated( + $"select * from authentication_states where journey_id = {journeyId} for update") + .SingleOrDefaultAsync(); - var dbAuthState = await _dbContext.AuthenticationStates.FromSqlInterpolated( - $"select * from authentication_states where journey_id = {journeyId} for update") - .SingleOrDefaultAsync(); - - if (dbAuthState is not null) + if (dbAuthState is not null) + { + try { - try - { - return AuthenticationState.Deserialize(dbAuthState.Payload); - } - catch (Exception ex) - { - _logger.LogError(ex, $"Failed deserializing {nameof(AuthenticationState)}."); - } + return AuthenticationState.Deserialize(dbAuthState.Payload); } - - return null; - }); + catch (Exception ex) + { + _logger.LogError(ex, $"Failed deserializing {nameof(AuthenticationState)}."); + } + } } return null; - - static bool IsPostgresSerializationError(Exception ex) => - ex.InnerException is PostgresException pex && pex.SqlState == PostgresErrorCodes.SerializationFailure; - - Task CreateTransaction() => - _dbContext.Database.BeginTransactionAsync(System.Data.IsolationLevel.RepeatableRead); } public async Task SetAuthenticationState(HttpContext httpContext, AuthenticationState authenticationState)