using Thalos.Bff.Application.Security.Oidc; namespace Thalos.Bff.Application.UnitTests; public class GoogleOidcFlowServiceTests { [Fact] public void BuildStartContext_WhenReturnUrlAllowed_PreservesCallerReturnUrl() { var service = new GoogleOidcFlowService(CreateOptions(), "state-signing-secret"); var context = service.BuildStartContext("https://furniture-display-demo.dream-views.com/dashboard", "tenant-1"); Assert.Equal("https://furniture-display-demo.dream-views.com/dashboard", context.Payload.ReturnUrl); Assert.Equal("tenant-1", context.Payload.TenantId); Assert.Contains("code_challenge_method=S256", context.AuthorizationUrl); Assert.Contains("state=", context.AuthorizationUrl); Assert.Contains("nonce=", context.AuthorizationUrl); } [Fact] public void BuildStartContext_WhenReturnUrlNotAllowed_UsesDefaultReturnUrl() { var service = new GoogleOidcFlowService(CreateOptions(), "state-signing-secret"); var context = service.BuildStartContext("https://malicious.example.com/redirect", "tenant-1"); Assert.Equal("https://auth.dream-views.com/", context.Payload.ReturnUrl); } [Fact] public void TryValidateCallbackState_WhenStateMatchesAndNotExpired_ReturnsTrue() { var service = new GoogleOidcFlowService(CreateOptions(), "state-signing-secret"); var start = service.BuildStartContext("https://auth.dream-views.com/", "tenant-1"); var ok = service.TryValidateCallbackState(start.EncodedState, start.Payload.State, out var payload); Assert.True(ok); Assert.Equal(start.Payload.CodeVerifier, payload.CodeVerifier); Assert.Equal(start.Payload.TenantId, payload.TenantId); } [Fact] public void TryValidateCallbackState_WhenStateTampered_ReturnsFalse() { var service = new GoogleOidcFlowService(CreateOptions(), "state-signing-secret"); var start = service.BuildStartContext("https://auth.dream-views.com/", "tenant-1"); var ok = service.TryValidateCallbackState(start.EncodedState, $"{start.Payload.State}-tamper", out _); Assert.False(ok); } private static GoogleOidcOptions CreateOptions() { return new GoogleOidcOptions( "client-id-1", "client-secret-1", "https://auth.dream-views.com/api/identity/oidc/google/callback", "https://accounts.google.com/o/oauth2/v2/auth", "https://oauth2.googleapis.com/token", "openid profile email", "https://auth.dream-views.com/", "demo-tenant", ["auth.dream-views.com", "furniture-display-demo.dream-views.com"], TimeSpan.FromMinutes(10)); } }