♻️ Refactor the state and auth system
This commit is contained in:
		| @@ -176,23 +176,52 @@ public class ConnectionController( | ||||
|         if (callbackData.State == null) | ||||
|             return BadRequest("State parameter is missing."); | ||||
|  | ||||
|         // Get and validate state from cache | ||||
|         // Get the state from the cache | ||||
|         var stateKey = $"{StateCachePrefix}{callbackData.State}"; | ||||
|         var stateValue = await cache.GetAsync<string>(stateKey); | ||||
|         if (string.IsNullOrEmpty(stateValue)) | ||||
|             return BadRequest("Invalid or expired state parameter"); | ||||
|  | ||||
|         // Remove state from cache to prevent replay attacks | ||||
|          | ||||
|         // Try to get the state as OidcState first (new format) | ||||
|         var oidcState = await cache.GetAsync<OidcState>(stateKey); | ||||
|          | ||||
|         // If not found, try to get as string (legacy format) | ||||
|         if (oidcState == null) | ||||
|         { | ||||
|             var stateValue = await cache.GetAsync<string>(stateKey); | ||||
|             if (string.IsNullOrEmpty(stateValue) || !OidcState.TryParse(stateValue, out oidcState) || oidcState == null) | ||||
|                 return BadRequest("Invalid or expired state parameter"); | ||||
|         } | ||||
|          | ||||
|         // Remove the state from cache to prevent replay attacks | ||||
|         await cache.RemoveAsync(stateKey); | ||||
|  | ||||
|         var stateParts = stateValue.Split('|'); | ||||
|         if (stateParts.Length != 3) | ||||
|         // Handle the flow based on state type | ||||
|         if (oidcState.FlowType == OidcFlowType.Connect && oidcState.AccountId.HasValue) | ||||
|         { | ||||
|             return BadRequest("Invalid state format"); | ||||
|             // Connection flow | ||||
|             if (oidcState.DeviceId != null) | ||||
|             { | ||||
|                 callbackData.State = oidcState.DeviceId; | ||||
|             } | ||||
|             return await HandleManualConnection(provider, oidcService, callbackData, oidcState.AccountId.Value); | ||||
|         } | ||||
|         else if (oidcState.FlowType == OidcFlowType.Login) | ||||
|         { | ||||
|             // Login/Registration flow | ||||
|             if (!string.IsNullOrEmpty(oidcState.DeviceId)) | ||||
|             { | ||||
|                 callbackData.State = oidcState.DeviceId; | ||||
|             } | ||||
|  | ||||
|             // Store return URL if provided | ||||
|             if (!string.IsNullOrEmpty(oidcState.ReturnUrl) && oidcState.ReturnUrl != "/") | ||||
|             { | ||||
|                 var returnUrlKey = $"{ReturnUrlCachePrefix}{callbackData.State}"; | ||||
|                 await cache.SetAsync(returnUrlKey, oidcState.ReturnUrl, StateExpiration); | ||||
|             } | ||||
|  | ||||
|             return await HandleLoginOrRegistration(provider, oidcService, callbackData); | ||||
|         } | ||||
|  | ||||
|         var accountId = Guid.Parse(stateParts[0]); | ||||
|         return await HandleManualConnection(provider, oidcService, callbackData, accountId); | ||||
|         return BadRequest("Unsupported flow type"); | ||||
|     } | ||||
|  | ||||
|     private async Task<IActionResult> HandleManualConnection( | ||||
| @@ -219,6 +248,9 @@ public class ConnectionController( | ||||
|             return BadRequest($"{provider} did not return a valid user identifier."); | ||||
|         } | ||||
|  | ||||
|         // Extract device ID from the callback state if available | ||||
|         var deviceId = !string.IsNullOrEmpty(callbackData.State) ? callbackData.State : string.Empty; | ||||
|  | ||||
|         // Check if this provider account is already connected to any user | ||||
|         var existingConnection = await db.AccountConnections | ||||
|             .FirstOrDefaultAsync(c => | ||||
| @@ -314,9 +346,16 @@ public class ConnectionController( | ||||
|         if (connection != null) | ||||
|         { | ||||
|             // Login existing user | ||||
|             var session = await auth.CreateSessionAsync(connection.Account, clock.GetCurrentInstant()); | ||||
|             var token = auth.CreateToken(session); | ||||
|             return Redirect($"/auth/token?token={token}"); | ||||
|             var deviceId = !string.IsNullOrEmpty(callbackData.State) ?  | ||||
|                 callbackData.State.Split('|').FirstOrDefault() :  | ||||
|                 string.Empty; | ||||
|                  | ||||
|             var challenge = await oidcService.CreateChallengeForUserAsync( | ||||
|                 userInfo,  | ||||
|                 connection.Account,  | ||||
|                 HttpContext,  | ||||
|                 deviceId ?? string.Empty); | ||||
|             return Redirect($"/auth/callback?context={challenge.Id}"); | ||||
|         } | ||||
|  | ||||
|         // Register new user | ||||
|   | ||||
		Reference in New Issue
	
	Block a user