From 26fcfef2352d673ebc7838334377990eb63b92b9 Mon Sep 17 00:00:00 2001 From: Patrick Pimentel Date: Fri, 23 Jan 2026 18:04:26 -0500 Subject: [PATCH] fix(redirect): [PM-30810] Https Redirection for Cloud Users - Used reflection instead of change the interface. --- .../DuoUniversalTokenService.cs | 11 +------- .../Services/DuoUniversalTokenServiceTests.cs | 28 +++++++++++++------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Core/Auth/Identity/TokenProviders/DuoUniversalTokenService.cs b/src/Core/Auth/Identity/TokenProviders/DuoUniversalTokenService.cs index a6dbce032e..2604efbcf2 100644 --- a/src/Core/Auth/Identity/TokenProviders/DuoUniversalTokenService.cs +++ b/src/Core/Auth/Identity/TokenProviders/DuoUniversalTokenService.cs @@ -77,15 +77,6 @@ public interface IDuoUniversalTokenService /// TwoFactorProvider Duo or OrganizationDuo /// Duo.Client object or null Task BuildDuoTwoFactorClientAsync(TwoFactorProvider provider); - - /// - /// Builds the redirect URI for Duo authentication based on the client type and request context. - /// Mobile clients include a deeplinkScheme parameter (https for cloud, bitwarden for self-hosted). - /// Desktop clients always use the bitwarden scheme. - /// Other clients (web, browser, cli) do not include the deeplinkScheme parameter. - /// - /// The redirect URI to be used for Duo authentication - string BuildDuoTwoFactorRedirectUri(); } public class DuoUniversalTokenService( @@ -220,7 +211,7 @@ public class DuoUniversalTokenService( return Enum.TryParse(candidate, ignoreCase: true, out var scheme) ? scheme : null; } - public string BuildDuoTwoFactorRedirectUri() + private string BuildDuoTwoFactorRedirectUri() { // Fetch Client name from header value since duo auth can be initiated from multiple clients and we want // to redirect back to the initiating client diff --git a/test/Core.Test/Auth/Services/DuoUniversalTokenServiceTests.cs b/test/Core.Test/Auth/Services/DuoUniversalTokenServiceTests.cs index 2ad06fdd76..bb374a4405 100644 --- a/test/Core.Test/Auth/Services/DuoUniversalTokenServiceTests.cs +++ b/test/Core.Test/Auth/Services/DuoUniversalTokenServiceTests.cs @@ -1,4 +1,5 @@ -using Bit.Core.Auth.Identity.TokenProviders; +using System.Reflection; +using Bit.Core.Auth.Identity.TokenProviders; using Bit.Core.Auth.Models; using Bit.Core.Context; using Bit.Test.Common.AutoFixture; @@ -13,6 +14,17 @@ namespace Bit.Core.Test.Auth.Services; [SutProviderCustomize] public class DuoUniversalTokenServiceTests { + /// + /// Helper method to invoke the private BuildDuoTwoFactorRedirectUri method via reflection. + /// + private static string InvokeBuildDuoTwoFactorRedirectUri(DuoUniversalTokenService sut) + { + var method = typeof(DuoUniversalTokenService).GetMethod( + "BuildDuoTwoFactorRedirectUri", + BindingFlags.NonPublic | BindingFlags.Instance); + return (string)method!.Invoke(sut, null)!; + } + [Theory] [BitAutoData("", "ClientId", "ClientSecret")] [BitAutoData("api-valid.duosecurity.com", "", "ClientSecret")] @@ -113,7 +125,7 @@ public class DuoUniversalTokenServiceTests var sut = new DuoUniversalTokenService(currentContext, globalSettings); // Act - var result = sut.BuildDuoTwoFactorRedirectUri(); + var result = InvokeBuildDuoTwoFactorRedirectUri(sut); // Assert Assert.Contains("client=mobile", result); @@ -143,7 +155,7 @@ public class DuoUniversalTokenServiceTests var sut = new DuoUniversalTokenService(currentContext, globalSettings); // Act - var result = sut.BuildDuoTwoFactorRedirectUri(); + var result = InvokeBuildDuoTwoFactorRedirectUri(sut); // Assert Assert.Contains("client=mobile", result); @@ -169,7 +181,7 @@ public class DuoUniversalTokenServiceTests var sut = new DuoUniversalTokenService(currentContext, globalSettings); // Act - var result = sut.BuildDuoTwoFactorRedirectUri(); + var result = InvokeBuildDuoTwoFactorRedirectUri(sut); // Assert Assert.Contains("client=desktop", result); @@ -199,7 +211,7 @@ public class DuoUniversalTokenServiceTests var sut = new DuoUniversalTokenService(currentContext, globalSettings); // Act - var result = sut.BuildDuoTwoFactorRedirectUri(); + var result = InvokeBuildDuoTwoFactorRedirectUri(sut); // Assert Assert.Contains($"client={clientName}", result); @@ -225,7 +237,7 @@ public class DuoUniversalTokenServiceTests var sut = new DuoUniversalTokenService(currentContext, globalSettings); // Act - var result = sut.BuildDuoTwoFactorRedirectUri(); + var result = InvokeBuildDuoTwoFactorRedirectUri(sut); // Assert Assert.Contains("client=web", result); @@ -254,7 +266,7 @@ public class DuoUniversalTokenServiceTests var sut = new DuoUniversalTokenService(currentContext, globalSettings); // Act - var result = sut.BuildDuoTwoFactorRedirectUri(); + var result = InvokeBuildDuoTwoFactorRedirectUri(sut); // Assert Assert.Contains("client=web", result); @@ -284,7 +296,7 @@ public class DuoUniversalTokenServiceTests var sut = new DuoUniversalTokenService(currentContext, globalSettings); // Act - var result = sut.BuildDuoTwoFactorRedirectUri(); + var result = InvokeBuildDuoTwoFactorRedirectUri(sut); // Assert Assert.Contains("client=mobile", result);