Skip to content

Commit d99ac36

Browse files
Spomkyclaude
andcommitted
fix: enforce HTTPS scheme check before host matching in CheckAllowedOrigins fallback path
The HTTPS scheme check was unreachable in the fallback path (no allowed origins configured) because the method returned early on host match. Move the check before host comparison so it is always enforced. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 50445d6 commit d99ac36

File tree

2 files changed

+13
-8
lines changed

2 files changed

+13
-8
lines changed

src/webauthn/src/CeremonyStep/CeremonyStepManagerFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public function creationCeremony(): CeremonyStepManager
135135
new CheckChallenge(),
136136
$this->allowedOrigins === null ? new CheckOrigin(
137137
$this->securedRelyingPartyId ?? []
138-
) : new CheckAllowedOrigins($this->allowedOrigins, $this->allowSubdomains),
138+
) : new CheckAllowedOrigins($this->allowedOrigins, $this->allowSubdomains, $this->securedRelyingPartyId ?? []),
139139
new CheckTopOrigin($this->topOriginValidator),
140140
new CheckRelyingPartyIdIdHash(),
141141
new CheckUserWasPresent(),
@@ -160,7 +160,7 @@ public function requestCeremony(): CeremonyStepManager
160160
new CheckChallenge(),
161161
$this->allowedOrigins === null ? new CheckOrigin(
162162
$this->securedRelyingPartyId ?? []
163-
) : new CheckAllowedOrigins($this->allowedOrigins, $this->allowSubdomains),
163+
) : new CheckAllowedOrigins($this->allowedOrigins, $this->allowSubdomains, $this->securedRelyingPartyId ?? []),
164164
new CheckTopOrigin(),
165165
new CheckRelyingPartyIdIdHash(),
166166
new CheckUserWasPresent(),

src/webauthn/src/CeremonyStep/CheckAllowedOrigins.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@
3838

3939
/**
4040
* @param string[] $allowedOrigins
41+
* @param string[] $securedRelyingPartyId RP IDs that are allowed to use HTTP (e.g. localhost for development)
4142
*/
4243
public function __construct(
4344
array $allowedOrigins,
44-
private bool $allowSubdomains = false
45+
private bool $allowSubdomains = false,
46+
private array $securedRelyingPartyId = [],
4547
) {
4648
$fullOrigins = [];
4749
$hostOrigins = [];
@@ -113,6 +115,13 @@ public function process(
113115

114116
$rpId = $publicKeyCredentialOptions->rpId ?? $publicKeyCredentialOptions->rp->id ?? $host;
115117
$facetId = $this->getFacetId($rpId, $publicKeyCredentialOptions->extensions, $authData->extensions);
118+
119+
if (! in_array($facetId, $this->securedRelyingPartyId, true)) {
120+
$scheme = $parsedOrigin['scheme'] ?? '';
121+
$scheme === 'https' || throw AuthenticatorResponseVerificationException::create(
122+
'Invalid scheme. HTTPS required.'
123+
);
124+
}
116125
$facetId !== '' || throw AuthenticatorResponseVerificationException::create(
117126
'Invalid origin. Unable to determine the facet ID.'
118127
);
@@ -126,11 +135,7 @@ public function process(
126135
if (! $this->allowSubdomains && $isSubDomains) {
127136
throw AuthenticatorResponseVerificationException::create('Invalid origin. Subdomains are not allowed.');
128137
}
129-
130-
$scheme = $parsedOrigin['scheme'] ?? '';
131-
$scheme === 'https' || throw AuthenticatorResponseVerificationException::create(
132-
'Invalid scheme. HTTPS required.'
133-
);
138+
throw AuthenticatorResponseVerificationException::create('Invalid origin.');
134139
}
135140

136141
/**

0 commit comments

Comments
 (0)