Skip to content

Commit

Permalink
Pass along clientDataJSON in legacy flow
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=270111
rdar://123457653

Reviewed by Brent Fulgham.

We started passing along the raw clientDataJSON in the modern flow. We need to do
the same in the legacy flow to keep it working since we don't use clientDataHash anymore.

* Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h:
* Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm:
(WebKit::configureRegistrationRequestContext):
(WebKit::configureAssertionOptions):
(WebKit::configurationAssertionRequestContext):
(WebKit::WebAuthenticatorCoordinatorProxy::contextForRequest):
(WebKit::continueAfterRequest):

Canonical link: https://commits.webkit.org/275345@main
  • Loading branch information
Pascoe committed Feb 26, 2024
1 parent 2dd0e81 commit 21dc5d5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,14 @@ typedef NS_ENUM(NSUInteger, ASCPublicKeyCredentialKind) {

- (instancetype)initWithKind:(ASCPublicKeyCredentialKind)credentialKind relyingPartyIdentifier:(NSString *)relyingPartyIdentifier clientDataHash:(NSData *)clientDataHash userVerificationPreference:(nullable NSString *)userVerificationPreference allowedCredentials:(nullable NSArray<ASCPublicKeyCredentialDescriptor *> *)allowedCredentials;

- (instancetype)initWithKind:(ASCPublicKeyCredentialKind)credentialKind relyingPartyIdentifier:(NSString *)relyingPartyIdentifier clientDataJSON:(NSData *)clientDataJSON userVerificationPreference:(nullable NSString *)userVerificationPreference allowedCredentials:(nullable NSArray<ASCPublicKeyCredentialDescriptor *> *)allowedCredentials;

@property (nonatomic, readonly) ASCPublicKeyCredentialKind credentialKind;
@property (nonatomic, copy, readonly) NSString *relyingPartyIdentifier;
// There should always be exactly one of these set.
@property (nonatomic, nullable, copy, readonly) NSData *challenge;
// If clientDataHash is null, then gets generated from challenge and relyingPartyIdentifier.
@property (nonatomic, nullable, copy) NSData *clientDataHash;
@property (nonatomic, nullable, copy) NSData *clientDataJSON;
@property (nonatomic, nullable, readonly, copy) NSString *userVerificationPreference;
@property (nonatomic, nullable, copy) ASCWebAuthenticationExtensionsClientInputs *extensions;
@property (nonatomic, nullable, copy) NSData *extensionsCBOR;
Expand Down Expand Up @@ -193,6 +196,7 @@ typedef NS_ENUM(NSInteger, ASPublicKeyCredentialResidentKeyPreference) {

@property (nonatomic, nullable, copy) NSData *challenge;
@property (nonatomic, nullable, copy) NSData *clientDataHash;
@property (nonatomic, nullable, copy) NSData *clientDataJSON;
@property (nonatomic, copy) NSString *relyingPartyIdentifier;
@property (nonatomic, copy) NSString *userName;
@property (nonatomic, copy) NSData *userIdentifier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#import <WebCore/PublicKeyCredentialCreationOptions.h>
#import <WebCore/RegistrableDomain.h>
#import <WebCore/SecurityOrigin.h>
#import <WebCore/WebAuthenticationUtils.h>
#import <wtf/BlockPtr.h>
#import <wtf/CompletionHandler.h>
#import <wtf/EnumTraits.h>
Expand Down Expand Up @@ -604,7 +605,7 @@ static inline ASPublicKeyCredentialResidentKeyPreference toASCResidentKeyPrefere
return ASPublicKeyCredentialResidentKeyPreferenceNotPresent;
}

static RetainPtr<ASCCredentialRequestContext> configureRegistrationRequestContext(const PublicKeyCredentialCreationOptions& options, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID, std::optional<WebCore::MediationRequirement> mediation)
static RetainPtr<ASCCredentialRequestContext> configureRegistrationRequestContext(const PublicKeyCredentialCreationOptions& options, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID, std::optional<WebCore::MediationRequirement> mediation, const WebCore::SecurityOriginData& callerOrigin)
{
ASCCredentialRequestTypes requestTypes = ASCCredentialRequestTypePlatformPublicKeyRegistration | ASCCredentialRequestTypeSecurityKeyPublicKeyRegistration;

Expand Down Expand Up @@ -634,7 +635,10 @@ static inline ASPublicKeyCredentialResidentKeyPreference toASCResidentKeyPrefere

auto credentialCreationOptions = adoptNS([allocASCPublicKeyCredentialCreationOptionsInstance() init]);

[credentialCreationOptions setChallenge:WebCore::toNSData(options.challenge).get()];
auto clientDataJson = WebCore::buildClientDataJson(ClientDataType::Create, options.challenge, callerOrigin.securityOrigin(), WebAuthn::Scope::SameOrigin);
RetainPtr nsClientDataJSON = adoptNS([[NSData alloc] initWithBytes:clientDataJson->data() length:clientDataJson->byteLength()]);
[credentialCreationOptions setClientDataJSON:nsClientDataJSON.get()];

[credentialCreationOptions setRelyingPartyIdentifier:*options.rp.id];
[credentialCreationOptions setUserName:options.user.name];
[credentialCreationOptions setUserIdentifier:WebCore::toNSData(options.user.id).get()];
Expand Down Expand Up @@ -684,11 +688,15 @@ static inline ASPublicKeyCredentialResidentKeyPreference toASCResidentKeyPrefere
return requestContext;
}

static inline RetainPtr<ASCPublicKeyCredentialAssertionOptions> configureAssertionOptions(const PublicKeyCredentialRequestOptions& options, ASCPublicKeyCredentialKind kind, const std::optional<SecurityOriginData>& parentOrigin, RetainPtr<NSMutableArray<ASCPublicKeyCredentialDescriptor *>> allowedCredentials, RetainPtr<NSString> userVerification)
static inline RetainPtr<ASCPublicKeyCredentialAssertionOptions> configureAssertionOptions(const PublicKeyCredentialRequestOptions& options, ASCPublicKeyCredentialKind kind, const std::optional<SecurityOriginData>& parentOrigin, RetainPtr<NSMutableArray<ASCPublicKeyCredentialDescriptor *>> allowedCredentials, RetainPtr<NSString> userVerification, const WebCore::SecurityOriginData& callerOrigin)
{
auto assertionOptions = adoptNS(allocASCPublicKeyCredentialAssertionOptionsInstance());
RetainPtr challenge = WebCore::toNSData(options.challenge);
[assertionOptions initWithKind:kind relyingPartyIdentifier:options.rpId challenge:challenge.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
// AS API makes no difference between SameSite vs CrossOrigin
auto scope = parentOrigin ? WebAuthn::Scope::CrossOrigin : WebAuthn::Scope::SameOrigin;
auto topOrigin = parentOrigin ? parentOrigin->toString() : nullString();
auto clientDataJson = WebCore::buildClientDataJson(ClientDataType::Get, options.challenge, callerOrigin.securityOrigin(), scope, topOrigin);
RetainPtr nsClientDataJSON = adoptNS([[NSData alloc] initWithBytes:clientDataJson->data() length:clientDataJson->byteLength()]);
[assertionOptions initWithKind:kind relyingPartyIdentifier:options.rpId clientDataJSON:nsClientDataJSON.get() userVerificationPreference:userVerification.get() allowedCredentials:allowedCredentials.get()];
if (options.extensions) {
if ([assertionOptions respondsToSelector:@selector(setExtensionsCBOR:)])
[assertionOptions setExtensionsCBOR:toNSData(options.extensions->toCBOR()).get()];
Expand All @@ -704,7 +712,7 @@ static inline ASPublicKeyCredentialResidentKeyPreference toASCResidentKeyPrefere
return assertionOptions;
}

static RetainPtr<ASCCredentialRequestContext> configurationAssertionRequestContext(const PublicKeyCredentialRequestOptions& options, std::optional<WebCore::MediationRequirement> mediation, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID, std::optional<WebCore::SecurityOriginData>& parentOrigin)
static RetainPtr<ASCCredentialRequestContext> configurationAssertionRequestContext(const PublicKeyCredentialRequestOptions& options, std::optional<WebCore::MediationRequirement> mediation, std::optional<WebCore::GlobalFrameIdentifier> globalFrameID, std::optional<WebCore::SecurityOriginData>& parentOrigin, const WebCore::SecurityOriginData& callerOrigin)
{
ASCCredentialRequestTypes requestTypes = ASCCredentialRequestTypePlatformPublicKeyAssertion | ASCCredentialRequestTypeSecurityKeyPublicKeyAssertion;

Expand Down Expand Up @@ -736,14 +744,14 @@ static inline ASPublicKeyCredentialResidentKeyPreference toASCResidentKeyPrefere
setGlobalFrameIDForContext(requestContext, globalFrameID);

if (requestTypes & ASCCredentialRequestTypePlatformPublicKeyAssertion) {
RetainPtr assertionOptions = configureAssertionOptions(options, ASCPublicKeyCredentialKindPlatform, parentOrigin, allowedCredentials, userVerification);
RetainPtr assertionOptions = configureAssertionOptions(options, ASCPublicKeyCredentialKindPlatform, parentOrigin, allowedCredentials, userVerification, callerOrigin);
if (!assertionOptions)
return nil;
[requestContext setPlatformKeyCredentialAssertionOptions:assertionOptions.get()];
}

if (requestTypes & ASCCredentialRequestTypeSecurityKeyPublicKeyAssertion) {
RetainPtr assertionOptions = configureAssertionOptions(options, ASCPublicKeyCredentialKindSecurityKey, parentOrigin, allowedCredentials, userVerification);
RetainPtr assertionOptions = configureAssertionOptions(options, ASCPublicKeyCredentialKindSecurityKey, parentOrigin, allowedCredentials, userVerification, callerOrigin);
if (!assertionOptions)
return nil;
[requestContext setSecurityKeyCredentialAssertionOptions:assertionOptions.get()];
Expand Down Expand Up @@ -779,9 +787,9 @@ static inline ASPublicKeyCredentialResidentKeyPreference toASCResidentKeyPrefere
{
RetainPtr<ASCCredentialRequestContext> result;
WTF::switchOn(requestData.options, [&](const PublicKeyCredentialCreationOptions& options) {
result = configureRegistrationRequestContext(options, requestData.globalFrameID, requestData.mediation);
result = configureRegistrationRequestContext(options, requestData.globalFrameID, requestData.mediation, requestData.frameInfo.securityOrigin);
}, [&](const PublicKeyCredentialRequestOptions& options) {
result = configurationAssertionRequestContext(options, requestData.mediation, requestData.globalFrameID, requestData.parentOrigin);
result = configurationAssertionRequestContext(options, requestData.mediation, requestData.globalFrameID, requestData.parentOrigin, requestData.frameInfo.securityOrigin);
});
return result;
}
Expand All @@ -798,6 +806,7 @@ static inline void continueAfterRequest(RetainPtr<id <ASCCredentialProtocol>> cr
ASCPlatformPublicKeyCredentialRegistration *registrationCredential = credential.get();
response.rawId = toArrayBuffer(registrationCredential.credentialID);
response.attestationObject = toArrayBuffer(registrationCredential.attestationObject);
response.clientDataJSON = toArrayBuffer(registrationCredential.rawClientDataJSON);
rawAttachment = registrationCredential.attachment;
if ([registrationCredential respondsToSelector:@selector(transports)])
response.transports = toAuthenticatorTransports(registrationCredential.transports);
Expand All @@ -809,6 +818,7 @@ static inline void continueAfterRequest(RetainPtr<id <ASCCredentialProtocol>> cr
ASCSecurityKeyPublicKeyCredentialRegistration *registrationCredential = credential.get();
response.rawId = toArrayBuffer(registrationCredential.credentialID);
response.attestationObject = toArrayBuffer(registrationCredential.attestationObject);
response.clientDataJSON = toArrayBuffer(registrationCredential.rawClientDataJSON);
rawAttachment = registrationCredential.attachment;
if ([registrationCredential respondsToSelector:@selector(transports)])
response.transports = toAuthenticatorTransports(registrationCredential.transports);
Expand All @@ -822,6 +832,7 @@ static inline void continueAfterRequest(RetainPtr<id <ASCCredentialProtocol>> cr
response.authenticatorData = toArrayBuffer(assertionCredential.authenticatorData);
response.signature = toArrayBuffer(assertionCredential.signature);
response.userHandle = toArrayBuffer(assertionCredential.userHandle);
response.clientDataJSON = toArrayBuffer(assertionCredential.rawClientDataJSON);
rawAttachment = assertionCredential.attachment;
if ([assertionCredential respondsToSelector:@selector(extensionOutputsCBOR)])
response.extensionOutputs = toExtensionOutputs(assertionCredential.extensionOutputsCBOR);
Expand All @@ -833,6 +844,7 @@ static inline void continueAfterRequest(RetainPtr<id <ASCCredentialProtocol>> cr
response.authenticatorData = toArrayBuffer(assertionCredential.authenticatorData);
response.signature = toArrayBuffer(assertionCredential.signature);
response.userHandle = toArrayBuffer(assertionCredential.userHandle);
response.clientDataJSON = toArrayBuffer(assertionCredential.rawClientDataJSON);
rawAttachment = assertionCredential.attachment;
if ([assertionCredential respondsToSelector:@selector(extensionOutputsCBOR)])
response.extensionOutputs = toExtensionOutputs(assertionCredential.extensionOutputsCBOR);
Expand Down

0 comments on commit 21dc5d5

Please sign in to comment.