blob: bf84f5057e0236bb93e32b6433bb13e61dcc115c [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/webauthn/chrome_web_authentication_delegate_base.h"
#include "base/test/scoped_command_line.h"
#include "chrome/browser/webauthn/webauthn_pref_names.h"
#include "chrome/browser/webauthn/webauthn_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
namespace {
class OriginMayUseRemoteDesktopClientOverrideTest
: public ChromeRenderViewHostTestHarness {
protected:
static constexpr char kCorpCrdOrigin[] =
"https://remotedesktop.corp.google.com";
static constexpr char kCorpCrdAutopushOrigin[] =
"https://remotedesktop-autopush.corp.google.com/";
static constexpr char kCorpCrdDailyOrigin[] =
"https://remotedesktop-daily-6.corp.google.com/";
const std::array<const char*, 3> kCorpCrdOrigins = {
kCorpCrdOrigin, kCorpCrdAutopushOrigin, kCorpCrdDailyOrigin};
static constexpr char kExampleOrigin[] = "https://example.com";
static constexpr char kAnotherExampleOrigin[] = "https://another.example.com";
};
#if !BUILDFLAG(IS_ANDROID)
TEST_F(OriginMayUseRemoteDesktopClientOverrideTest,
RemoteProxiedRequestsAllowedPolicy) {
// The "webauthn.remote_proxied_requests_allowed" policy pref should enable
// Google's internal CRD origin to use the RemoteDesktopClientOverride
// extension.
enum class Policy {
kUnset,
kDisabled,
kEnabled,
};
ChromeWebAuthenticationDelegateBase delegate;
PrefService* prefs =
Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
for (auto* origin : kCorpCrdOrigins) {
for (const auto policy :
{Policy::kUnset, Policy::kDisabled, Policy::kEnabled}) {
switch (policy) {
case Policy::kUnset:
prefs->ClearPref(webauthn::pref_names::kRemoteProxiedRequestsAllowed);
break;
case Policy::kDisabled:
prefs->SetBoolean(webauthn::pref_names::kRemoteProxiedRequestsAllowed,
false);
break;
case Policy::kEnabled:
prefs->SetBoolean(webauthn::pref_names::kRemoteProxiedRequestsAllowed,
true);
break;
}
constexpr const char* const crd_origins[] = {
kCorpCrdOrigin,
kCorpCrdAutopushOrigin,
kCorpCrdDailyOrigin,
};
EXPECT_EQ(
delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(origin))),
base::Contains(crd_origins, origin) && policy == Policy::kEnabled);
}
}
}
TEST_F(OriginMayUseRemoteDesktopClientOverrideTest,
AdditionalOriginSwitch_WithGooglePolicy) {
// The --webauthn-remote-proxied-requests-allowed-additional-origin switch
// allows passing an additional origin for testing.
ChromeWebAuthenticationDelegateBase delegate;
base::test::ScopedCommandLine scoped_command_line;
scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII(
webauthn::switches::kRemoteProxiedRequestsAllowedAdditionalOrigin,
kExampleOrigin);
// The flag shouldn't have an effect without the policy enabled.
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kCorpCrdOrigin))));
// With the policy enabled, both the hard-coded and flag origin should be
// allowed.
PrefService* prefs =
Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
prefs->SetBoolean(webauthn::pref_names::kRemoteProxiedRequestsAllowed, true);
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kCorpCrdOrigin))));
// Other origins still shouldn't be permitted.
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(),
url::Origin::Create(GURL("https://other.example.com"))));
}
#endif // !BUILDFLAG(IS_ANDROID)
TEST_F(OriginMayUseRemoteDesktopClientOverrideTest,
AdditionalOriginSwitch_WithAllowedOriginsPolicy) {
// The --webauthn-remote-proxied-requests-allowed-additional-origin switch
// allows passing an additional origin for testing. This origin will be
// allowed if the WebAuthenticationRemoteDesktopAllowedOrigins policy is set
// to a non-empty list of origins. If the policy is set, the command-line
// origin is treated as another allowed origin in addition to those specified
// by the policy.
ChromeWebAuthenticationDelegateBase delegate;
base::test::ScopedCommandLine scoped_command_line;
scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII(
webauthn::switches::kRemoteProxiedRequestsAllowedAdditionalOrigin,
kExampleOrigin);
// Initially, no origins should be allowed because the allowed origins pref
// hasn't been set yet.
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kAnotherExampleOrigin))));
// Set the allowed origins pref to include another origin.
PrefService* prefs =
Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
base::Value::List().Append(kAnotherExampleOrigin));
// Both the origin specified by the command-line switch and the origin in the
// allowed origins pref should be allowed.
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kAnotherExampleOrigin))));
// Google Corp CRD origins are not affected by either the switch or this
// policy.
for (auto* origin : kCorpCrdOrigins) {
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(origin))));
}
// Origins not listed in either the switch or the policy remain disallowed.
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(),
url::Origin::Create(GURL("https://very.other.example.com"))));
}
TEST_F(OriginMayUseRemoteDesktopClientOverrideTest,
AdditionalOriginSwitch_WithExplicitlyEmptyAllowedOriginsPolicy) {
// The --webauthn-remote-proxied-requests-allowed-additional-origin switch
// should be ignored when the allowed origins policy list is empty.
ChromeWebAuthenticationDelegateBase delegate;
base::test::ScopedCommandLine scoped_command_line;
scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII(
webauthn::switches::kRemoteProxiedRequestsAllowedAdditionalOrigin,
kExampleOrigin);
PrefService* prefs =
Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
// Test with policy unset.
prefs->ClearPref(webauthn::pref_names::kRemoteDesktopAllowedOrigins);
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
// Test with policy explicitly empty.
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
base::Value::List());
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
}
TEST_F(OriginMayUseRemoteDesktopClientOverrideTest,
AllowedOriginsPolicy_InvalidURLs) {
ChromeWebAuthenticationDelegateBase delegate;
PrefService* prefs =
Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
const std::vector<std::string> invalid_origins = {
"invalid",
"http://",
"example.com", // Missing scheme
"https://example.com:invalidport",
};
base::Value::List invalid_origins_list;
for (const auto& origin : invalid_origins) {
invalid_origins_list.Append(origin);
}
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
std::move(invalid_origins_list));
// None of the above invalid origins should grant access.
for (const auto& origin : invalid_origins) {
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(origin))));
}
// A valid one, added for good measure, should still work.
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
base::Value::List().Append(kExampleOrigin));
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
}
TEST_F(OriginMayUseRemoteDesktopClientOverrideTest,
AllowedOriginsPolicy_MultipleValidURLs) {
ChromeWebAuthenticationDelegateBase delegate;
PrefService* prefs =
Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
base::Value::List valid_origins;
valid_origins.Append(kExampleOrigin);
valid_origins.Append(kAnotherExampleOrigin);
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
std::move(valid_origins));
// Both origins specified in the policy should grant access.
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kExampleOrigin))));
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL(kAnotherExampleOrigin))));
// An unrelated origin should not be allowed.
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(),
url::Origin::Create(GURL("https://very.other.example.com"))));
}
TEST_F(OriginMayUseRemoteDesktopClientOverrideTest,
AllowedOriginsPolicy_SchemePortPathMismatch) {
ChromeWebAuthenticationDelegateBase delegate;
PrefService* prefs =
Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
// Scheme mismatch.
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
base::Value::List().Append("https://example.com"));
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL("http://example.com"))));
// Port mismatch.
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
base::Value::List().Append("https://example.com:1234"));
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL("https://example.com"))));
EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(),
url::Origin::Create(GURL("https://example.com:5678"))));
// Path mismatch (should be allowed because paths are ignored).
prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins,
base::Value::List().Append("https://example.com/path"));
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(), url::Origin::Create(GURL("https://example.com"))));
EXPECT_TRUE(delegate.OriginMayUseRemoteDesktopClientOverride(
browser_context(),
url::Origin::Create(GURL("https://example.com/otherpath"))));
}
} // namespace