11/*
2- * Copyright (C) 2024 KeePassXC Team <team@keepassxc.org>
2+ * Copyright (C) 2026 KeePassXC Team <team@keepassxc.org>
33 *
44 * This program is free software: you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@ BrowserPasskeysClient* BrowserPasskeysClient::instance()
3333// https://www.w3.org/TR/2019/REC-webauthn-1-20190304/#createCredential
3434int BrowserPasskeysClient::getCredentialCreationOptions (const QJsonObject& publicKeyOptions,
3535 const QString& origin,
36+ const QStringList& relatedOrigins,
3637 QJsonObject* result) const
3738{
3839 if (!result || publicKeyOptions.isEmpty ()) {
@@ -41,23 +42,26 @@ int BrowserPasskeysClient::getCredentialCreationOptions(const QJsonObject& publi
4142
4243 // Check validity of some basic values
4344 const auto checkResultError = passkeyUtils ()->checkLimits (publicKeyOptions);
44- if (checkResultError > 0 ) {
45+ if (checkResultError != PASSKEYS_SUCCESS ) {
4546 return checkResultError;
4647 }
4748
4849 // Get effective domain
4950 QString effectiveDomain;
5051 const auto effectiveDomainResponse = passkeyUtils ()->getEffectiveDomain (origin, &effectiveDomain);
51- if (effectiveDomainResponse > 0 ) {
52+ if (effectiveDomainResponse != PASSKEYS_SUCCESS ) {
5253 return effectiveDomainResponse;
5354 }
5455
5556 // Validate RP ID
5657 QString rpId;
5758 const auto rpName = publicKeyOptions[" rp" ][" name" ].toString ();
5859 const auto rpIdResponse = passkeyUtils ()->validateRpId (publicKeyOptions[" rp" ][" id" ], effectiveDomain, &rpId);
59- if (rpIdResponse > 0 ) {
60- return rpIdResponse;
60+ if (rpIdResponse != PASSKEYS_SUCCESS) {
61+ // Validate Related Origin Requests if found
62+ if (relatedOrigins.isEmpty () || !passkeyUtils ()->validateRelatedOrigins (relatedOrigins, origin)) {
63+ return rpIdResponse;
64+ }
6165 }
6266
6367 // Check PublicKeyCredentialTypes
@@ -126,6 +130,7 @@ int BrowserPasskeysClient::getCredentialCreationOptions(const QJsonObject& publi
126130// https://www.w3.org/TR/2019/REC-webauthn-1-20190304/#getAssertion
127131int BrowserPasskeysClient::getAssertionOptions (const QJsonObject& publicKeyOptions,
128132 const QString& origin,
133+ const QStringList& relatedOrigins,
129134 QJsonObject* result) const
130135{
131136 if (!result || publicKeyOptions.isEmpty ()) {
@@ -135,15 +140,18 @@ int BrowserPasskeysClient::getAssertionOptions(const QJsonObject& publicKeyOptio
135140 // Get effective domain
136141 QString effectiveDomain;
137142 const auto effectiveDomainResponse = passkeyUtils ()->getEffectiveDomain (origin, &effectiveDomain);
138- if (effectiveDomainResponse > 0 ) {
143+ if (effectiveDomainResponse != PASSKEYS_SUCCESS ) {
139144 return effectiveDomainResponse;
140145 }
141146
142147 // Validate RP ID
143148 QString rpId;
144149 const auto rpIdResponse = passkeyUtils ()->validateRpId (publicKeyOptions[" rpId" ], effectiveDomain, &rpId);
145- if (rpIdResponse > 0 ) {
146- return rpIdResponse;
150+ if (rpIdResponse != PASSKEYS_SUCCESS) {
151+ // Validate Related Origin Requests if found
152+ if (relatedOrigins.isEmpty () || !passkeyUtils ()->validateRelatedOrigins (relatedOrigins, origin)) {
153+ return rpIdResponse;
154+ }
147155 }
148156
149157 // Extensions
0 commit comments