Changeset 257877 in webkit


Ignore:
Timestamp:
Mar 4, 2020 1:42:39 PM (4 years ago)
Author:
jiewen_tan@apple.com
Message:

[WebAuthn] Implement -[_WKWebAuthenticationPanelDelegate panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:] SPI
https://bugs.webkit.org/show_bug.cgi?id=208533
<rdar://problem/60010184>

Reviewed by Alex Christensen.

Source/WebCore:

Covered by new tests within existing test files.

  • en.lproj/Localizable.strings:
  • platform/LocalizedStrings.cpp:

(WebCore::touchIDPromptTitle):
(WebCore::biometricFallbackPromptTitle):

  • platform/LocalizedStrings.h:

Adds localized strings to support the customized LocalAuthentication dialog.

Source/WebKit:

This patch implements the above SPI to replace -[_WKWebAuthenticationPanelDelegate panel:verifyUserWithAccessControl:completionHandler:].
The original SPI is designed on the premise that Safari is going to highly customize the LocalAuthentication UI, and that is not happening
anymore. Therefore, WebKit takes back the invocation of LocalAuthentication and offer a new SPI to tell clients when WebKit is about to
show LocalAuthentication UI. Clients then have the trigger to pull at their pleasure.

This patch implements all plumbings to replace the SPI. Besides that, this patch also:
1) enhances the LocalConnection::verifyUser with a slightly customized LocalAuthentication dialog;
2) adds the SPI used above into the SPI header;
3) makes _WKWebAuthenticationPanelDelegate.transports as a NSSet instead of a NSArray;
4) lets LocalService::isAvailable return false if Apple attestation is not available.

  • Platform/spi/Cocoa/LocalAuthenticationSPI.h:
  • UIProcess/API/APIWebAuthenticationPanelClient.h:

(API::WebAuthenticationPanelClient::decidePolicyForLocalAuthenticator const):
(API::WebAuthenticationPanelClient::verifyUser const): Deleted.

  • UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h:
  • UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:

(-[_WKWebAuthenticationPanel transports]):

  • UIProcess/WebAuthentication/Authenticator.h:
  • UIProcess/WebAuthentication/AuthenticatorManager.cpp:

(WebKit::AuthenticatorManager::decidePolicyForLocalAuthenticator):
(WebKit::AuthenticatorManager::verifyUser): Deleted.

  • UIProcess/WebAuthentication/AuthenticatorManager.h:
  • UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.h:
  • UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:

(WebKit::LocalAuthenticator::makeCredential):
(WebKit::LocalAuthenticator::continueMakeCredentialAfterDecidePolicy):
(WebKit::LocalAuthenticator::continueMakeCredentialAfterUserVerification):
(WebKit::LocalAuthenticator::continueMakeCredentialAfterAttested):
(WebKit::LocalAuthenticator::getAssertion):
(WebKit::LocalAuthenticator::continueGetAssertionAfterResponseSelected):
(WebKit::LocalAuthenticator::continueGetAssertionAfterUserVerification):
(WebKit::LocalAuthenticator::continueMakeCredentialAfterUserConsented): Deleted.
(WebKit::LocalAuthenticator::continueGetAssertionAfterUserConsented): Deleted.

  • UIProcess/WebAuthentication/Cocoa/LocalConnection.h:
  • UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:

(WebKit::LocalConnection::verifyUser const):
(WebKit::LocalConnection::isUnlocked const): Deleted.

  • UIProcess/WebAuthentication/Cocoa/LocalService.mm:

(WebKit::LocalService::isAvailable):

  • UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h:
  • UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:

(WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient):
(WebKit::localAuthenticatorPolicy):
(WebKit::WebAuthenticationPanelClient::decidePolicyForLocalAuthenticator const):
(WebKit::WebAuthenticationPanelClient::verifyUser const): Deleted.

  • UIProcess/WebAuthentication/Mock/MockLocalConnection.h:
  • UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:

(WebKit::MockLocalConnection::verifyUser const):
(WebKit::MockLocalConnection::isUnlocked const): Deleted.

  • UIProcess/WebAuthentication/WebAuthenticationFlags.h:

Tools:

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:

(-[TestWebAuthenticationPanelDelegate panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:]):
(TestWebKitAPI::TEST):
(-[TestWebAuthenticationPanelDelegate panel:verifyUserWithAccessControl:completionHandler:]): Deleted.

  • TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-la.html: Removed.
Location:
trunk
Files:
1 deleted
28 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html

    r257085 r257877  
    9999                }
    100100            };
    101             return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Couldn't get user consent.");
     101            return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Couldn't verify user.");
    102102        }, "PublicKeyCredential's [[create]] without user consent in a mock local authenticator.");
    103103
  • trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html

    r250940 r257877  
    5656            if (window.testRunner)
    5757                testRunner.addTestKeyToKeychain(privateKeyBase64, testRpId, userhandleBase64);
    58             return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Couldn't get user consent.").then(() => {
     58            return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Couldn't verify user.").then(() => {
    5959                if (window.testRunner)
    6060                    testRunner.cleanUpKeychain(testRpId, userhandleBase64);
  • trunk/Source/WebCore/ChangeLog

    r257870 r257877  
     12020-03-03  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Implement -[_WKWebAuthenticationPanelDelegate panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:] SPI
     4        https://bugs.webkit.org/show_bug.cgi?id=208533
     5        <rdar://problem/60010184>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Covered by new tests within existing test files.
     10
     11        * en.lproj/Localizable.strings:
     12        * platform/LocalizedStrings.cpp:
     13        (WebCore::touchIDPromptTitle):
     14        (WebCore::biometricFallbackPromptTitle):
     15        * platform/LocalizedStrings.h:
     16        Adds localized strings to support the customized LocalAuthentication dialog.
     17
    1182020-03-04  Antoine Quint  <graouts@apple.com>
    219
  • trunk/Source/WebCore/en.lproj/Localizable.strings

    r256086 r257877  
    311311"Enter Full Screen" = "Enter Full Screen";
    312312
     313/* Use passcode as a fallback to sign into this website */
     314"Enter passcode to sign into this website." = "Enter passcode to sign into this website.";
     315
    313316/* menu item */
    314317"Enter Picture in Picture" = "Enter Picture in Picture";
     
    878881"To view this page, you must log in to this area on %@:" = "To view this page, you must log in to this area on %@:";
    879882
     883/* Use Touch ID to sign into this website */
     884"Touch ID to sign into this website." = "Touch ID to sign into this website.";
     885
    880886/* Transformations context sub-menu item */
    881887"Transformations" = "Transformations";
  • trunk/Source/WebCore/platform/LocalizedStrings.cpp

    r254238 r257877  
    12081208#endif
    12091209
     1210#if ENABLE(WEB_AUTHN)
     1211String touchIDPromptTitle()
     1212{
     1213    return WEB_UI_STRING("Touch ID to sign into this website.", "Use Touch ID to sign into this website");
     1214}
     1215
     1216String biometricFallbackPromptTitle()
     1217{
     1218    return WEB_UI_STRING("Enter passcode to sign into this website.", "Use passcode as a fallback to sign into this website");
     1219}
     1220#endif
     1221
    12101222} // namespace WebCore
  • trunk/Source/WebCore/platform/LocalizedStrings.h

    r252181 r257877  
    340340#endif
    341341
     342#if ENABLE(WEB_AUTHN)
     343    WEBCORE_EXPORT String touchIDPromptTitle();
     344    WEBCORE_EXPORT String biometricFallbackPromptTitle();
     345#endif
     346
    342347#if USE(GLIB) && defined(GETTEXT_PACKAGE)
    343348#define WEB_UI_STRING(string, description) WebCore::localizedString(_(string))
  • trunk/Source/WebKit/ChangeLog

    r257876 r257877  
     12020-03-03  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Implement -[_WKWebAuthenticationPanelDelegate panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:] SPI
     4        https://bugs.webkit.org/show_bug.cgi?id=208533
     5        <rdar://problem/60010184>
     6
     7        Reviewed by Alex Christensen.
     8
     9        This patch implements the above SPI to replace -[_WKWebAuthenticationPanelDelegate panel:verifyUserWithAccessControl:completionHandler:].
     10        The original SPI is designed on the premise that Safari is going to highly customize the LocalAuthentication UI, and that is not happening
     11        anymore. Therefore, WebKit takes back the invocation of LocalAuthentication and offer a new SPI to tell clients when WebKit is about to
     12        show LocalAuthentication UI. Clients then have the trigger to pull at their pleasure.
     13
     14        This patch implements all plumbings to replace the SPI. Besides that, this patch also:
     15        1) enhances the LocalConnection::verifyUser with a slightly customized LocalAuthentication dialog;
     16        2) adds the SPI used above into the SPI header;
     17        3) makes _WKWebAuthenticationPanelDelegate.transports as a NSSet instead of a NSArray;
     18        4) lets LocalService::isAvailable return false if Apple attestation is not available.
     19
     20        * Platform/spi/Cocoa/LocalAuthenticationSPI.h:
     21        * UIProcess/API/APIWebAuthenticationPanelClient.h:
     22        (API::WebAuthenticationPanelClient::decidePolicyForLocalAuthenticator const):
     23        (API::WebAuthenticationPanelClient::verifyUser const): Deleted.
     24        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h:
     25        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
     26        (-[_WKWebAuthenticationPanel transports]):
     27        * UIProcess/WebAuthentication/Authenticator.h:
     28        * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
     29        (WebKit::AuthenticatorManager::decidePolicyForLocalAuthenticator):
     30        (WebKit::AuthenticatorManager::verifyUser): Deleted.
     31        * UIProcess/WebAuthentication/AuthenticatorManager.h:
     32        * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.h:
     33        * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
     34        (WebKit::LocalAuthenticator::makeCredential):
     35        (WebKit::LocalAuthenticator::continueMakeCredentialAfterDecidePolicy):
     36        (WebKit::LocalAuthenticator::continueMakeCredentialAfterUserVerification):
     37        (WebKit::LocalAuthenticator::continueMakeCredentialAfterAttested):
     38        (WebKit::LocalAuthenticator::getAssertion):
     39        (WebKit::LocalAuthenticator::continueGetAssertionAfterResponseSelected):
     40        (WebKit::LocalAuthenticator::continueGetAssertionAfterUserVerification):
     41        (WebKit::LocalAuthenticator::continueMakeCredentialAfterUserConsented): Deleted.
     42        (WebKit::LocalAuthenticator::continueGetAssertionAfterUserConsented): Deleted.
     43        * UIProcess/WebAuthentication/Cocoa/LocalConnection.h:
     44        * UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:
     45        (WebKit::LocalConnection::verifyUser const):
     46        (WebKit::LocalConnection::isUnlocked const): Deleted.
     47        * UIProcess/WebAuthentication/Cocoa/LocalService.mm:
     48        (WebKit::LocalService::isAvailable):
     49        * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h:
     50        * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:
     51        (WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient):
     52        (WebKit::localAuthenticatorPolicy):
     53        (WebKit::WebAuthenticationPanelClient::decidePolicyForLocalAuthenticator const):
     54        (WebKit::WebAuthenticationPanelClient::verifyUser const): Deleted.
     55        * UIProcess/WebAuthentication/Mock/MockLocalConnection.h:
     56        * UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
     57        (WebKit::MockLocalConnection::verifyUser const):
     58        (WebKit::MockLocalConnection::isUnlocked const): Deleted.
     59        * UIProcess/WebAuthentication/WebAuthenticationFlags.h:
     60
    1612020-03-04  Alex Christensen  <achristensen@webkit.org>
    262
  • trunk/Source/WebKit/Platform/spi/Cocoa/LocalAuthenticationSPI.h

    r257371 r257877  
    3535
    3636typedef NS_ENUM(NSInteger, LAOption) {
    37     LAOptionNotInteractive,
     37    LAOptionAuthenticationTitle,
     38    LAOptionPasscodeTitle,
    3839};
    3940
    4041@interface LAContext(Private) <NSSecureCoding>
    4142
    42 - (NSDictionary *)evaluatePolicy:(LAPolicy)policy options:(NSDictionary *)options error:(NSError **)error;
     43- (void)evaluateAccessControl:(SecAccessControlRef)accessControl operation:(LAAccessControlOperation)operation options:(NSDictionary *)options reply:(void(^)(NSDictionary *result, NSError *error))reply;
    4344
    4445@end
  • trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h

    r257269 r257877  
    2828#if ENABLE(WEB_AUTHN)
    2929
     30#include "WebAuthenticationFlags.h"
    3031#include <wtf/CompletionHandler.h>
    3132#include <wtf/HashSet.h>
     
    3839namespace WebCore {
    3940class AuthenticatorAssertionResponse;
    40 }
    41 
    42 namespace WebKit {
    43 enum class WebAuthenticationStatus : uint8_t;
    44 enum class WebAuthenticationResult : bool;
    4541}
    4642
     
    5652    virtual void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&& completionHandler) const { completionHandler(emptyString()); }
    5753    virtual void selectAssertionResponse(Vector<Ref<WebCore::AuthenticatorAssertionResponse>>&& responses, CompletionHandler<void(const WebCore::AuthenticatorAssertionResponse&)>&& completionHandler) const { ASSERT(!responses.isEmpty()); completionHandler(responses[0]); }
    58     virtual void verifyUser(SecAccessControlRef, CompletionHandler<void(LAContext *)>&& completionHandler) const { completionHandler(nullptr); }
     54    virtual void decidePolicyForLocalAuthenticator(CompletionHandler<void(WebKit::LocalAuthenticatorPolicy)>&& completionHandler) const { completionHandler(WebKit::LocalAuthenticatorPolicy::Disallow); }
    5955};
    6056
  • trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp

    r257571 r257877  
    4848#include "APISessionState.h"
    4949#include "APIUIClient.h"
     50#include "APIWebAuthenticationPanel.h"
     51#include "APIWebAuthenticationPanelClient.h"
    5052#include "APIWebsitePolicies.h"
    5153#include "APIWindowFeatures.h"
     
    20802082#if ENABLE(WEB_AUTHN)
    20812083        // The current method is specialized for WebKitTestRunner.
    2082         void runWebAuthenticationPanel(WebPageProxy&, API::WebAuthenticationPanel&, WebFrameProxy&, FrameInfoData&&, CompletionHandler<void(WebKit::WebAuthenticationPanelResult)>&& completionHandler) final
    2083         {
     2084        void runWebAuthenticationPanel(WebPageProxy&, API::WebAuthenticationPanel& panel, WebFrameProxy&, FrameInfoData&&, CompletionHandler<void(WebKit::WebAuthenticationPanelResult)>&& completionHandler) final
     2085        {
     2086            class PanelClient : public API::WebAuthenticationPanelClient {
     2087            public:
     2088                void decidePolicyForLocalAuthenticator(CompletionHandler<void(WebKit::LocalAuthenticatorPolicy)>&& completionHandler) const { completionHandler(WebKit::LocalAuthenticatorPolicy::Allow); }
     2089            };
     2090
    20842091            if (!m_client.runWebAuthenticationPanel) {
    20852092                completionHandler(WebKit::WebAuthenticationPanelResult::Unavailable);
    20862093                return;
    20872094            }
     2095
     2096            panel.setClient(WTF::makeUniqueRef<PanelClient>());
    20882097            completionHandler(WebKit::WebAuthenticationPanelResult::Presented);
    20892098        }
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h

    r257269 r257877  
    6969} WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    7070
     71typedef NS_ENUM(NSInteger, _WKLocalAuthenticatorPolicy) {
     72    _WKLocalAuthenticatorPolicyAllow,
     73    _WKLocalAuthenticatorPolicyDisallow,
     74} WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     75
    7176@protocol _WKWebAuthenticationPanelDelegate <NSObject>
    7277
     
    7782- (void)panel:(_WKWebAuthenticationPanel *)panel requestPINWithRemainingRetries:(NSUInteger)retries completionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    7883- (void)panel:(_WKWebAuthenticationPanel *)panel selectAssertionResponse:(NSArray < _WKWebAuthenticationAssertionResponse *> *)responses completionHandler:(void (^)(_WKWebAuthenticationAssertionResponse *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    79 - (void)panel:(_WKWebAuthenticationPanel *)panel verifyUserWithAccessControl:(SecAccessControlRef)accessControl completionHandler:(void (^)(LAContext *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     84- (void)panel:(_WKWebAuthenticationPanel *)panel decidePolicyForLocalAuthenticatorWithCompletionHandler:(void (^)(_WKLocalAuthenticatorPolicy policy))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    8085
    8186@end
     
    8691@property (nullable, nonatomic, weak) id <_WKWebAuthenticationPanelDelegate> delegate;
    8792@property (nonatomic, readonly, copy) NSString *relyingPartyID;
    88 @property (nonatomic, readonly, copy) NSArray *transports;
     93@property (nonatomic, readonly, copy) NSSet *transports;
    8994@property (nonatomic, readonly) _WKWebAuthenticationType type;
    9095
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm

    r257269 r257877  
    3434#if ENABLE(WEB_AUTHN)
    3535    WeakPtr<WebKit::WebAuthenticationPanelClient> _client;
    36     RetainPtr<NSMutableArray> _transports;
     36    RetainPtr<NSMutableSet> _transports;
    3737#endif
    3838}
     
    8282}
    8383
    84 - (NSArray *)transports
     84- (NSSet *)transports
    8585{
    8686    if (_transports)
     
    8888
    8989    auto& transports = _panel->transports();
    90     _transports = [[NSMutableArray alloc] initWithCapacity:transports.size()];
     90    _transports = [[NSMutableSet alloc] initWithCapacity:transports.size()];
    9191    for (auto& transport : transports)
    9292        [_transports addObject:adoptNS([[NSNumber alloc] initWithInt:wkWebAuthenticationTransport(transport)]).get()];
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h

    r257269 r257877  
    5757        virtual void requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&&) = 0;
    5858        virtual void selectAssertionResponse(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, CompletionHandler<void(const WebCore::AuthenticatorAssertionResponse&)>&&) = 0;
    59         virtual void verifyUser(SecAccessControlRef, CompletionHandler<void(LAContext *)>&&) = 0;
     59        virtual void decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&&) = 0;
    6060    };
    6161
  • trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp

    r257571 r257877  
    296296}
    297297
    298 void AuthenticatorManager::verifyUser(SecAccessControlRef accessControlRef, CompletionHandler<void(LAContext *)>&& completionHandler)
    299 {
    300     RetainPtr<SecAccessControlRef> accessControl = accessControlRef;
    301     dispatchPanelClientCall([accessControl = WTFMove(accessControl), completionHandler = WTFMove(completionHandler)] (const API::WebAuthenticationPanel& panel) mutable {
    302         panel.client().verifyUser(accessControl.get(), WTFMove(completionHandler));
     298void AuthenticatorManager::decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&& completionHandler)
     299{
     300    dispatchPanelClientCall([completionHandler = WTFMove(completionHandler)] (const API::WebAuthenticationPanel& panel) mutable {
     301        panel.client().decidePolicyForLocalAuthenticator(WTFMove(completionHandler));
    303302    });
    304303}
  • trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h

    r257269 r257877  
    8484    void requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&&) final;
    8585    void selectAssertionResponse(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, CompletionHandler<void(const WebCore::AuthenticatorAssertionResponse&)>&&) final;
    86     void verifyUser(SecAccessControlRef, CompletionHandler<void(LAContext *)>&&) final;
     86    void decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&&) final;
    8787
    8888    // Overriden by MockAuthenticatorManager.
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.h

    r257269 r257877  
    3939public:
    4040    // Here is the FSM.
    41     // MakeCredential: Init => RequestReceived => UserConsented => Attested => End
    42     // GetAssertion: Init => RequestReceived => ResponseSelected => UserConsented => End
     41    // MakeCredential: Init => RequestReceived => PolicyDecided => UserVerified => Attested => End
     42    // GetAssertion: Init => RequestReceived => ResponseSelected => UserVerified => End
    4343    enum class State {
    4444        Init,
    4545        RequestReceived,
    46         UserConsented,
     46        UserVerified,
    4747        Attested,
    48         ResponseSelected
     48        ResponseSelected,
     49        PolicyDecided,
    4950    };
    5051
     
    5859
    5960    void makeCredential() final;
    60     void continueMakeCredentialAfterUserConsented(SecAccessControlRef, LAContext *);
     61    void continueMakeCredentialAfterDecidePolicy(LocalAuthenticatorPolicy);
     62    void continueMakeCredentialAfterUserVerification(SecAccessControlRef, LocalConnection::UserVerification, LAContext *);
    6163    void continueMakeCredentialAfterAttested(SecKeyRef, Vector<uint8_t>&& credentialId, Vector<uint8_t>&& authData, NSArray *certificates, NSError *);
    6264
    6365    void getAssertion() final;
    6466    void continueGetAssertionAfterResponseSelected(Ref<WebCore::AuthenticatorAssertionResponse>&&);
    65     void continueGetAssertionAfterUserConsented(LAContext *, Ref<WebCore::AuthenticatorAssertionResponse>&&);
     67    void continueGetAssertionAfterUserVerification(Ref<WebCore::AuthenticatorAssertionResponse>&&, LocalConnection::UserVerification, LAContext *);
    6668
    6769    void receiveException(WebCore::ExceptionData&&, WebAuthenticationStatus = WebAuthenticationStatus::LAError) const;
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm

    r257269 r257877  
    161161    // Step 6.
    162162    // Get user consent.
     163    if (auto* observer = this->observer()) {
     164        auto callback = [weakThis = makeWeakPtr(*this)] (LocalAuthenticatorPolicy policy) {
     165            ASSERT(RunLoop::isMain());
     166            if (!weakThis)
     167                return;
     168
     169            weakThis->continueMakeCredentialAfterDecidePolicy(policy);
     170        };
     171        observer->decidePolicyForLocalAuthenticator(WTFMove(callback));
     172    }
     173}
     174
     175void LocalAuthenticator::continueMakeCredentialAfterDecidePolicy(LocalAuthenticatorPolicy policy)
     176{
     177    ASSERT(m_state == State::RequestReceived);
     178    m_state = State::PolicyDecided;
     179
     180    if (policy == LocalAuthenticatorPolicy::Disallow) {
     181        receiveRespond(ExceptionData { UnknownError, "Disallow local authenticator."_s });
     182        return;
     183    }
     184
    163185    RetainPtr<SecAccessControlRef> accessControl;
    164186    {
     
    172194    }
    173195
    174     if (auto* observer = this->observer()) {
    175         SecAccessControlRef accessControlRef = accessControl.get();
    176         auto callback = [accessControl = WTFMove(accessControl), weakThis = makeWeakPtr(*this)] (LAContext *context) {
    177             ASSERT(RunLoop::isMain());
    178             if (!weakThis)
    179                 return;
    180 
    181             weakThis->continueMakeCredentialAfterUserConsented(accessControl.get(), context);
    182         };
    183         observer->verifyUser(accessControlRef, WTFMove(callback));
    184     }
    185 }
    186 
    187 void LocalAuthenticator::continueMakeCredentialAfterUserConsented(SecAccessControlRef accessControlRef, LAContext *context)
     196    SecAccessControlRef accessControlRef = accessControl.get();
     197    auto callback = [accessControl = WTFMove(accessControl), weakThis = makeWeakPtr(*this)] (LocalConnection::UserVerification verification, LAContext *context) {
     198        ASSERT(RunLoop::isMain());
     199        if (!weakThis)
     200            return;
     201
     202        weakThis->continueMakeCredentialAfterUserVerification(accessControl.get(), verification, context);
     203    };
     204    m_connection->verifyUser(accessControlRef, WTFMove(callback));
     205}
     206
     207void LocalAuthenticator::continueMakeCredentialAfterUserVerification(SecAccessControlRef accessControlRef, LocalConnection::UserVerification verification, LAContext *context)
    188208{
    189209    using namespace LocalAuthenticatorInternal;
    190210
    191     ASSERT(m_state == State::RequestReceived);
    192     m_state = State::UserConsented;
     211    ASSERT(m_state == State::PolicyDecided);
     212    m_state = State::UserVerified;
    193213    auto& creationOptions = WTF::get<PublicKeyCredentialCreationOptions>(requestData().options);
    194214
    195     if (!m_connection->isUnlocked(context)) {
    196         receiveRespond(ExceptionData { NotAllowedError, "Couldn't get user consent."_s });
     215    if (verification == LocalConnection::UserVerification::No) {
     216        receiveException({ NotAllowedError, "Couldn't verify user."_s });
    197217        return;
    198218    }
     
    310330    using namespace LocalAuthenticatorInternal;
    311331
    312     ASSERT(m_state == State::UserConsented);
     332    ASSERT(m_state == State::UserVerified);
    313333    m_state = State::Attested;
    314334    auto& creationOptions = WTF::get<PublicKeyCredentialCreationOptions>(requestData().options);
     
    393413    }
    394414
    395     // Step 6.
     415    // Step 6-7. User consent is implicitly acquired by selecting responses.
    396416    for (NSDictionary *attribute : intersectedCredentialsAttributes) {
    397417        auto addResult = m_assertionResponses.add(AuthenticatorAssertionResponse::create(
     
    423443    m_state = State::ResponseSelected;
    424444
    425     // Step 7. Get user consent.
    426     if (auto* observer = this->observer()) {
    427         auto accessControlRef = response->accessControl();
    428         auto callback = [weakThis = makeWeakPtr(*this), response = WTFMove(response)] (LAContext *context) mutable {
    429             ASSERT(RunLoop::isMain());
    430             if (!weakThis)
    431                 return;
    432 
    433             weakThis->continueGetAssertionAfterUserConsented(context, WTFMove(response));
    434         };
    435         observer->verifyUser(accessControlRef, WTFMove(callback));
    436     }
    437 }
    438 
    439 void LocalAuthenticator::continueGetAssertionAfterUserConsented(LAContext *context, Ref<WebCore::AuthenticatorAssertionResponse>&& response)
     445    auto accessControlRef = response->accessControl();
     446    auto callback = [
     447        weakThis = makeWeakPtr(*this),
     448        response = WTFMove(response)
     449    ] (LocalConnection::UserVerification verification, LAContext *context) mutable {
     450        ASSERT(RunLoop::isMain());
     451        if (!weakThis)
     452            return;
     453
     454        weakThis->continueGetAssertionAfterUserVerification(WTFMove(response), verification, context);
     455    };
     456    m_connection->verifyUser(accessControlRef, WTFMove(callback));
     457}
     458
     459void LocalAuthenticator::continueGetAssertionAfterUserVerification(Ref<WebCore::AuthenticatorAssertionResponse>&& response, LocalConnection::UserVerification verification, LAContext *context)
    440460{
    441461    using namespace LocalAuthenticatorInternal;
    442462    ASSERT(m_state == State::ResponseSelected);
    443     m_state = State::UserConsented;
    444 
    445     if (!m_connection->isUnlocked(context)) {
    446         receiveRespond(ExceptionData { NotAllowedError, "Couldn't get user consent."_s });
     463    m_state = State::UserVerified;
     464
     465    if (verification == LocalConnection::UserVerification::No) {
     466        receiveException({ NotAllowedError, "Couldn't verify user."_s });
    447467        return;
    448468    }
     
    457477    RetainPtr<CFDataRef> signature;
    458478    {
    459         auto query = adoptNS([[NSMutableDictionary alloc] init]);
    460         [query addEntriesFromDictionary:@{
     479        NSDictionary *query = @{
    461480            (id)kSecClass: (id)kSecClassKey,
    462481            (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
    463482            (id)kSecAttrApplicationLabel: toNSData(response->rawId()).get(),
     483            (id)kSecUseAuthenticationContext: context,
    464484            (id)kSecReturnRef: @YES,
    465485#if HAVE(DATA_PROTECTION_KEYCHAIN)
     
    468488            (id)kSecAttrNoLegacy: @YES
    469489#endif
    470         }];
    471         // context is nullptr in mock testing.
    472         if (context)
    473             [query setObject:context forKey:(id)kSecUseAuthenticationContext];
     490        };
    474491        CFTypeRef privateKeyRef = nullptr;
    475         OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query.get(), &privateKeyRef);
     492        OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &privateKeyRef);
    476493        if (status) {
    477494            receiveException({ UnknownError, makeString("Couldn't get the private key reference: ", status) });
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.h

    r257410 r257877  
    3737
    3838namespace WebCore {
    39 
    4039class AuthenticatorAssertionResponse;
    41 
    4240}
    4341
     
    5351    WTF_MAKE_NONCOPYABLE(LocalConnection);
    5452public:
     53    enum class UserVerification : bool {
     54        No,
     55        Yes
     56    };
     57
    5558    using AttestationCallback = CompletionHandler<void(NSArray *, NSError *)>;
     59    using UserVerificationCallback = CompletionHandler<void(UserVerification, LAContext *)>;
    5660
    5761    LocalConnection() = default;
     
    5963
    6064    // Overrided by MockLocalConnection.
    61     virtual bool isUnlocked(LAContext *) const;
     65    virtual void verifyUser(SecAccessControlRef, UserVerificationCallback&&) const;
    6266    virtual RetainPtr<SecKeyRef> createCredentialPrivateKey(LAContext *, SecAccessControlRef, const String& secAttrLabel, NSData *secAttrApplicationTag) const;
    6367    virtual void getAttestation(SecKeyRef, NSData *authData, NSData *hash, AttestationCallback&&) const;
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.mm

    r257269 r257877  
    2929#if ENABLE(WEB_AUTHN)
    3030
     31#import <WebCore/LocalizedStrings.h>
    3132#import <wtf/BlockPtr.h>
    3233#import <wtf/RunLoop.h>
     
    4041namespace WebKit {
    4142
    42 bool LocalConnection::isUnlocked(LAContext *context) const
     43void LocalConnection::verifyUser(SecAccessControlRef accessControl, UserVerificationCallback&& completionHandler) const
    4344{
    44     NSError *error = nil;
    45     auto result = [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics options:@{ @(LAOptionNotInteractive): @YES } error:&error];
    46     if (!result)
    47         LOG_ERROR("Couldn't get user consent: %@", error);
    48     return !!result;
     45    auto context = adoptNS([allocLAContextInstance() init]);
     46
     47    auto options = adoptNS([[NSMutableDictionary alloc] init]);
     48    if ([context biometryType] == LABiometryTypeTouchID)
     49        [options setObject:WebCore::touchIDPromptTitle() forKey:@(LAOptionAuthenticationTitle)];
     50    [options setObject:WebCore::biometricFallbackPromptTitle() forKey:@(LAOptionPasscodeTitle)];
     51
     52    auto reply = makeBlockPtr([context, completionHandler = WTFMove(completionHandler)] (NSDictionary *, NSError *error) mutable {
     53        ASSERT(!RunLoop::isMain());
     54
     55        UserVerification verification = UserVerification::Yes;
     56        if (error) {
     57            LOG_ERROR("Couldn't authenticate with biometrics: %@", error);
     58            verification = UserVerification::No;
     59        }
     60        RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), verification, context = WTFMove(context)] () mutable {
     61            completionHandler(verification, context.get());
     62        });
     63    });
     64
     65    [context evaluateAccessControl:accessControl operation:LAAccessControlOperationUseKeySign options:options.get() reply:reply.get()];
    4966}
    5067
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalService.mm

    r257085 r257877  
    5656#if defined(LOCALSERVICE_ADDITIONS)
    5757LOCALSERVICE_ADDITIONS
     58#else
     59    return false;
    5860#endif
    5961
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h

    r257269 r257877  
    5151    void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&&) const final;
    5252    void selectAssertionResponse(Vector<Ref<WebCore::AuthenticatorAssertionResponse>>&&, CompletionHandler<void(const WebCore::AuthenticatorAssertionResponse&)>&&) const final;
    53     void verifyUser(SecAccessControlRef, CompletionHandler<void(LAContext *)>&&) const final;
     53    void decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&&) const final;
    5454
    5555    _WKWebAuthenticationPanel *m_panel;
     
    6161        bool panelRequestPinWithRemainingRetriesCompletionHandler : 1;
    6262        bool panelSelectAssertionResponseCompletionHandler : 1;
    63         bool panelVerifyUserWithAccessControlCompletionHandler : 1;
     63        bool panelDecidePolicyForLocalAuthenticatorCompletionHandler : 1;
    6464    } m_delegateMethods;
    6565};
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm

    r257269 r257877  
    3333#import "CompletionHandlerCallChecker.h"
    3434#import "WKNSArray.h"
    35 #import "WebAuthenticationFlags.h"
    3635#import "_WKWebAuthenticationAssertionResponseInternal.h"
    3736#import "_WKWebAuthenticationPanel.h"
     
    5150    m_delegateMethods.panelRequestPinWithRemainingRetriesCompletionHandler = [delegate respondsToSelector:@selector(panel:requestPINWithRemainingRetries:completionHandler:)];
    5251    m_delegateMethods.panelSelectAssertionResponseCompletionHandler = [delegate respondsToSelector:@selector(panel:selectAssertionResponse:completionHandler:)];
    53     m_delegateMethods.panelVerifyUserWithAccessControlCompletionHandler = [delegate respondsToSelector:@selector(panel:verifyUserWithAccessControl:completionHandler:)];
     52    m_delegateMethods.panelDecidePolicyForLocalAuthenticatorCompletionHandler = [delegate respondsToSelector:@selector(panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:)];
    5453}
    5554
     
    168167}
    169168
    170 void WebAuthenticationPanelClient::verifyUser(SecAccessControlRef accessControl, CompletionHandler<void(LAContext *)>&& completionHandler) const
    171 {
    172     if (!m_delegateMethods.panelVerifyUserWithAccessControlCompletionHandler) {
    173         completionHandler(adoptNS([allocLAContextInstance() init]).get());
     169static LocalAuthenticatorPolicy localAuthenticatorPolicy(_WKLocalAuthenticatorPolicy result)
     170{
     171    switch (result) {
     172    case _WKLocalAuthenticatorPolicyAllow:
     173        return LocalAuthenticatorPolicy::Allow;
     174    case _WKLocalAuthenticatorPolicyDisallow:
     175        return LocalAuthenticatorPolicy::Disallow;
     176    }
     177    ASSERT_NOT_REACHED();
     178    return LocalAuthenticatorPolicy::Allow;
     179}
     180
     181void WebAuthenticationPanelClient::decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&& completionHandler) const
     182{
     183    if (!m_delegateMethods.panelDecidePolicyForLocalAuthenticatorCompletionHandler) {
     184        completionHandler(LocalAuthenticatorPolicy::Disallow);
    174185        return;
    175186    }
     
    177188    auto delegate = m_delegate.get();
    178189    if (!delegate) {
    179         completionHandler(adoptNS([allocLAContextInstance() init]).get());
    180         return;
    181     }
    182 
    183     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(panel:verifyUserWithAccessControl:completionHandler:));
    184     [delegate panel:m_panel verifyUserWithAccessControl:accessControl completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](LAContext *context) mutable {
     190        completionHandler(LocalAuthenticatorPolicy::Disallow);
     191        return;
     192    }
     193
     194    auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:));
     195    [delegate panel:m_panel decidePolicyForLocalAuthenticatorWithCompletionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](_WKLocalAuthenticatorPolicy policy) mutable {
    185196        if (checker->completionHandlerHasBeenCalled())
    186197            return;
    187198        checker->didCallCompletionHandler();
    188         completionHandler(context);
     199        completionHandler(localAuthenticatorPolicy(policy));
    189200    }).get()];
    190201}
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h

    r257269 r257877  
    3838
    3939private:
    40     bool isUnlocked(LAContext *) const final;
     40    void verifyUser(SecAccessControlRef, UserVerificationCallback&&) const final;
    4141    RetainPtr<SecKeyRef> createCredentialPrivateKey(LAContext *, SecAccessControlRef, const String& secAttrLabel, NSData *secAttrApplicationTag) const final;
    4242    void getAttestation(SecKeyRef, NSData *authData, NSData *hash, AttestationCallback&&) const final;
  • trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm

    r257269 r257877  
    4545}
    4646
    47 bool MockLocalConnection::isUnlocked(LAContext *context) const
     47void MockLocalConnection::verifyUser(SecAccessControlRef, UserVerificationCallback&& callback) const
    4848{
    49     return m_configuration.local->acceptAuthentication;
     49    // Mock async operations.
     50    RunLoop::main().dispatch([configuration = m_configuration, callback = WTFMove(callback)]() mutable {
     51        ASSERT(configuration.local);
     52        if (!configuration.local->acceptAuthentication) {
     53            callback(UserVerification::No, nil);
     54            return;
     55        }
     56        callback(UserVerification::Yes, adoptNS([allocLAContextInstance() init]).get());
     57    });
    5058}
    5159
  • trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationFlags.h

    r257269 r257877  
    5252};
    5353
     54enum class LocalAuthenticatorPolicy : bool {
     55    Allow,
     56    Disallow
     57};
     58
    5459} // namespace WebKit
    5560
  • trunk/Tools/ChangeLog

    r257876 r257877  
     12020-03-03  Jiewen Tan  <jiewen_tan@apple.com>
     2
     3        [WebAuthn] Implement -[_WKWebAuthenticationPanelDelegate panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:] SPI
     4        https://bugs.webkit.org/show_bug.cgi?id=208533
     5        <rdar://problem/60010184>
     6
     7        Reviewed by Alex Christensen.
     8
     9        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     10        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
     11        (-[TestWebAuthenticationPanelDelegate panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:]):
     12        (TestWebKitAPI::TEST):
     13        (-[TestWebAuthenticationPanelDelegate panel:verifyUserWithAccessControl:completionHandler:]): Deleted.
     14        * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-la.html: Removed.
     15
    1162020-03-04  Alex Christensen  <achristensen@webkit.org>
    217
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r257828 r257877  
    354354                574217882400AC25002B303D /* web-authentication-make-credential-la-error.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 574217872400ABFD002B303D /* web-authentication-make-credential-la-error.html */; };
    355355                5742178A2400AED8002B303D /* web-authentication-make-credential-la-duplicate-credential.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 574217892400AED0002B303D /* web-authentication-make-credential-la-duplicate-credential.html */; };
    356                 5742178C2400CD47002B303D /* web-authentication-get-assertion-la.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5742178B2400CD2D002B303D /* web-authentication-get-assertion-la.html */; };
    357356                5742178E2400D2DF002B303D /* web-authentication-make-credential-la.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5742178D2400D26C002B303D /* web-authentication-make-credential-la.html */; };
    358357                574F55D2204D47F0002948C6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F55D0204D471C002948C6 /* Security.framework */; };
     
    15301529                                570D26FC23C3F87000D5CF67 /* web-authentication-get-assertion-hid-pin.html in Copy Resources */,
    15311530                                57663DEC234F1F9300E85E09 /* web-authentication-get-assertion-hid.html in Copy Resources */,
    1532                                 5742178C2400CD47002B303D /* web-authentication-get-assertion-la.html in Copy Resources */,
    15331531                                579833922368FA37008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */,
    15341532                                57663DEA234EA66D00E85E09 /* web-authentication-get-assertion-nfc.html in Copy Resources */,
     
    19831981                574217872400ABFD002B303D /* web-authentication-make-credential-la-error.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-la-error.html"; sourceTree = "<group>"; };
    19841982                574217892400AED0002B303D /* web-authentication-make-credential-la-duplicate-credential.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-la-duplicate-credential.html"; sourceTree = "<group>"; };
    1985                 5742178B2400CD2D002B303D /* web-authentication-get-assertion-la.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-get-assertion-la.html"; sourceTree = "<group>"; };
    19861983                5742178D2400D26C002B303D /* web-authentication-make-credential-la.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-la.html"; sourceTree = "<group>"; };
    19871984                5742178F2400D54D002B303D /* web-authentication-make-credential.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential.html"; sourceTree = "<group>"; };
     
    36153612                                570D26FB23C3F86500D5CF67 /* web-authentication-get-assertion-hid-pin.html */,
    36163613                                57663DEB234F1F8000E85E09 /* web-authentication-get-assertion-hid.html */,
    3617                                 5742178B2400CD2D002B303D /* web-authentication-get-assertion-la.html */,
    36183614                                5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */,
    36193615                                57663DE9234EA60B00E85E09 /* web-authentication-get-assertion-nfc.html */,
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm

    r257269 r257877  
    5656static bool webAuthenticationPanelUpdateLANoCredential = false;
    5757static bool webAuthenticationPanelCancelImmediately = false;
    58 static bool webAuthenticationPanelVerifyUser = false;
     58static _WKLocalAuthenticatorPolicy localAuthenticatorPolicy = _WKLocalAuthenticatorPolicyDisallow;
    5959static String webAuthenticationPanelPin;
    6060static BOOL webAuthenticationPanelNullUserHandle = NO;
     
    152152}
    153153
    154 - (void)panel:(_WKWebAuthenticationPanel *)panel verifyUserWithAccessControl:(SecAccessControlRef)accessControl completionHandler:(void (^)(LAContext *))completionHandler
    155 {
    156     webAuthenticationPanelVerifyUser = true;
    157     auto context = adoptNS([[LAContext alloc] init]);
    158     completionHandler(context.get());
     154- (void)panel:(_WKWebAuthenticationPanel *)panel decidePolicyForLocalAuthenticatorWithCompletionHandler:(void (^)(_WKLocalAuthenticatorPolicy policy))completionHandler
     155{
     156    completionHandler(localAuthenticatorPolicy);
    159157}
    160158
     
    301299    webAuthenticationPanelPin = emptyString();
    302300    webAuthenticationPanelNullUserHandle = NO;
    303     webAuthenticationPanelVerifyUser = false;
     301    localAuthenticatorPolicy = _WKLocalAuthenticatorPolicyDisallow;
    304302}
    305303
     
    308306    EXPECT_WK_STREQ(panel.relyingPartyID, relyingPartyID);
    309307
    310     // Brute force given the maximum size of the array is 4.
    311     auto *theTransports = panel.transports;
    312     EXPECT_EQ(theTransports.count, transports.count);
     308    EXPECT_EQ(panel.transports.count, transports.count);
    313309    size_t count = 0;
    314310    for (NSNumber *transport : transports) {
    315         for (NSNumber *theTransport : theTransports) {
    316             if (transport == theTransport) {
    317                 count++;
    318                 break;
    319             }
    320         }
     311        if ([panel.transports containsObject:transport])
     312            count++;
    321313    }
    322314    EXPECT_EQ(count, transports.count);
     
    12601252
    12611253    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
    1262     [webView waitForMessage:@"Succeeded!"];
     1254    [webView waitForMessage:@"Disallow local authenticator."];
     1255}
     1256
     1257TEST(WebAuthenticationPanel, LAMakeCredentialDisallowLocalAuthenticator)
     1258{
     1259    reset();
     1260    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
     1261
     1262    auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
     1263    [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
     1264    [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
     1265
     1266    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
     1267    auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
     1268    [webView setUIDelegate:delegate.get()];
     1269
     1270    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
     1271    [webView waitForMessage:@"Disallow local authenticator."];
     1272}
     1273
     1274TEST(WebAuthenticationPanel, LAMakeCredentialAllowLocalAuthenticator)
     1275{
     1276    reset();
     1277    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
     1278
     1279    auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
     1280    [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
     1281    [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
     1282
     1283    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
     1284    auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
     1285    [webView setUIDelegate:delegate.get()];
     1286
     1287    localAuthenticatorPolicy = _WKLocalAuthenticatorPolicyAllow;
     1288    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
     1289    [webView waitForMessage:@"Succeeded!"];
     1290    checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get(), adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportInternal]).get()], _WKWebAuthenticationTypeCreate);
    12631291    cleanUpKeychain("");
    12641292}
    12651293
    1266 TEST(WebAuthenticationPanel, LAMakeCredential)
    1267 {
    1268     reset();
    1269     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
    1270 
    1271     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
    1272     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
    1273     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
    1274 
    1275     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
    1276     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
    1277     [webView setUIDelegate:delegate.get()];
    1278 
    1279     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
    1280     Util::run(&webAuthenticationPanelVerifyUser);
    1281     checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get(), adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportInternal]).get()], _WKWebAuthenticationTypeCreate);
    1282     [webView waitForMessage:@"Succeeded!"];
    1283 }
    1284 
    1285 TEST(WebAuthenticationPanel, LAGetAssertion)
    1286 {
    1287     reset();
    1288     RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-la" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
    1289 
    1290     auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
    1291     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()];
    1292     [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationLocalAuthenticatorExperimentalFeature()];
    1293 
    1294     auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]);
    1295     auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]);
    1296     [webView setUIDelegate:delegate.get()];
    1297 
    1298     ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "", testUserhandleBase64));
    1299     [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
    1300     Util::run(&webAuthenticationPanelVerifyUser);
    1301     checkPanel([delegate panel], @"", @[adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportUSB]).get(), adoptNS([[NSNumber alloc] initWithInt:_WKWebAuthenticationTransportInternal]).get()], _WKWebAuthenticationTypeGet);
    1302     [webView waitForMessage:@"Succeeded!"];
    1303     cleanUpKeychain("");
    1304 }
    1305 
    13061294#endif // USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
    13071295
Note: See TracChangeset for help on using the changeset viewer.