| Differences between
and this patch
- a/Source/WebKit/ChangeLog +44 lines
Lines 1-3 a/Source/WebKit/ChangeLog_sec1
1
2020-12-24  Jiewen Tan  <jiewen_tan@apple.com>
2
3
        [WebAuthn] Adopt new UI for the Client PIN and dismiss flow
4
        https://bugs.webkit.org/show_bug.cgi?id=219712
5
        <rdar://problem/72154935>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Covered by manual tests.
10
11
        This patch does the following few things:
12
        1. It tweaks the WebAuthn process as a UI view service to be able to run NearField in the background.
13
        2. It adopts new SPI for security keys' client pin support.
14
        3. It adopts new SPI to dismiss the UI when necessary.
15
16
        * Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h:
17
        (NS_ERROR_ENUM):
18
        Adds new SPI.
19
20
        * Scripts/process-entitlements.sh:
21
        Tweaks WebAuthn process for NFC.
22
23
        * UIProcess/WebAuthentication/Cocoa/AuthenticationServicesCoreSoftLink.h:
24
        * UIProcess/WebAuthentication/Cocoa/AuthenticationServicesCoreSoftLink.mm:
25
        Paperwork.
26
27
        * UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.h:
28
        * UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.mm:
29
        (WebKit::AuthenticatorPresenterCoordinator::~AuthenticatorPresenterCoordinator):
30
        (WebKit::AuthenticatorPresenterCoordinator::updatePresenter):
31
        (WebKit::AuthenticatorPresenterCoordinator::requestPin):
32
        (WebKit::AuthenticatorPresenterCoordinator::dimissPresenter):
33
        (WebKit::AuthenticatorPresenterCoordinator::setPin):
34
        Adopts new SPIs.
35
36
        * UIProcess/WebAuthentication/Cocoa/NfcService.mm:
37
        (WebKit::NfcService::platformStartDiscovery):
38
        Tweaks NFC.
39
40
        * UIProcess/WebAuthentication/Cocoa/WKASCAuthorizationPresenterDelegate.mm:
41
        (-[WKASCAuthorizationPresenterDelegate authorizationPresenter:credentialRequestedForLoginChoice:authenticatedContext:completionHandler:]):
42
        (-[WKASCAuthorizationPresenterDelegate authorizationPresenter:validateUserEnteredPIN:completionHandler:]):
43
        Adopts new SPIs.
44
1
2020-12-21  Wenson Hsieh  <wenson_hsieh@apple.com>
45
2020-12-21  Wenson Hsieh  <wenson_hsieh@apple.com>
2
46
3
        REGRESSION (iOS 14): Bad access crash in ShareableBitmap::makeCGImageCopy() under assignLegacyDataForContextMenuInteraction()
47
        REGRESSION (iOS 14): Bad access crash in ShareableBitmap::makeCGImageCopy() under assignLegacyDataForContextMenuInteraction()
- a/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h +19 lines
Lines 71-76 NS_ASSUME_NONNULL_BEGIN a/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h_sec1
71
71
72
- (void)presentAuthorizationWithContext:(ASCAuthorizationPresentationContext *)context completionHandler:(void (^)(id<ASCCredentialProtocol> _Nullable, NSError * _Nullable))completionHandler;
72
- (void)presentAuthorizationWithContext:(ASCAuthorizationPresentationContext *)context completionHandler:(void (^)(id<ASCCredentialProtocol> _Nullable, NSError * _Nullable))completionHandler;
73
- (void)updateInterfaceWithLoginChoices:(NSArray<id <ASCLoginChoiceProtocol>> *)loginChoices;
73
- (void)updateInterfaceWithLoginChoices:(NSArray<id <ASCLoginChoiceProtocol>> *)loginChoices;
74
- (void)presentPINEntryInterface;
75
- (void)dismissWithError:(nullable NSError *)error;
74
76
75
@property (nonatomic, weak) id <ASCAuthorizationPresenterDelegate> delegate;
77
@property (nonatomic, weak) id <ASCAuthorizationPresenterDelegate> delegate;
76
78
Lines 158-163 typedef NS_ENUM(NSInteger, ASCSecurityKeyPublicKeyCredentialLoginChoiceKind) { a/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h_sec2
158
160
159
@end
161
@end
160
162
163
extern NSErrorDomain const ASCAuthorizationErrorDomain;
164
165
typedef NS_ERROR_ENUM(ASCAuthorizationErrorDomain, ASCAuthorizationError) {
166
    ASCAuthorizationErrorUnknown,
167
    ASCAuthorizationErrorFailed,
168
    ASCAuthorizationErrorUserCanceled,
169
    ASCAuthorizationErrorPINRequired,
170
};
171
172
extern NSString * const ASCPINValidationResultKey;
173
174
typedef NS_ENUM(NSInteger, ASCPINValidationResult) {
175
    ASCPINValidationResultPINBlocked,
176
    ASCPINValidationResultPINAuthBlocked,
177
    ASCPINValidationResultPINInvalid,
178
};
179
161
NS_ASSUME_NONNULL_END
180
NS_ASSUME_NONNULL_END
162
181
163
//#endif // USE(APPLE_INTERNAL_SDK)
182
//#endif // USE(APPLE_INTERNAL_SDK)
- a/Source/WebKit/Scripts/process-entitlements.sh +3 lines
Lines 243-248 function ios_family_process_webauthn_entitlements() a/Source/WebKit/Scripts/process-entitlements.sh_sec1
243
243
244
    plistbuddy Add :com.apple.nfcd.hwmanager bool YES
244
    plistbuddy Add :com.apple.nfcd.hwmanager bool YES
245
    plistbuddy Add :com.apple.nfcd.session.reader.internal bool YES
245
    plistbuddy Add :com.apple.nfcd.session.reader.internal bool YES
246
    # FIXME(rdar://problem/72646664): Find a better way to invoke NearField in the background.
247
    plistbuddy Add :com.apple.internal.nfc.allow.backgrounded.session bool YES
248
    plistbuddy Add :com.apple.UIKit.vends-view-services bool YES
246
249
247
    plistbuddy Add :keychain-access-groups array
250
    plistbuddy Add :keychain-access-groups array
248
    plistbuddy Add :keychain-access-groups:0 string com.apple.webkit.webauthn
251
    plistbuddy Add :keychain-access-groups:0 string com.apple.webkit.webauthn
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticationServicesCoreSoftLink.h +6 lines
Lines 38-41 SOFT_LINK_CLASS_FOR_HEADER(WebKit, ASCPlatformPublicKeyCredentialLoginChoice); a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticationServicesCoreSoftLink.h_sec1
38
SOFT_LINK_CLASS_FOR_HEADER(WebKit, ASCSecurityKeyPublicKeyCredentialLoginChoice);
38
SOFT_LINK_CLASS_FOR_HEADER(WebKit, ASCSecurityKeyPublicKeyCredentialLoginChoice);
39
SOFT_LINK_CLASS_FOR_HEADER(WebKit, ASCAppleIDCredential);
39
SOFT_LINK_CLASS_FOR_HEADER(WebKit, ASCAppleIDCredential);
40
40
41
SOFT_LINK_CONSTANT_FOR_HEADER(WebKit, AuthenticationServicesCore, ASCAuthorizationErrorDomain, NSErrorDomain);
42
#define ASCAuthorizationErrorDomain WebKit::get_AuthenticationServicesCore_ASCAuthorizationErrorDomain()
43
44
SOFT_LINK_CONSTANT_FOR_HEADER(WebKit, AuthenticationServicesCore, ASCPINValidationResultKey, NSString*);
45
#define ASCPINValidationResultKey WebKit::get_AuthenticationServicesCore_ASCPINValidationResultKey()
46
41
#endif // HAVE(ASC_AUTH_UI)
47
#endif // HAVE(ASC_AUTH_UI)
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticationServicesCoreSoftLink.mm +3 lines
Lines 38-41 SOFT_LINK_CLASS_FOR_SOURCE(WebKit, AuthenticationServicesCore, ASCPlatformPublic a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticationServicesCoreSoftLink.mm_sec1
38
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, AuthenticationServicesCore, ASCSecurityKeyPublicKeyCredentialLoginChoice);
38
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, AuthenticationServicesCore, ASCSecurityKeyPublicKeyCredentialLoginChoice);
39
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, AuthenticationServicesCore, ASCAppleIDCredential);
39
SOFT_LINK_CLASS_FOR_SOURCE(WebKit, AuthenticationServicesCore, ASCAppleIDCredential);
40
40
41
SOFT_LINK_CONSTANT_FOR_SOURCE(WebKit, AuthenticationServicesCore, ASCAuthorizationErrorDomain, NSErrorDomain);
42
SOFT_LINK_CONSTANT_FOR_SOURCE(WebKit, AuthenticationServicesCore, ASCPINValidationResultKey, NSString*);
43
41
#endif // HAVE(ASC_AUTH_UI)
44
#endif // HAVE(ASC_AUTH_UI)
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.h -2 / +6 lines
Lines 35-44 a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.h_sec1
35
#include <wtf/RetainPtr.h>
35
#include <wtf/RetainPtr.h>
36
#include <wtf/WeakPtr.h>
36
#include <wtf/WeakPtr.h>
37
37
38
OBJC_CLASS ASCAppleIDCredential;
38
OBJC_CLASS ASCAuthorizationPresentationContext;
39
OBJC_CLASS ASCAuthorizationPresentationContext;
39
OBJC_CLASS ASCAuthorizationPresenter;
40
OBJC_CLASS ASCAuthorizationPresenter;
40
OBJC_CLASS ASCLoginChoiceProtocol;
41
OBJC_CLASS ASCLoginChoiceProtocol;
41
OBJC_CLASS LAContext;
42
OBJC_CLASS LAContext;
43
OBJC_CLASS NSError;
42
OBJC_CLASS WKASCAuthorizationPresenterDelegate;
44
OBJC_CLASS WKASCAuthorizationPresenterDelegate;
43
45
44
namespace WebKit {
46
namespace WebKit {
Lines 50-56 class AuthenticatorPresenterCoordinator : public CanMakeWeakPtr<AuthenticatorPre a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.h_sec2
50
    WTF_MAKE_NONCOPYABLE(AuthenticatorPresenterCoordinator);
52
    WTF_MAKE_NONCOPYABLE(AuthenticatorPresenterCoordinator);
51
public:
53
public:
52
    using TransportSet = HashSet<WebCore::AuthenticatorTransport, WTF::IntHash<WebCore::AuthenticatorTransport>, WTF::StrongEnumHashTraits<WebCore::AuthenticatorTransport>>;
54
    using TransportSet = HashSet<WebCore::AuthenticatorTransport, WTF::IntHash<WebCore::AuthenticatorTransport>, WTF::StrongEnumHashTraits<WebCore::AuthenticatorTransport>>;
53
    using CredentialRequestHandler = Function<void()>;
55
    using CredentialRequestHandler = Function<void(ASCAppleIDCredential *, NSError *)>;
54
56
55
    AuthenticatorPresenterCoordinator(const AuthenticatorManager&, const String& rpId, const TransportSet&, WebCore::ClientDataType);
57
    AuthenticatorPresenterCoordinator(const AuthenticatorManager&, const String& rpId, const TransportSet&, WebCore::ClientDataType);
56
    ~AuthenticatorPresenterCoordinator();
58
    ~AuthenticatorPresenterCoordinator();
Lines 63-70 public: a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.h_sec3
63
65
64
    void setCredentialRequestHandler(CredentialRequestHandler&& handler) { m_credentialRequestHandler = WTFMove(handler); }
66
    void setCredentialRequestHandler(CredentialRequestHandler&& handler) { m_credentialRequestHandler = WTFMove(handler); }
65
    void setLAContext(LAContext *);
67
    void setLAContext(LAContext *);
66
67
    void didSelectAssertionResponse(ASCLoginChoiceProtocol *, LAContext *);
68
    void didSelectAssertionResponse(ASCLoginChoiceProtocol *, LAContext *);
69
    void setPin(const String&);
68
70
69
private:
71
private:
70
    WeakPtr<AuthenticatorManager> m_manager;
72
    WeakPtr<AuthenticatorManager> m_manager;
Lines 79-84 private: a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.h_sec4
79
81
80
    CompletionHandler<void(WebCore::AuthenticatorAssertionResponse*)> m_responseHandler;
82
    CompletionHandler<void(WebCore::AuthenticatorAssertionResponse*)> m_responseHandler;
81
    HashMap<ASCLoginChoiceProtocol *, RefPtr<WebCore::AuthenticatorAssertionResponse>> m_credentials;
83
    HashMap<ASCLoginChoiceProtocol *, RefPtr<WebCore::AuthenticatorAssertionResponse>> m_credentials;
84
85
    CompletionHandler<void(const String&)> m_pinHandler;
82
};
86
};
83
87
84
} // namespace WebKit
88
} // namespace WebKit
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.mm -6 / +36 lines
Lines 86-101 AuthenticatorPresenterCoordinator::~AuthenticatorPresenterCoordinator() a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.mm_sec1
86
        m_laContextHandler(nullptr);
86
        m_laContextHandler(nullptr);
87
    if (m_responseHandler)
87
    if (m_responseHandler)
88
        m_responseHandler(nullptr);
88
        m_responseHandler(nullptr);
89
    if (m_pinHandler)
90
        m_pinHandler(String());
89
}
91
}
90
92
91
void AuthenticatorPresenterCoordinator::updatePresenter(WebAuthenticationStatus)
93
void AuthenticatorPresenterCoordinator::updatePresenter(WebAuthenticationStatus status)
92
{
94
{
93
    // FIXME(219713): Adopt new UI for the update flow.
95
    switch (status) {
96
    case WebAuthenticationStatus::PinBlocked: {
97
        auto error = adoptNS([[NSError alloc] initWithDomain:ASCAuthorizationErrorDomain code:ASCAuthorizationErrorPINRequired userInfo:@{ ASCPINValidationResultKey: @(ASCPINValidationResultPINBlocked) }]);
98
        m_credentialRequestHandler(nil, error.get());
99
        break;
100
    }
101
    case WebAuthenticationStatus::PinAuthBlocked: {
102
        auto error = adoptNS([[NSError alloc] initWithDomain:ASCAuthorizationErrorDomain code:ASCAuthorizationErrorPINRequired userInfo:@{ ASCPINValidationResultKey: @(ASCPINValidationResultPINAuthBlocked) }]);
103
        m_credentialRequestHandler(nil, error.get());
104
        break;
105
    }
106
    case WebAuthenticationStatus::PinInvalid: {
107
        auto error = adoptNS([[NSError alloc] initWithDomain:ASCAuthorizationErrorDomain code:ASCAuthorizationErrorPINRequired userInfo:@{ ASCPINValidationResultKey: @(ASCPINValidationResultPINInvalid) }]);
108
        m_credentialRequestHandler(nil, error.get());
109
        break;
110
    }
111
    default:
112
        // FIXME(219713): Adopt new UI for the update flow.
113
        break;
114
    }
94
}
115
}
95
116
96
void AuthenticatorPresenterCoordinator::requestPin(uint64_t, CompletionHandler<void(const String&)>&&)
117
void AuthenticatorPresenterCoordinator::requestPin(uint64_t, CompletionHandler<void(const String&)>&& completionHandler)
97
{
118
{
98
    // FIXME(219712): Adopt new UI for the Client PIN flow.
119
    m_pinHandler = WTFMove(completionHandler);
120
    [m_presenter presentPINEntryInterface];
99
}
121
}
100
122
101
void AuthenticatorPresenterCoordinator::selectAssertionResponse(Vector<Ref<AuthenticatorAssertionResponse>>&& responses, WebAuthenticationSource source, CompletionHandler<void(AuthenticatorAssertionResponse*)>&& completionHandler)
123
void AuthenticatorPresenterCoordinator::selectAssertionResponse(Vector<Ref<AuthenticatorAssertionResponse>>&& responses, WebAuthenticationSource source, CompletionHandler<void(AuthenticatorAssertionResponse*)>&& completionHandler)
Lines 157-166 void AuthenticatorPresenterCoordinator::requestLAContextForUserVerification(Comp a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.mm_sec2
157
void AuthenticatorPresenterCoordinator::dimissPresenter(WebAuthenticationResult result)
179
void AuthenticatorPresenterCoordinator::dimissPresenter(WebAuthenticationResult result)
158
{
180
{
159
    if (result == WebAuthenticationResult::Succeeded && m_credentialRequestHandler) {
181
    if (result == WebAuthenticationResult::Succeeded && m_credentialRequestHandler) {
160
        m_credentialRequestHandler();
182
        // FIXME(219767): Replace the ASCAppleIDCredential with the upcoming WebAuthn credentials one.
183
        // This is just a place holder to tell the UI that the ceremony succeeds.
184
        m_credentialRequestHandler(adoptNS([WebKit::allocASCAppleIDCredentialInstance() initWithUser:@"" identityToken:adoptNS([[NSData alloc] init]).get()]).get(), nil);
161
        return;
185
        return;
162
    }
186
    }
163
    // FIXME(219716): Adopt new UI for the dismiss flow.
187
188
    [m_presenter dismissWithError:nil];
164
}
189
}
165
190
166
void AuthenticatorPresenterCoordinator::setLAContext(LAContext *context)
191
void AuthenticatorPresenterCoordinator::setLAContext(LAContext *context)
Lines 185-190 void AuthenticatorPresenterCoordinator::didSelectAssertionResponse(ASCLoginChoic a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/AuthenticatorPresenterCoordinator.mm_sec3
185
    m_responseHandler(response.get());
210
    m_responseHandler(response.get());
186
}
211
}
187
212
213
void AuthenticatorPresenterCoordinator::setPin(const String& pin)
214
{
215
    m_pinHandler(pin);
216
}
217
188
} // namespace WebKit
218
} // namespace WebKit
189
219
190
#endif // ENABLE(WEB_AUTHN)
220
#endif // ENABLE(WEB_AUTHN)
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm -1 / +1 lines
Lines 118-124 void NfcService::platformStartDiscovery() a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/NfcService.mm_sec1
118
            m_connection = NfcConnection::create(WTFMove(session), *this);
118
            m_connection = NfcConnection::create(WTFMove(session), *this);
119
        });
119
        });
120
    });
120
    });
121
    [[getNFHardwareManagerClass() sharedHardwareManager] startReaderSession:callback.get()];
121
    [[getNFHardwareManagerClass() sharedHardwareManagerWithNoUI] startReaderSession:callback.get()];
122
#endif // HAVE(NEAR_FIELD)
122
#endif // HAVE(NEAR_FIELD)
123
}
123
}
124
124
- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WKASCAuthorizationPresenterDelegate.mm -5 / +13 lines
Lines 47-56 - (instancetype)initWithCoordinator:(WebKit::AuthenticatorPresenterCoordinator&) a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WKASCAuthorizationPresenterDelegate.mm_sec1
47
47
48
- (void)authorizationPresenter:(ASCAuthorizationPresenter *)presenter credentialRequestedForLoginChoice:(id <ASCLoginChoiceProtocol>)loginChoice authenticatedContext:(nullable LAContext *)context completionHandler:(void (^)(id <ASCCredentialProtocol> _Nullable credential, NSError * _Nullable error))completionHandler
48
- (void)authorizationPresenter:(ASCAuthorizationPresenter *)presenter credentialRequestedForLoginChoice:(id <ASCLoginChoiceProtocol>)loginChoice authenticatedContext:(nullable LAContext *)context completionHandler:(void (^)(id <ASCCredentialProtocol> _Nullable credential, NSError * _Nullable error))completionHandler
49
{
49
{
50
    auto requestHandler = [completionHandler = makeBlockPtr(completionHandler)] {
50
    auto requestHandler = [completionHandler = makeBlockPtr(completionHandler)] (ASCAppleIDCredential *credential, NSError *error) {
51
        // FIXME(219767): Replace the ASCAppleIDCredential with the upcoming WebAuthn credentials one.
51
        completionHandler(credential, error);
52
        // This is just a place holder to tell the UI that the ceremony succeeds.
53
        completionHandler(adoptNS([WebKit::allocASCAppleIDCredentialInstance() initWithUser:@"" identityToken:adoptNS([[NSData alloc] init]).get()]).get(), nil);
54
    };
52
    };
55
    [self dispatchCoordinatorCallback:[requestHandler = WTFMove(requestHandler)] (WebKit::AuthenticatorPresenterCoordinator& coordinator) mutable {
53
    [self dispatchCoordinatorCallback:[requestHandler = WTFMove(requestHandler)] (WebKit::AuthenticatorPresenterCoordinator& coordinator) mutable {
56
        coordinator.setCredentialRequestHandler(WTFMove(requestHandler));
54
        coordinator.setCredentialRequestHandler(WTFMove(requestHandler));
Lines 87-93 - (void)authorizationPresenter:(ASCAuthorizationPresenter *)presenter credential a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WKASCAuthorizationPresenterDelegate.mm_sec2
87
85
88
- (void)authorizationPresenter:(ASCAuthorizationPresenter *)presenter validateUserEnteredPIN:(NSString *)pin completionHandler:(void (^)(id <ASCCredentialProtocol> credential, NSError *error))completionHandler
86
- (void)authorizationPresenter:(ASCAuthorizationPresenter *)presenter validateUserEnteredPIN:(NSString *)pin completionHandler:(void (^)(id <ASCCredentialProtocol> credential, NSError *error))completionHandler
89
{
87
{
90
    // FIXME(219712): Adopt new UI for the Client PIN flow.
88
    auto requestHandler = [completionHandler = makeBlockPtr(completionHandler)] (ASCAppleIDCredential *credential, NSError *error) {
89
        completionHandler(credential, error);
90
    };
91
    [self dispatchCoordinatorCallback:[requestHandler = WTFMove(requestHandler)] (WebKit::AuthenticatorPresenterCoordinator& coordinator) mutable {
92
        coordinator.setCredentialRequestHandler(WTFMove(requestHandler));
93
    }];
94
95
    String pinString = pin;
96
    [self dispatchCoordinatorCallback:[pinString = WTFMove(pinString)] (WebKit::AuthenticatorPresenterCoordinator& coordinator) mutable {
97
        coordinator.setPin(pinString);
98
    }];
91
}
99
}
92
100
93
- (void)dispatchCoordinatorCallback:(Function<void(WebKit::AuthenticatorPresenterCoordinator&)>&&)callback
101
- (void)dispatchCoordinatorCallback:(Function<void(WebKit::AuthenticatorPresenterCoordinator&)>&&)callback

Return to Bug 219712