Title: [272826] trunk
Revision
272826
Author
[email protected]
Date
2021-02-12 17:40:41 -0800 (Fri, 12 Feb 2021)

Log Message

[WebAuthn] Provide SPI to query local credentials
https://bugs.webkit.org/show_bug.cgi?id=221743
<rdar://problem/65849832>

Reviewed by Brent Fulgham.

Source/WebKit:

Covered by API tests.

* UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h:
* UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
(getAllLocalAuthenticatorCredentialsImpl):
(+[_WKWebAuthenticationPanel getAllLocalAuthenticatorCredentials]):
(+[_WKWebAuthenticationPanel getAllLocalAuthenticatorCredentialsWithAccessGroup:]):
(+[_WKWebAuthenticationPanel deleteLocalAuthenticatorCredentialWithID:]):
* UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (272825 => 272826)


--- trunk/Source/WebKit/ChangeLog	2021-02-13 01:27:47 UTC (rev 272825)
+++ trunk/Source/WebKit/ChangeLog	2021-02-13 01:40:41 UTC (rev 272826)
@@ -1,3 +1,21 @@
+2021-02-12  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Provide SPI to query local credentials
+        https://bugs.webkit.org/show_bug.cgi?id=221743
+        <rdar://problem/65849832>
+
+        Reviewed by Brent Fulgham.
+
+        Covered by API tests.
+
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h:
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
+        (getAllLocalAuthenticatorCredentialsImpl):
+        (+[_WKWebAuthenticationPanel getAllLocalAuthenticatorCredentials]):
+        (+[_WKWebAuthenticationPanel getAllLocalAuthenticatorCredentialsWithAccessGroup:]):
+        (+[_WKWebAuthenticationPanel deleteLocalAuthenticatorCredentialWithID:]):
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h:
+
 2021-02-12  Jer Noble  <[email protected]>
 
         [Mac] Unable to play WebM/Opus generated from Chrome MediaRecorder

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h (272825 => 272826)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h	2021-02-13 01:27:47 UTC (rev 272825)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h	2021-02-13 01:40:41 UTC (rev 272826)
@@ -24,6 +24,7 @@
  */
 
 #import <Foundation/Foundation.h>
+#import <WebKit/WKDeclarationSpecifiers.h>
 #import <WebKit/WKFoundation.h>
 
 NS_ASSUME_NONNULL_BEGIN
@@ -79,6 +80,10 @@
     _WKWebAuthenticationSourceExternal,
 } WK_API_AVAILABLE(macos(11.0), ios(14.0));
 
+WK_EXPORT extern NSString * const _WKLocalAuthenticatorCredentialNameKey;
+WK_EXPORT extern NSString * const _WKLocalAuthenticatorCredentialIDKey;
+WK_EXPORT extern NSString * const _WKLocalAuthenticatorCredentialRelyingPartyIDKey;
+
 @protocol _WKWebAuthenticationPanelDelegate <NSObject>
 
 @optional
@@ -98,9 +103,12 @@
 
 @property (nullable, nonatomic, weak) id <_WKWebAuthenticationPanelDelegate> delegate;
 
-+ (void)clearAllLocalAuthenticatorCredentials;
-+ (BOOL)isUserVerifyingPlatformAuthenticatorAvailable;
++ (NSArray<NSDictionary *> *)getAllLocalAuthenticatorCredentials WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
++ (void)deleteLocalAuthenticatorCredentialWithID:(NSData *)credentialID WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
++ (void)clearAllLocalAuthenticatorCredentials WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
++ (BOOL)isUserVerifyingPlatformAuthenticatorAvailable WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 - (instancetype)init;
 
 // FIXME: <rdar://problem/71509485> Adds detailed NSError.

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm (272825 => 272826)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm	2021-02-13 01:27:47 UTC (rev 272825)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm	2021-02-13 01:40:41 UTC (rev 272826)
@@ -44,6 +44,8 @@
 #import "_WKPublicKeyCredentialUserEntity.h"
 #import <WebCore/AuthenticatorResponse.h>
 #import <WebCore/AuthenticatorResponseData.h>
+#import <WebCore/CBORReader.h>
+#import <WebCore/FidoConstants.h>
 #import <WebCore/MockWebAuthenticationConfiguration.h>
 #import <WebCore/PublicKeyCredentialCreationOptions.h>
 #import <WebCore/PublicKeyCredentialRequestOptions.h>
@@ -79,6 +81,10 @@
 }
 #endif
 
+NSString * const _WKLocalAuthenticatorCredentialNameKey = @"_WKLocalAuthenticatorCredentialNameKey";
+NSString * const _WKLocalAuthenticatorCredentialIDKey = @"_WKLocalAuthenticatorCredentialIDKey";
+NSString * const _WKLocalAuthenticatorCredentialRelyingPartyIDKey = @"_WKLocalAuthenticatorCredentialRelyingPartyIDKey";
+
 @implementation _WKWebAuthenticationPanel {
 #if ENABLE(WEB_AUTHN)
     WeakPtr<WebKit::WebAuthenticationPanelClient> _client;
@@ -180,6 +186,88 @@
 }
 #endif // ENABLE(WEB_AUTHN)
 
+#if ENABLE(WEB_AUTHN)
+static RetainPtr<NSArray> getAllLocalAuthenticatorCredentialsImpl(NSString *accessGroup)
+{
+    NSDictionary *query = @{
+        (__bridge id)kSecClass: (__bridge id)kSecClassKey,
+        (__bridge id)kSecAttrKeyClass: (__bridge id)kSecAttrKeyClassPrivate,
+        (__bridge id)kSecAttrAccessGroup: accessGroup,
+        (__bridge id)kSecReturnAttributes: @YES,
+        (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitAll,
+#if HAVE(DATA_PROTECTION_KEYCHAIN)
+        (__bridge id)kSecUseDataProtectionKeychain: @YES
+#else
+        (__bridge id)kSecAttrNoLegacy: @YES
+#endif
+    };
+    CFTypeRef attributesArrayRef = nullptr;
+    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesArrayRef);
+    if (status && status != errSecItemNotFound)
+        return nullptr;
+    auto retainAttributesArray = adoptCF(attributesArrayRef);
+
+    auto result = adoptNS([[NSMutableArray alloc] init]);
+    for (NSDictionary *attributes in (NSArray *)attributesArrayRef) {
+        auto decodedResponse = cbor::CBORReader::read(vectorFromNSData(attributes[(__bridge id)kSecAttrApplicationTag]));
+        if (!decodedResponse || !decodedResponse->isMap()) {
+            ASSERT_NOT_REACHED();
+            return nullptr;
+        }
+        auto& responseMap = decodedResponse->getMap();
+
+        auto it = responseMap.find(cbor::CBORValue(fido::kEntityNameMapKey));
+        if (it == responseMap.end() || !it->second.isString()) {
+            ASSERT_NOT_REACHED();
+            return nullptr;
+        }
+        auto& username = it->second.getString();
+
+        [result addObject:@{
+            _WKLocalAuthenticatorCredentialNameKey: username,
+            _WKLocalAuthenticatorCredentialIDKey: attributes[(__bridge id)kSecAttrApplicationLabel],
+            _WKLocalAuthenticatorCredentialRelyingPartyIDKey: attributes[(__bridge id)kSecAttrLabel]
+        }];
+    }
+
+    return result;
+}
+#endif
+
++ (NSArray<NSDictionary *> *)getAllLocalAuthenticatorCredentials
+{
+#if ENABLE(WEB_AUTHN)
+    return getAllLocalAuthenticatorCredentialsImpl(String(WebCore::LocalAuthenticatiorAccessGroup)).autorelease();
+#else
+    return nullptr;
+#endif
+}
+
++ (NSArray<NSDictionary *> *)getAllLocalAuthenticatorCredentialsWithAccessGroup:(NSString *)accessGroup
+{
+#if ENABLE(WEB_AUTHN)
+    return getAllLocalAuthenticatorCredentialsImpl(accessGroup).autorelease();
+#else
+    return nullptr;
+#endif
+}
+
++ (void)deleteLocalAuthenticatorCredentialWithID:(NSData *)credentialID
+{
+#if ENABLE(WEB_AUTHN)
+    NSDictionary* deleteQuery = @{
+        (__bridge id)kSecClass: (__bridge id)kSecClassKey,
+        (__bridge id)kSecAttrApplicationLabel: credentialID,
+#if HAVE(DATA_PROTECTION_KEYCHAIN)
+        (__bridge id)kSecUseDataProtectionKeychain: @YES
+#else
+        (__bridge id)kSecAttrNoLegacy: @YES
+#endif
+    };
+    SecItemDelete((__bridge CFDictionaryRef)deleteQuery);
+#endif
+}
+
 + (void)clearAllLocalAuthenticatorCredentials
 {
 #if ENABLE(WEB_AUTHN)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h (272825 => 272826)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h	2021-02-13 01:27:47 UTC (rev 272825)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h	2021-02-13 01:40:41 UTC (rev 272826)
@@ -38,6 +38,8 @@
 + (WebCore::PublicKeyCredentialCreationOptions)convertToCoreCreationOptionsWithOptions:(_WKPublicKeyCredentialCreationOptions *)options WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 + (WebCore::PublicKeyCredentialRequestOptions)convertToCoreRequestOptionsWithOptions:(_WKPublicKeyCredentialRequestOptions *)options WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
++ (NSArray<NSDictionary *> *)getAllLocalAuthenticatorCredentialsWithAccessGroup:(NSString *)accessGroup WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 // For details of configuration, refer to MockWebAuthenticationConfiguration.h.
 @property (nonatomic, copy) NSDictionary *mockConfiguration;
 

Modified: trunk/Tools/ChangeLog (272825 => 272826)


--- trunk/Tools/ChangeLog	2021-02-13 01:27:47 UTC (rev 272825)
+++ trunk/Tools/ChangeLog	2021-02-13 01:40:41 UTC (rev 272826)
@@ -1,3 +1,14 @@
+2021-02-12  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Provide SPI to query local credentials
+        https://bugs.webkit.org/show_bug.cgi?id=221743
+        <rdar://problem/65849832>
+
+        Reviewed by Brent Fulgham.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
+        (TestWebKitAPI::TEST):
+
 2021-02-12  Michael Saboff  <[email protected]>
 
         [ARM64e] Harden Mach exception handling

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm (272825 => 272826)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2021-02-13 01:27:47 UTC (rev 272825)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2021-02-13 01:40:41 UTC (rev 272826)
@@ -1925,6 +1925,37 @@
     }];
     Util::run(&webAuthenticationPanelRan);
 }
+
+TEST(WebAuthenticationPanel, GetAllCredential)
+{
+    reset();
+
+    ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "example.com", testUserEntityBundleBase64));
+
+    auto *credentials = [_WKWebAuthenticationPanel getAllLocalAuthenticatorCredentialsWithAccessGroup:@"com.apple.TestWebKitAPI"];
+    EXPECT_NOT_NULL(credentials);
+    EXPECT_EQ([credentials count], 1lu);
+
+    EXPECT_NOT_NULL([credentials firstObject]);
+    EXPECT_WK_STREQ([credentials firstObject][_WKLocalAuthenticatorCredentialNameKey], "John");
+    EXPECT_WK_STREQ([[credentials firstObject][_WKLocalAuthenticatorCredentialIDKey] base64EncodedStringWithOptions:0], "SMSXHngF7hEOsElA73C3RY+8bR4=");
+    EXPECT_WK_STREQ([credentials firstObject][_WKLocalAuthenticatorCredentialRelyingPartyIDKey], "example.com");
+
+    cleanUpKeychain("example.com");
+}
+
+TEST(WebAuthenticationPanel, DeleteOneCredential)
+{
+    reset();
+
+    ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "example.com", testUserEntityBundleBase64));
+
+    [_WKWebAuthenticationPanel deleteLocalAuthenticatorCredentialWithID:adoptNS([[NSData alloc] initWithBase64EncodedString:@"SMSXHngF7hEOsElA73C3RY+8bR4=" options:0]).get()];
+
+    auto *credentials = [_WKWebAuthenticationPanel getAllLocalAuthenticatorCredentialsWithAccessGroup:@"com.apple.TestWebKitAPI"];
+    EXPECT_NOT_NULL(credentials);
+    EXPECT_EQ([credentials count], 0lu);
+}
 #endif
 
 } // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to