Changeset 291018 in webkit


Ignore:
Timestamp:
Mar 8, 2022 3:51:45 PM (4 months ago)
Author:
J Pascoe
Message:

[WebAuthn] Using WebAuthn within cross-origin iframe elements
https://bugs.webkit.org/show_bug.cgi?id=222240
rdar://problem/74830748

Reviewed by Brent Fulgham.

Source/WebCore:

This patch relaxes the requirement to perform a Web Authentication assertion
inside an i-frame with the "publickey-credentials-get" feature policy from
'same-site' to 'cross-origin with consent'.

There is an additional requirement that there is only a single cross-origin
parent to present to the user in the prompt. If we can't display the updated
prompt, then cross-origin assertions are not allowed.

Test: http/wpt/webauthn/public-key-credential-cross-origin.https.html

  • Modules/credentialmanagement/CredentialsContainer.cpp:

(WebCore::CredentialsContainer::scopeAndSingleParent):
(WebCore::CredentialsContainer::get):
(WebCore::CredentialsContainer::isCreate):
(WebCore::CredentialsContainer::scope): Deleted.

  • Modules/credentialmanagement/CredentialsContainer.h:
  • Modules/webauthn/AuthenticatorCoordinator.cpp:

(WebCore::AuthenticatorCoordinator::discoverFromExternalSource const):

  • Modules/webauthn/AuthenticatorCoordinator.h:
  • Modules/webauthn/AuthenticatorCoordinatorClient.h:

Source/WebKit:

This patch relaxes the requirement to perform a Web Authentication assertion
inside an i-frame with the "publickey-credentials-get" feature policy from
'same-site' to 'cross-origin with consent'.

There is an additional requirement that there is only a single cross-origin
parent to present to the user in the prompt. If we can't display the updated
prompt, then cross-origin assertions are not allowed.

  • Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h:
  • UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm:

(WebKit::configureAssertionOptions):
(WebKit::configurationAssertionRequestContext):
(WebKit::WebAuthenticatorCoordinatorProxy::contextForRequest):

  • UIProcess/WebAuthentication/WebAuthenticationRequestData.h:
  • UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp:

(WebKit::WebAuthenticatorCoordinatorProxy::makeCredential):
(WebKit::WebAuthenticatorCoordinatorProxy::getAssertion):
(WebKit::WebAuthenticatorCoordinatorProxy::handleRequest):

  • UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h:
  • UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in:
  • WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp:

(WebKit::WebAuthenticatorCoordinator::getAssertion):

  • WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h:

LayoutTests:

Update existing tests and create new test for cross-origin, non same-site i-frames.

  • http/wpt/webauthn/public-key-credential-cross-origin.https-expected.txt: Added.
  • http/wpt/webauthn/public-key-credential-cross-origin.https.html: Added.
  • http/wpt/webauthn/public-key-credential-same-origin-with-ancestors.https-expected.txt:
  • http/wpt/webauthn/public-key-credential-same-origin-with-ancestors.https.html:
  • http/wpt/webauthn/resources/public-key-credential-cross-origin.https.html: Added.
Location:
trunk
Files:
3 added
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r291009 r291018  
     12022-03-08  J Pascoe  <j_pascoe@apple.com>
     2
     3        [WebAuthn] Using WebAuthn within cross-origin iframe elements
     4        https://bugs.webkit.org/show_bug.cgi?id=222240
     5        rdar://problem/74830748
     6
     7        Reviewed by Brent Fulgham.
     8
     9        Update existing tests and create new test for cross-origin, non same-site i-frames.
     10
     11        * http/wpt/webauthn/public-key-credential-cross-origin.https-expected.txt: Added.
     12        * http/wpt/webauthn/public-key-credential-cross-origin.https.html: Added.
     13        * http/wpt/webauthn/public-key-credential-same-origin-with-ancestors.https-expected.txt:
     14        * http/wpt/webauthn/public-key-credential-same-origin-with-ancestors.https.html:
     15        * http/wpt/webauthn/resources/public-key-credential-cross-origin.https.html: Added.
     16
    1172022-03-08  Chris Fleizach  <cfleizach@apple.com>
    218
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-same-origin-with-ancestors.https-expected.txt

    r287116 r291018  
    55PASS Tests that a frame that is same-site, cross-origin without publickey-credentials-get feature policy cannot use get().
    66PASS Tests that a frame that is same-site, cross-origin with publickey-credentials-get feature policy can use get().
    7 PASS Tests that a frame that is cross-origin, NOT same-site with publickey-credentials-get feature policy cannot use get().
     7PASS Tests that a frame using an ip address that is cross-origin, NOT same-site with publickey-credentials-get feature policy cannot use get().
    88
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-same-origin-with-ancestors.https.html

    r287116 r291018  
    1 <!DOCTYPE html><!-- webkit-test-runner [ WebAuthenticationModernEnabled=true ] -->
     1<!DOCTYPE html><!-- webkit-test-runner [ WebAuthenticationModernEnabled=false ] -->
    22<html>
    33<head>
     
    3838        promise_test(t => {
    3939            return withCrossOriginIframe("samesite-iframe.html", "publickey-credentials-get").then((message) => {
    40                 assert_equals(message.data, "Throw NotAllowedError: The origin of the document is not the same as its ancestors.");
     40                assert_equals(message.data, "Throw SecurityError: The effective domain of the document is not a valid domain.");
    4141            });
    42         }, "Tests that a frame that is cross-origin, NOT same-site with publickey-credentials-get feature policy cannot use get().");
     42        }, "Tests that a frame using an ip address that is cross-origin, NOT same-site with publickey-credentials-get feature policy cannot use get().");
    4343    </script>
    4444</body>
  • trunk/Source/WebCore/ChangeLog

    r291017 r291018  
     12022-03-08  J Pascoe  <j_pascoe@apple.com>
     2
     3        [WebAuthn] Using WebAuthn within cross-origin iframe elements
     4        https://bugs.webkit.org/show_bug.cgi?id=222240
     5        rdar://problem/74830748
     6
     7        Reviewed by Brent Fulgham.
     8
     9        This patch relaxes the requirement to perform a Web Authentication assertion
     10        inside an i-frame with the "publickey-credentials-get" feature policy from
     11        'same-site' to 'cross-origin with consent'.
     12
     13        There is an additional requirement that there is only a single cross-origin
     14        parent to present to the user in the prompt. If we can't display the updated
     15        prompt, then cross-origin assertions are not allowed.
     16
     17        Test: http/wpt/webauthn/public-key-credential-cross-origin.https.html
     18
     19        * Modules/credentialmanagement/CredentialsContainer.cpp:
     20        (WebCore::CredentialsContainer::scopeAndSingleParent):
     21        (WebCore::CredentialsContainer::get):
     22        (WebCore::CredentialsContainer::isCreate):
     23        (WebCore::CredentialsContainer::scope): Deleted.
     24        * Modules/credentialmanagement/CredentialsContainer.h:
     25        * Modules/webauthn/AuthenticatorCoordinator.cpp:
     26        (WebCore::AuthenticatorCoordinator::discoverFromExternalSource const):
     27        * Modules/webauthn/AuthenticatorCoordinator.h:
     28        * Modules/webauthn/AuthenticatorCoordinatorClient.h:
     29
    1302022-03-08  Chris Dumez  <cdumez@apple.com>
    231
  • trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.cpp

    r290184 r291018  
    4747}
    4848
    49 WebAuthn::Scope CredentialsContainer::scope()
     49ScopeAndCrossOriginParent CredentialsContainer::scopeAndCrossOriginParent() const
    5050{
    5151    if (!m_document)
    52         return WebAuthn::Scope::CrossOrigin;
     52        return std::pair { WebAuthn::Scope::CrossOrigin, std::nullopt };
    5353
    54     bool isSameOrigin = true;
    5554    bool isSameSite = true;
    5655    auto& origin = m_document->securityOrigin();
    5756    auto& url = m_document->url();
     57    std::optional<SecurityOriginData> crossOriginParent;
    5858    for (auto* document = m_document->parentDocument(); document; document = document->parentDocument()) {
    5959        if (!origin.isSameOriginDomain(document->securityOrigin()) && !areRegistrableDomainsEqual(url, document->url()))
    6060            isSameSite = false;
    61         if (!origin.isSameOriginAs(document->securityOrigin()))
    62             isSameOrigin = false;
     61        if (!crossOriginParent && !origin.isSameOriginAs(document->securityOrigin()))
     62            crossOriginParent = origin.data();
    6363    }
    6464
    65     if (isSameOrigin)
    66         return WebAuthn::Scope::SameOrigin;
     65    if (!crossOriginParent)
     66        return std::pair { WebAuthn::Scope::SameOrigin, std::nullopt };
    6767    if (isSameSite)
    68         return WebAuthn::Scope::SameSite;
    69     return WebAuthn::Scope::CrossOrigin;
     68        return std::pair { WebAuthn::Scope::SameSite, std::nullopt };
     69    return std::pair { WebAuthn::Scope::CrossOrigin, crossOriginParent };
    7070}
    7171
     
    9999    }
    100100
    101     m_document->page()->authenticatorCoordinator().discoverFromExternalSource(*m_document, WTFMove(options), scope(), WTFMove(promise));
     101    m_document->page()->authenticatorCoordinator().discoverFromExternalSource(*m_document, WTFMove(options), scopeAndCrossOriginParent(), WTFMove(promise));
    102102}
    103103
     
    134134    }
    135135
    136     m_document->page()->authenticatorCoordinator().create(*m_document, options.publicKey.value(), scope(), WTFMove(options.signal), WTFMove(promise));
     136    m_document->page()->authenticatorCoordinator().create(*m_document, options.publicKey.value(), scopeAndCrossOriginParent().first, WTFMove(options.signal), WTFMove(promise));
    137137}
    138138
  • trunk/Source/WebCore/Modules/credentialmanagement/CredentialsContainer.h

    r287116 r291018  
    5959    CredentialsContainer(WeakPtr<Document>&&);
    6060
    61     WebAuthn::Scope scope();
     61    ScopeAndCrossOriginParent scopeAndCrossOriginParent() const;
    6262
    6363    WeakPtr<Document> m_document;
  • trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp

    r290515 r291018  
    185185}
    186186
    187 void AuthenticatorCoordinator::discoverFromExternalSource(const Document& document, CredentialRequestOptions&& requestOptions, WebAuthn::Scope scope, CredentialPromise&& promise) const
     187void AuthenticatorCoordinator::discoverFromExternalSource(const Document& document, CredentialRequestOptions&& requestOptions, const ScopeAndCrossOriginParent& scopeAndCrossOriginParent, CredentialPromise&& promise) const
    188188{
    189189    using namespace AuthenticatorCoordinatorInternal;
     
    196196    // Step 1, 3, 13 are handled by the caller.
    197197    // Step 2.
    198     // This implements https://www.w3.org/TR/webauthn-2/#sctn-permissions-policy except only same-site, cross-origin is permitted.
    199     if (scope != WebAuthn::Scope::SameOrigin && !(scope == WebAuthn::Scope::SameSite && isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::PublickeyCredentialsGetRule, document, LogFeaturePolicyFailure::No))) {
     198    // This implements https://www.w3.org/TR/webauthn-2/#sctn-permissions-policy
     199    if (scopeAndCrossOriginParent.first != WebAuthn::Scope::SameOrigin && !isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::PublickeyCredentialsGetRule, document, LogFeaturePolicyFailure::No)) {
    200200        promise.reject(Exception { NotAllowedError, "The origin of the document is not the same as its ancestors."_s });
    201201        return;
     
    231231
    232232    // Step 10-12.
    233     auto clientDataJson = buildClientDataJson(ClientDataType::Get, options.challenge, callerOrigin, scope);
     233    auto clientDataJson = buildClientDataJson(ClientDataType::Get, options.challenge, callerOrigin, scopeAndCrossOriginParent.first);
    234234    auto clientDataJsonHash = buildClientDataJsonHash(clientDataJson);
    235235
     
    255255    };
    256256    // Async operations are dispatched and handled in the messenger.
    257     m_client->getAssertion(*frame, callerOrigin, clientDataJsonHash, options, requestOptions.mediation, WTFMove(callback));
     257    m_client->getAssertion(*frame, callerOrigin, clientDataJsonHash, options, requestOptions.mediation, scopeAndCrossOriginParent, WTFMove(callback));
    258258}
    259259
  • trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.h

    r290184 r291018  
    4646struct PublicKeyCredentialRequestOptions;
    4747struct CredentialRequestOptions;
     48struct SecurityOriginData;
    4849
    4950template<typename IDLType> class DOMPromiseDeferred;
    5051
    5152using CredentialPromise = DOMPromiseDeferred<IDLNullable<IDLInterface<BasicCredential>>>;
     53using ScopeAndCrossOriginParent = std::pair<WebAuthn::Scope, std::optional<SecurityOriginData>>;
    5254
    5355class AuthenticatorCoordinator final {
     
    6062    // The following methods implement static methods of PublicKeyCredential.
    6163    void create(const Document&, const PublicKeyCredentialCreationOptions&, WebAuthn::Scope, RefPtr<AbortSignal>&&, CredentialPromise&&) const;
    62     void discoverFromExternalSource(const Document&, CredentialRequestOptions&&, WebAuthn::Scope, CredentialPromise&&) const;
     64    void discoverFromExternalSource(const Document&, CredentialRequestOptions&&, const ScopeAndCrossOriginParent&, CredentialPromise&&) const;
    6365    void isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred<IDLBoolean>&&) const;
    6466    void isConditionalMediationAvailable(DOMPromiseDeferred<IDLBoolean>&&) const;
  • trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h

    r290184 r291018  
    2828#if ENABLE(WEB_AUTHN)
    2929
     30#include "AuthenticatorCoordinator.h"
    3031#include "ExceptionData.h"
    3132#include <wtf/CompletionHandler.h>
    3233#include <wtf/WeakPtr.h>
     34
     35namespace WebAuthn {
     36enum class Scope;
     37}
    3338
    3439namespace WebCore {
     
    4449struct PublicKeyCredentialCreationOptions;
    4550struct PublicKeyCredentialRequestOptions;
     51struct SecurityOriginData;
    4652
    4753using RequestCompletionHandler = CompletionHandler<void(WebCore::AuthenticatorResponseData&&, WebCore::AuthenticatorAttachment, WebCore::ExceptionData&&)>;
     
    5662
    5763    virtual void makeCredential(const Frame&, const SecurityOrigin&, const Vector<uint8_t>&, const PublicKeyCredentialCreationOptions&, RequestCompletionHandler&&) = 0;
    58     virtual void getAssertion(const Frame&, const SecurityOrigin&, const Vector<uint8_t>&, const PublicKeyCredentialRequestOptions&, MediationRequirement, RequestCompletionHandler&&) = 0;
     64    virtual void getAssertion(const Frame&, const SecurityOrigin&, const Vector<uint8_t>&, const PublicKeyCredentialRequestOptions&, MediationRequirement, const ScopeAndCrossOriginParent&, RequestCompletionHandler&&) = 0;
    5965    virtual void isConditionalMediationAvailable(QueryCompletionHandler&&) = 0;
    6066    virtual void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&) = 0;
  • trunk/Source/WebKit/ChangeLog

    r291017 r291018  
     12022-03-08  J Pascoe  <j_pascoe@apple.com>
     2
     3        [WebAuthn] Using WebAuthn within cross-origin iframe elements
     4        https://bugs.webkit.org/show_bug.cgi?id=222240
     5        rdar://problem/74830748
     6
     7        Reviewed by Brent Fulgham.
     8
     9        This patch relaxes the requirement to perform a Web Authentication assertion
     10        inside an i-frame with the "publickey-credentials-get" feature policy from
     11        'same-site' to 'cross-origin with consent'.
     12
     13        There is an additional requirement that there is only a single cross-origin
     14        parent to present to the user in the prompt. If we can't display the updated
     15        prompt, then cross-origin assertions are not allowed.
     16
     17        * Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h:
     18        * UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm:
     19        (WebKit::configureAssertionOptions):
     20        (WebKit::configurationAssertionRequestContext):
     21        (WebKit::WebAuthenticatorCoordinatorProxy::contextForRequest):
     22        * UIProcess/WebAuthentication/WebAuthenticationRequestData.h:
     23        * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp:
     24        (WebKit::WebAuthenticatorCoordinatorProxy::makeCredential):
     25        (WebKit::WebAuthenticatorCoordinatorProxy::getAssertion):
     26        (WebKit::WebAuthenticatorCoordinatorProxy::handleRequest):
     27        * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h:
     28        * UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in:
     29        * WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp:
     30        (WebKit::WebAuthenticatorCoordinator::getAssertion):
     31        * WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h:
     32
    1332022-03-08  Chris Dumez  <cdumez@apple.com>
    234
  • trunk/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h

    r290893 r291018  
    168168@property (nonatomic, nullable, readonly, copy) NSArray<ASCPublicKeyCredentialDescriptor *> *allowedCredentials;
    169169
     170@property (nonatomic, nullable, copy) NSString *destinationSiteForCrossSiteAssertion;
     171
    170172@end
    171173
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm

    r290381 r291018  
    823823        });
    824824    };
    825     _panel->handleRequest({ WTFMove(hash), [_WKWebAuthenticationPanel convertToCoreCreationOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt }, WTFMove(callback));
     825    _panel->handleRequest({ WTFMove(hash), [_WKWebAuthenticationPanel convertToCoreCreationOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt, std::nullopt }, WTFMove(callback));
    826826#endif
    827827}
     
    837837        });
    838838    };
    839     _panel->handleRequest({ vectorFromNSData(clientDataHash), [_WKWebAuthenticationPanel convertToCoreCreationOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt }, WTFMove(callback));
     839    _panel->handleRequest({ vectorFromNSData(clientDataHash), [_WKWebAuthenticationPanel convertToCoreCreationOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt, std::nullopt }, WTFMove(callback));
    840840#endif
    841841}
     
    887887        });
    888888    };
    889     _panel->handleRequest({ WTFMove(hash), [_WKWebAuthenticationPanel convertToCoreRequestOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt }, WTFMove(callback));
     889    _panel->handleRequest({ WTFMove(hash), [_WKWebAuthenticationPanel convertToCoreRequestOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt, std::nullopt }, WTFMove(callback));
    890890#endif
    891891}
     
    901901        });
    902902    };
    903     _panel->handleRequest({ vectorFromNSData(clientDataHash), [_WKWebAuthenticationPanel convertToCoreRequestOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt }, WTFMove(callback));
     903    _panel->handleRequest({ vectorFromNSData(clientDataHash), [_WKWebAuthenticationPanel convertToCoreRequestOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, true, String(), nullptr, std::nullopt, std::nullopt }, WTFMove(callback));
    904904#endif
    905905}
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm

    r290893 r291018  
    173173}
    174174
    175 static RetainPtr<ASCCredentialRequestContext> configureRegistrationRequestContext(const PublicKeyCredentialCreationOptions& options, Vector<uint8_t> hash)
     175static inline void setGlobalFrameIDForContext(RetainPtr<ASCCredentialRequestContext> requestContext, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID)
     176{
     177    if (globalFrameID && [requestContext respondsToSelector:@selector(setGlobalFrameID:)]) {
     178        auto ascGlobalFrameID = adoptNS([allocASCGlobalFrameIdentifierInstance() init]);
     179        ascGlobalFrameID.get().webFrameID = [NSNumber numberWithUnsignedLong:globalFrameID->frameID.toUInt64()];
     180        ascGlobalFrameID.get().webPageID = [NSNumber numberWithUnsignedLong:globalFrameID->pageID.toUInt64()];
     181        requestContext.get().globalFrameID = ascGlobalFrameID.get();
     182    }
     183}
     184
     185static RetainPtr<ASCCredentialRequestContext> configureRegistrationRequestContext(const PublicKeyCredentialCreationOptions& options, const Vector<uint8_t>& hash, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID)
    176186{
    177187    ASCCredentialRequestTypes requestTypes = ASCCredentialRequestTypePlatformPublicKeyRegistration | ASCCredentialRequestTypeSecurityKeyPublicKeyRegistration;
     
    194204    auto requestContext = adoptNS([allocASCCredentialRequestContextInstance() initWithRequestTypes:requestTypes]);
    195205    [requestContext setRelyingPartyIdentifier:options.rp.id];
     206    setGlobalFrameIDForContext(requestContext, globalFrameID);
    196207
    197208    auto credentialCreationOptions = adoptNS([allocASCPublicKeyCredentialCreationOptionsInstance() init]);
     
    237248}
    238249
    239 static RetainPtr<ASCCredentialRequestContext> configurationAssertionRequestContext(const PublicKeyCredentialRequestOptions& options, Vector<uint8_t> hash, std::optional<WebCore::MediationRequirement> mediation, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID)
     250static inline RetainPtr<ASCPublicKeyCredentialAssertionOptions> configureAssertionOptions(const PublicKeyCredentialRequestOptions& options, const Vector<uint8_t>& hash, ASCPublicKeyCredentialKind kind, const std::optional<SecurityOriginData>& parentOrigin, RetainPtr<NSMutableArray<ASCPublicKeyCredentialDescriptor *>> allowedCredentials, RetainPtr<NSString> userVerification)
     251{
     252    auto assertionOptions = adoptNS(allocASCPublicKeyCredentialAssertionOptionsInstance());
     253    if ([assertionOptions respondsToSelector:@selector(initWithKind:relyingPartyIdentifier:clientDataHash:userVerificationPreference:allowedCredentials:)]) {
     254        auto nsHash = toNSData(hash);
     255        [assertionOptions initWithKind:ASCPublicKeyCredentialKindPlatform relyingPartyIdentifier:options.rpId clientDataHash:nsHash.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
     256    } else {
     257        auto challenge = WebCore::toNSData(options.challenge);
     258        [assertionOptions initWithKind:ASCPublicKeyCredentialKindPlatform relyingPartyIdentifier:options.rpId challenge:challenge.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
     259    }
     260    if (options.extensions && [assertionOptions respondsToSelector:@selector(setExtensions:)])
     261        [assertionOptions setExtensions:toASCExtensions(*options.extensions).get()];
     262    if (parentOrigin && [assertionOptions respondsToSelector:@selector(setDestinationSiteForCrossSiteAssertion:)])
     263        assertionOptions.get().destinationSiteForCrossSiteAssertion = parentOrigin->toString();
     264    else if (parentOrigin && ![assertionOptions respondsToSelector:@selector(setDestinationSiteForCrossSiteAssertion:)])
     265        return nil;
     266    return assertionOptions;
     267}
     268
     269static RetainPtr<ASCCredentialRequestContext> configurationAssertionRequestContext(const PublicKeyCredentialRequestOptions& options, const Vector<uint8_t>& hash, std::optional<WebCore::MediationRequirement> mediation, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID, std::optional<WebCore::SecurityOriginData>& parentOrigin)
    240270{
    241271    ASCCredentialRequestTypes requestTypes = ASCCredentialRequestTypePlatformPublicKeyAssertion | ASCCredentialRequestTypeSecurityKeyPublicKeyAssertion;
     
    263293    if (mediation == MediationRequirement::Conditional && [requestContext respondsToSelector:@selector(setRequestStyle:)])
    264294        requestContext.get().requestStyle = ASCredentialRequestStyleAutoFill;
    265     if (globalFrameID && [requestContext respondsToSelector:@selector(setGlobalFrameID:)]) {
    266         auto ascGlobalFrameID = adoptNS([allocASCGlobalFrameIdentifierInstance() init]);
    267         ascGlobalFrameID.get().webFrameID = [NSNumber numberWithUnsignedLong:globalFrameID->frameID.toUInt64()];
    268         ascGlobalFrameID.get().webPageID = [NSNumber numberWithUnsignedLong:globalFrameID->pageID.toUInt64()];
    269         requestContext.get().globalFrameID = ascGlobalFrameID.get();
    270     }
     295    setGlobalFrameIDForContext(requestContext, globalFrameID);
    271296
    272297    if (requestTypes & ASCCredentialRequestTypePlatformPublicKeyAssertion) {
    273         auto assertionOptions = adoptNS(allocASCPublicKeyCredentialAssertionOptionsInstance());
    274         if ([assertionOptions respondsToSelector:@selector(initWithKind:relyingPartyIdentifier:clientDataHash:userVerificationPreference:allowedCredentials:)]) {
    275             auto nsHash = toNSData(hash);
    276             [assertionOptions initWithKind:ASCPublicKeyCredentialKindPlatform relyingPartyIdentifier:options.rpId clientDataHash:nsHash.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
    277         } else {
    278             auto challenge = WebCore::toNSData(options.challenge);
    279             [assertionOptions initWithKind:ASCPublicKeyCredentialKindPlatform relyingPartyIdentifier:options.rpId challenge:challenge.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
    280         }
    281         if (options.extensions && [assertionOptions respondsToSelector:@selector(setExtensions:)])
    282             [assertionOptions setExtensions:toASCExtensions(*options.extensions).get()];
    283 
     298        auto assertionOptions = configureAssertionOptions(options, hash, ASCPublicKeyCredentialKindPlatform, parentOrigin, allowedCredentials, userVerification);
     299        if (!assertionOptions)
     300            return nil;
    284301        [requestContext setPlatformKeyCredentialAssertionOptions:assertionOptions.get()];
    285302    }
    286303
    287304    if (requestTypes & ASCCredentialRequestTypeSecurityKeyPublicKeyAssertion) {
    288         auto assertionOptions = adoptNS(allocASCPublicKeyCredentialAssertionOptionsInstance());
    289         if ([assertionOptions respondsToSelector:@selector(initWithKind:relyingPartyIdentifier:clientDataHash:userVerificationPreference:allowedCredentials:)]) {
    290             auto nsHash = toNSData(hash);
    291             [assertionOptions initWithKind:ASCPublicKeyCredentialKindSecurityKey relyingPartyIdentifier:options.rpId clientDataHash:nsHash.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
    292         } else {
    293             auto challenge = WebCore::toNSData(options.challenge);
    294             [assertionOptions initWithKind:ASCPublicKeyCredentialKindSecurityKey relyingPartyIdentifier:options.rpId challenge:challenge.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
    295         }
    296         if (options.extensions && [assertionOptions respondsToSelector:@selector(setExtensions:)])
    297             [assertionOptions setExtensions:toASCExtensions(*options.extensions).get()];
    298 
     305        auto assertionOptions = configureAssertionOptions(options, hash, ASCPublicKeyCredentialKindSecurityKey, parentOrigin, allowedCredentials, userVerification);
     306        if (!assertionOptions)
     307            return nil;
    299308        [requestContext setSecurityKeyCredentialAssertionOptions:assertionOptions.get()];
    300309    }
     
    307316    RetainPtr<ASCCredentialRequestContext> result;
    308317    WTF::switchOn(requestData.options, [&](const PublicKeyCredentialCreationOptions& options) {
    309         result = configureRegistrationRequestContext(options, requestData.hash);
     318        result = configureRegistrationRequestContext(options, requestData.hash, requestData.globalFrameID);
    310319    }, [&](const PublicKeyCredentialRequestOptions& options) {
    311         result = configurationAssertionRequestContext(options, requestData.hash, requestData.mediation, requestData.globalFrameID);
     320        result = configurationAssertionRequestContext(options, requestData.hash, requestData.mediation, requestData.globalFrameID, requestData.parentOrigin);
    312321    });
    313322    return result;
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h

    r290893 r291018  
    4040#include <wtf/WeakPtr.h>
    4141
     42namespace WebCore {
     43struct SecurityOriginData;
     44}
     45
    4246namespace WebKit {
    4347
     
    5963    WeakPtr<API::WebAuthenticationPanel> weakPanel;
    6064    std::optional<WebCore::MediationRequirement> mediation;
     65    std::optional<WebCore::SecurityOriginData> parentOrigin;
    6166};
    6267
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp

    r290184 r291018  
    5959void WebAuthenticatorCoordinatorProxy::makeCredential(FrameIdentifier frameId, FrameInfoData&& frameInfo, Vector<uint8_t>&& hash, PublicKeyCredentialCreationOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
    6060{
    61     handleRequest({ WTFMove(hash), WTFMove(options), m_webPageProxy, WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String(), nullptr, std::nullopt }, WTFMove(handler));
     61    handleRequest({ WTFMove(hash), WTFMove(options), m_webPageProxy, WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String(), nullptr, std::nullopt, std::nullopt }, WTFMove(handler));
    6262}
    6363
    64 void WebAuthenticatorCoordinatorProxy::getAssertion(FrameIdentifier frameId, FrameInfoData&& frameInfo, Vector<uint8_t>&& hash, PublicKeyCredentialRequestOptions&& options, MediationRequirement mediation, bool processingUserGesture, RequestCompletionHandler&& handler)
     64void WebAuthenticatorCoordinatorProxy::getAssertion(FrameIdentifier frameId, FrameInfoData&& frameInfo, Vector<uint8_t>&& hash, PublicKeyCredentialRequestOptions&& options, MediationRequirement mediation, std::optional<WebCore::SecurityOriginData> parentOrigin, bool processingUserGesture, RequestCompletionHandler&& handler)
    6565{
    66     handleRequest({ WTFMove(hash), WTFMove(options), m_webPageProxy, WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String(), nullptr, mediation }, WTFMove(handler));
     66    handleRequest({ WTFMove(hash), WTFMove(options), m_webPageProxy, WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String(), nullptr, mediation, parentOrigin }, WTFMove(handler));
    6767}
    6868
     
    7575        if (result) {
    7676#if HAVE(UNIFIED_ASC_AUTH_UI)
    77                 if (!authenticatorManager.isMock() && !authenticatorManager.isVirtual()) {
    78                     auto context = contextForRequest(WTFMove(data));
    79                     // performRequest calls out to ASCAgent which will then call [_WKWebAuthenticationPanel makeCredential/getAssertionWithChallenge]
    80                     // which calls authenticatorManager.handleRequest(..)
    81                     performRequest(context, WTFMove(handler));
     77            if (!authenticatorManager.isMock() && !authenticatorManager.isVirtual()) {
     78                auto context = contextForRequest(WTFMove(data));
     79                if (context.get() == nullptr) {
     80                    handler({ }, (AuthenticatorAttachment)0, ExceptionData { NotAllowedError, "The origin of the document is not the same as its ancestors."_s });
    8281                    return;
    8382                }
     83                // performRequest calls out to ASCAgent which will then call [_WKWebAuthenticationPanel makeCredential/getAssertionWithChallenge]
     84                // which calls authenticatorManager.handleRequest(..)
     85                performRequest(context, WTFMove(handler));
     86                return;
     87            }
     88#else
     89            if (data.parentOrigin && !authenticatorManager.isMock() && !authenticatorManager.isVirtual()) {
     90                handler({ }, (AuthenticatorAttachment)0, ExceptionData { NotAllowedError, "The origin of the document is not the same as its ancestors."_s });
     91                return;
     92            }
    8493#endif // HAVE(UNIFIED_ASC_AUTH_UI)
    8594
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h

    r290317 r291018  
    7272    // Receivers.
    7373    void makeCredential(WebCore::FrameIdentifier, FrameInfoData&&, Vector<uint8_t>&& hash, WebCore::PublicKeyCredentialCreationOptions&&, bool processingUserGesture, RequestCompletionHandler&&);
    74     void getAssertion(WebCore::FrameIdentifier, FrameInfoData&&, Vector<uint8_t>&& hash, WebCore::PublicKeyCredentialRequestOptions&&, WebCore::CredentialRequestOptions::MediationRequirement, bool processingUserGesture, RequestCompletionHandler&&);
     74    void getAssertion(WebCore::FrameIdentifier, FrameInfoData&&, Vector<uint8_t>&& hash, WebCore::PublicKeyCredentialRequestOptions&&, WebCore::CredentialRequestOptions::MediationRequirement, std::optional<WebCore::SecurityOriginData>, bool processingUserGesture, RequestCompletionHandler&&);
    7575    void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&);
    7676    void isConditionalMediationAvailable(QueryCompletionHandler&&);
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in

    r290903 r291018  
    2828
    2929    MakeCredential(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, Vector<uint8_t> hash, struct WebCore::PublicKeyCredentialCreationOptions options, bool processingUserGesture) -> (struct WebCore::AuthenticatorResponseData data, enum:int WebCore::AuthenticatorAttachment attachment, struct WebCore::ExceptionData exception)
    30     GetAssertion(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, Vector<uint8_t> hash, struct WebCore::PublicKeyCredentialRequestOptions options, enum:uint8_t WebCore::CredentialRequestOptions::MediationRequirement mediation, bool processingUserGesture) -> (struct WebCore::AuthenticatorResponseData data, enum:int WebCore::AuthenticatorAttachment attachment, struct WebCore::ExceptionData exception)
     30    GetAssertion(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, Vector<uint8_t> hash, struct WebCore::PublicKeyCredentialRequestOptions options, enum:uint8_t WebCore::CredentialRequestOptions::MediationRequirement mediation, std::optional<WebCore::SecurityOriginData> parentOrigin, bool processingUserGesture) -> (struct WebCore::AuthenticatorResponseData data, enum:int WebCore::AuthenticatorAttachment attachment, struct WebCore::ExceptionData exception)
    3131    isConditionalMediationAvailable() -> (bool result)
    3232    IsUserVerifyingPlatformAuthenticatorAvailable() -> (bool result)
  • trunk/Source/WebKit/WebAuthnProcess/WebAuthnConnectionToWebProcess.cpp

    r290184 r291018  
    9797void WebAuthnConnectionToWebProcess::makeCredential(Vector<uint8_t>&& hash, PublicKeyCredentialCreationOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
    9898{
    99     handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, processingUserGesture, String(), nullptr, std::nullopt }, WTFMove(handler));
     99    handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, processingUserGesture, String(), nullptr, std::nullopt, std::nullopt }, WTFMove(handler));
    100100}
    101101
    102102void WebAuthnConnectionToWebProcess::getAssertion(Vector<uint8_t>&& hash, PublicKeyCredentialRequestOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
    103103{
    104     handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, processingUserGesture, String(), nullptr, std::nullopt }, WTFMove(handler));
     104    handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, std::nullopt, { }, processingUserGesture, String(), nullptr, std::nullopt, std::nullopt }, WTFMove(handler));
    105105}
    106106
  • trunk/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp

    r290755 r291018  
    4747#include <WebCore/SecurityOrigin.h>
    4848#include <WebCore/UserGestureIndicator.h>
     49#include <WebCore/WebAuthenticationConstants.h>
    4950
    5051#undef WEBAUTHN_RELEASE_LOG
     
    9495}
    9596
    96 void WebAuthenticatorCoordinator::getAssertion(const Frame& frame, const SecurityOrigin&, const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions& options, MediationRequirement mediation, RequestCompletionHandler&& handler)
     97void WebAuthenticatorCoordinator::getAssertion(const Frame& frame, const SecurityOrigin&, const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions& options, MediationRequirement mediation, const ScopeAndCrossOriginParent& scopeAndCrossOriginParent, RequestCompletionHandler&& handler)
    9798{
    9899    auto* webFrame = WebFrame::fromCoreFrame(frame);
     
    107108#endif
    108109    if (!useWebAuthnProcess) {
    109         m_webPage.sendWithAsyncReply(Messages::WebAuthenticatorCoordinatorProxy::GetAssertion(webFrame->frameID(), webFrame->info(), hash, options, mediation, isProcessingUserGesture), WTFMove(handler));
     110        m_webPage.sendWithAsyncReply(Messages::WebAuthenticatorCoordinatorProxy::GetAssertion(webFrame->frameID(), webFrame->info(), hash, options, mediation, scopeAndCrossOriginParent.second, isProcessingUserGesture), WTFMove(handler));
     111        return;
     112    }
     113    if (scopeAndCrossOriginParent.first == WebAuthn::Scope::CrossOrigin) {
     114        handler({ }, (AuthenticatorAttachment)0, ExceptionData { NotAllowedError, "The origin of the document is not the same as its ancestors."_s });
    110115        return;
    111116    }
  • trunk/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h

    r290184 r291018  
    4242    // WebCore::AuthenticatorCoordinatorClient
    4343    void makeCredential(const WebCore::Frame&, const WebCore::SecurityOrigin&, const Vector<uint8_t>&, const WebCore::PublicKeyCredentialCreationOptions&, WebCore::RequestCompletionHandler&&) final;
    44     void getAssertion(const WebCore::Frame&, const WebCore::SecurityOrigin&, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&, WebCore::MediationRequirement, WebCore::RequestCompletionHandler&&) final;
     44    void getAssertion(const WebCore::Frame&, const WebCore::SecurityOrigin&, const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&, WebCore::MediationRequirement, const std::pair<WebAuthn::Scope, std::optional<WebCore::SecurityOriginData>>&, WebCore::RequestCompletionHandler&&) final;
    4545    void isConditionalMediationAvailable(WebCore::QueryCompletionHandler&&) final;
    4646    void isUserVerifyingPlatformAuthenticatorAvailable(WebCore::QueryCompletionHandler&&) final;
Note: See TracChangeset for help on using the changeset viewer.