Changeset 243193 in webkit
- Timestamp:
- Mar 19, 2019 11:11:57 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 40 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r243182 r243193 1 2019-03-19 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Implement FIDO AppID extension 4 https://bugs.webkit.org/show_bug.cgi?id=143491 5 <rdar://problem/48298273> 6 7 Reviewed by Brent Fulgham. 8 9 * http/wpt/webauthn/public-key-credential-create-success-hid.https.html: 10 * http/wpt/webauthn/public-key-credential-create-success-local.https.html: 11 * http/wpt/webauthn/public-key-credential-create-success-u2f.https.html: 12 * http/wpt/webauthn/public-key-credential-get-failure-u2f.https-expected.txt: 13 * http/wpt/webauthn/public-key-credential-get-failure-u2f.https.html: 14 * http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt: 15 * http/wpt/webauthn/public-key-credential-get-failure.https.html: 16 * http/wpt/webauthn/public-key-credential-get-success-hid.https.html: 17 * http/wpt/webauthn/public-key-credential-get-success-local.https.html: 18 * http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt: 19 * http/wpt/webauthn/public-key-credential-get-success-u2f.https.html: 20 1 21 2019-03-19 Ryosuke Niwa <rniwa@webkit.org> 2 22 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html
r239958 r243193 17 17 assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testHidCredentialIdBase64)); 18 18 assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}'); 19 assert_ throws("NotSupportedError", () => { credential.getClientExtensionResults() });19 assert_not_exists(credential.getClientExtensionResults(), "appid"); 20 20 21 21 // Check attestation -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html
r239471 r243193 31 31 assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testCredentialIdBase64)); 32 32 assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}'); 33 assert_ throws("NotSupportedError", () => { credential.getClientExtensionResults() });33 assert_not_exists(credential.getClientExtensionResults(), "appid"); 34 34 35 35 // Check attestation -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-u2f.https.html
r239958 r243193 13 13 assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testU2fCredentialIdBase64)); 14 14 assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.create","challenge":"MTIzNDU2","origin":"https://localhost:9443"}'); 15 assert_ throws("NotSupportedError", () => { credential.getClientExtensionResults() });15 assert_not_exists(credential.getClientExtensionResults(), "appid"); 16 16 17 17 // Check attestation -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-u2f.https-expected.txt
r239752 r243193 3 3 PASS PublicKeyCredential's [[get]] with no matched allow credentials in a mock hid authenticator. 4 4 PASS PublicKeyCredential's [[get]] with no matched allow credentials in a mock hid authenticator. 2 5 PASS PublicKeyCredential's [[get]] with no matched allow credentials in a mock hid authenticator. (AppID) 6 PASS PublicKeyCredential's [[get]] with no matched allow credentials in a mock hid authenticator. 2 (AppID) 5 7 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-u2f.https.html
r239752 r243193 43 43 return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "No credentials from the allowCredentials list is found in the authenticator."); 44 44 }, "PublicKeyCredential's [[get]] with no matched allow credentials in a mock hid authenticator. 2"); 45 46 // With AppID extension 47 promise_test(function(t) { 48 const options = { 49 publicKey: { 50 challenge: asciiToUint8Array("123456"), 51 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testCredentialIdBase64) }], 52 extensions: { appid: "" } 53 } 54 }; 55 56 if (window.testRunner) 57 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64] } }); 58 return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "No credentials from the allowCredentials list is found in the authenticator."); 59 }, "PublicKeyCredential's [[get]] with no matched allow credentials in a mock hid authenticator. (AppID)"); 60 61 promise_test(function(t) { 62 const options = { 63 publicKey: { 64 challenge: asciiToUint8Array("123456"), 65 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testCredentialIdBase64) }, { type: "public-key", id: Base64URL.parse(testCredentialIdBase64) }], 66 extensions: { appid: "" } 67 } 68 }; 69 70 if (window.testRunner) 71 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64] } }); 72 return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "No credentials from the allowCredentials list is found in the authenticator."); 73 }, "PublicKeyCredential's [[get]] with no matched allow credentials in a mock hid authenticator. 2 (AppID)"); 45 74 </script> -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https-expected.txt
r236842 r243193 2 2 PASS PublicKeyCredential's [[get]] with timeout 3 3 PASS PublicKeyCredential's [[get]] with a mismatched RP ID 4 PASS PublicKeyCredential's [[get]] with a mismatched APP ID (invalid URLs) 5 PASS PublicKeyCredential's [[get]] with a mismatched APP ID (different protocols) 6 PASS PublicKeyCredential's [[get]] with a mismatched APP ID (different sites 1) 7 PASS PublicKeyCredential's [[get]] with a mismatched APP ID (different sites 2) 4 8 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure.https.html
r236842 r243193 32 32 navigator.credentials.get(options), "The origin of the document is not a registrable domain suffix of the provided RP ID."); 33 33 }, "PublicKeyCredential's [[get]] with a mismatched RP ID"); 34 35 promise_test(t => { 36 const options = { 37 publicKey: { 38 challenge: asciiToUint8Array("123456"), 39 extensions: { appid: "abc" } 40 } 41 }; 42 43 return promiseRejects(t, "SecurityError", 44 navigator.credentials.get(options), "The origin of the document is not authorized for the provided App ID."); 45 }, "PublicKeyCredential's [[get]] with a mismatched APP ID (invalid URLs)"); 46 47 promise_test(t => { 48 const options = { 49 publicKey: { 50 challenge: asciiToUint8Array("123456"), 51 extensions: { appid: "ftp://localhost" } 52 } 53 }; 54 55 return promiseRejects(t, "SecurityError", 56 navigator.credentials.get(options), "The origin of the document is not authorized for the provided App ID."); 57 }, "PublicKeyCredential's [[get]] with a mismatched APP ID (different protocols)"); 58 59 promise_test(t => { 60 const options = { 61 publicKey: { 62 challenge: asciiToUint8Array("123456"), 63 extensions: { appid: "https://127.0.0.1" } 64 } 65 }; 66 67 return promiseRejects(t, "SecurityError", 68 navigator.credentials.get(options), "The origin of the document is not authorized for the provided App ID."); 69 }, "PublicKeyCredential's [[get]] with a mismatched APP ID (different sites 1)"); 70 71 promise_test(t => { 72 const options = { 73 publicKey: { 74 challenge: asciiToUint8Array("123456"), 75 extensions: { appid: "https://haha.localhost" } 76 } 77 }; 78 79 return promiseRejects(t, "SecurityError", 80 navigator.credentials.get(options), "The origin of the document is not authorized for the provided App ID."); 81 }, "PublicKeyCredential's [[get]] with a mismatched APP ID (different sites 2)"); 34 82 </script> -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html
r239958 r243193 17 17 assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}'); 18 18 assert_equals(credential.response.userHandle, null); 19 assert_not_exists(credential.getClientExtensionResults(), "appid"); 19 20 20 21 // Check authData -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-local.https.html
r239471 r243193 20 20 assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}'); 21 21 assert_equals(bytesToHexString(credential.response.userHandle), "00010203040506070809"); 22 assert_not_exists(credential.getClientExtensionResults(), "appid"); 22 23 23 24 // Check authData … … 33 34 return crypto.subtle.verify({name: "ECDSA", hash: "SHA-256"}, publicKey, extractRawSignature(credential.response.signature), concatenateBuffers(credential.response.authenticatorData, hash)).then( verified => { 34 35 assert_true(verified); 35 assert_ throws("NotSupportedError", () => { credential.getClientExtensionResults() });36 assert_not_exists(credential.getClientExtensionResults(), "appid"); 36 37 }); 37 38 }); -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt
r239752 r243193 3 3 PASS PublicKeyCredential's [[get]] with more allow credentials in a mock hid authenticator. 4 4 PASS PublicKeyCredential's [[get]] with test of user presence in a mock hid authenticator. 5 PASS PublicKeyCredential's [[get]] with empty extensions in a mock hid authenticator. 6 PASS PublicKeyCredential's [[get]] with same site AppID but not used in a mock hid authenticator. 7 PASS PublicKeyCredential's [[get]] with empty AppID in a mock hid authenticator. 8 PASS PublicKeyCredential's [[get]] with an AppID in a mock hid authenticator. 9 PASS PublicKeyCredential's [[get]] with multiple credentials and AppID is not used in a mock hid authenticator. 10 PASS PublicKeyCredential's [[get]] with multiple credentials and AppID is used in a mock hid authenticator. 5 11 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https.html
r239958 r243193 5 5 <script src="./resources/util.js"></script> 6 6 <script> 7 function checkResult(credential) 7 const defaultAppIDHash = "c2671b6eb9233197d5f2b1288a55ba4f0860f96f7199bba32fe6da7c3f0f31e5"; 8 9 function checkResult(credential, isAppID = false, appIDHash = defaultAppIDHash) 8 10 { 9 11 // Check respond … … 13 15 assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}'); 14 16 assert_equals(credential.response.userHandle, null); 17 if (!isAppID) 18 assert_not_exists(credential.getClientExtensionResults(), "appid"); 19 else 20 assert_true(credential.getClientExtensionResults().appid); 15 21 16 22 // Check authData 17 23 const authData = decodeAuthData(new Uint8Array(credential.response.authenticatorData)); 18 assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763"); 24 if (!isAppID) 25 assert_equals(bytesToHexString(authData.rpIdHash), "49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763"); 26 else 27 assert_equals(bytesToHexString(authData.rpIdHash), appIDHash); 19 28 assert_equals(authData.flags, 1); 20 29 assert_equals(authData.counter, 59); … … 68 77 }); 69 78 }, "PublicKeyCredential's [[get]] with test of user presence in a mock hid authenticator."); 79 80 // With AppID extension 81 promise_test(t => { 82 const options = { 83 publicKey: { 84 challenge: Base64URL.parse("MTIzNDU2"), 85 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 86 timeout: 100, 87 extensions: { } 88 } 89 }; 90 91 if (window.testRunner) 92 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fSignResponse] } }); 93 return navigator.credentials.get(options).then(credential => { 94 return checkResult(credential); 95 }); 96 }, "PublicKeyCredential's [[get]] with empty extensions in a mock hid authenticator."); 97 98 promise_test(t => { 99 const options = { 100 publicKey: { 101 challenge: Base64URL.parse("MTIzNDU2"), 102 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 103 timeout: 100, 104 extensions: { appid: "https://localhost:666/appid" } 105 } 106 }; 107 108 if (window.testRunner) 109 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fSignResponse] } }); 110 return navigator.credentials.get(options).then(credential => { 111 return checkResult(credential); 112 }); 113 }, "PublicKeyCredential's [[get]] with same site AppID but not used in a mock hid authenticator."); 114 115 promise_test(t => { 116 const options = { 117 publicKey: { 118 challenge: Base64URL.parse("MTIzNDU2"), 119 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 120 timeout: 100, 121 extensions: { appid: "" } 122 } 123 }; 124 125 if (window.testRunner) 126 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } }); 127 return navigator.credentials.get(options).then(credential => { 128 return checkResult(credential, true); 129 }); 130 }, "PublicKeyCredential's [[get]] with empty AppID in a mock hid authenticator."); 131 132 // FIXME: Sub domains need to be tested as well. However, localhost has no sub domains. 133 promise_test(t => { 134 const options = { 135 publicKey: { 136 challenge: Base64URL.parse("MTIzNDU2"), 137 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 138 timeout: 100, 139 extensions: { appid: "https://localhost:666/appid" } 140 } 141 }; 142 143 if (window.testRunner) 144 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } }); 145 return navigator.credentials.get(options).then(credential => { 146 return checkResult(credential, true, "7eabc5cc3251bdc59115ef87b5f7ee74cb03747e39ba8341748565cc129c0719"); 147 }); 148 }, "PublicKeyCredential's [[get]] with an AppID in a mock hid authenticator."); 149 150 promise_test(t => { 151 const options = { 152 publicKey: { 153 challenge: Base64URL.parse("MTIzNDU2"), 154 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testCredentialIdBase64) }, { type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 155 timeout: 100, 156 extensions: { appid: "" } 157 } 158 }; 159 160 if (window.testRunner) 161 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } }); 162 return navigator.credentials.get(options).then(credential => { 163 return checkResult(credential); 164 }); 165 }, "PublicKeyCredential's [[get]] with multiple credentials and AppID is not used in a mock hid authenticator."); 166 167 promise_test(t => { 168 const options = { 169 publicKey: { 170 challenge: Base64URL.parse("MTIzNDU2"), 171 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testCredentialIdBase64) }, { type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 172 timeout: 100, 173 extensions: { appid: "" } 174 } 175 }; 176 177 if (window.testRunner) 178 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", isU2f: true, payloadBase64: [testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } }); 179 return navigator.credentials.get(options).then(credential => { 180 return checkResult(credential, true); 181 }); 182 }, "PublicKeyCredential's [[get]] with multiple credentials and AppID is used in a mock hid authenticator."); 183 70 184 </script> -
trunk/Source/WebCore/CMakeLists.txt
r243014 r243193 439 439 Modules/webaudio/WaveShaperNode.idl 440 440 441 Modules/webauthn/AuthenticationExtensionsClientInputs.idl 441 442 Modules/webauthn/AuthenticatorAssertionResponse.idl 442 443 Modules/webauthn/AuthenticatorAttestationResponse.idl -
trunk/Source/WebCore/ChangeLog
r243192 r243193 1 2019-03-19 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Implement FIDO AppID extension 4 https://bugs.webkit.org/show_bug.cgi?id=143491 5 <rdar://problem/48298273> 6 7 Reviewed by Brent Fulgham. 8 9 This patch adds support for FIDO AppID extension: https://www.w3.org/TR/webauthn/#sctn-appid-extension. 10 To be noticed, this implementation follows what spec suggested in the 'Note' session and what Chrome/Firefox 11 do in practice to avoid some unnecessary steps of 12 https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-appid-and-facets-v2.0-id-20180227.html#determining-if-a-caller-s-facetid-is-authorized-for-an-appid. 13 14 In fido::convertToU2fSignCommand, the checkOnly flag is deleted as it is never used. 15 16 Covered by new tests in existing files. 17 18 * CMakeLists.txt: 19 * DerivedSources-input.xcfilelist: 20 * DerivedSources-output.xcfilelist: 21 * DerivedSources.make: 22 * Modules/webauthn/AuthenticationExtensionsClientInputs.h: Copied from Source/WebCore/Modules/webauthn/PublicKeyCredential.idl. 23 (WebCore::AuthenticationExtensionsClientInputs::encode const): 24 (WebCore::AuthenticationExtensionsClientInputs::decode): 25 * Modules/webauthn/AuthenticationExtensionsClientInputs.idl: Copied from Source/WebCore/Modules/webauthn/PublicKeyCredentialRequestOptions.idl. 26 * Modules/webauthn/AuthenticatorCoordinator.cpp: 27 (WebCore::AuthenticatorCoordinatorInternal::processAppIdExtension): 28 (WebCore::AuthenticatorCoordinator::create const): 29 (WebCore::AuthenticatorCoordinator::discoverFromExternalSource const): 30 * Modules/webauthn/PublicKeyCredential.cpp: 31 (WebCore::PublicKeyCredential::tryCreate): 32 (WebCore::PublicKeyCredential::PublicKeyCredential): 33 (WebCore::PublicKeyCredential::getClientExtensionResults const): 34 (WebCore::PublicKeyCredential::create): Deleted. 35 * Modules/webauthn/PublicKeyCredential.h: 36 * Modules/webauthn/PublicKeyCredential.idl: 37 * Modules/webauthn/PublicKeyCredentialCreationOptions.h: 38 * Modules/webauthn/PublicKeyCredentialCreationOptions.idl: 39 * Modules/webauthn/PublicKeyCredentialData.h: 40 (WebCore::PublicKeyCredentialData::encode const): 41 (WebCore::PublicKeyCredentialData::decode): 42 * Modules/webauthn/PublicKeyCredentialRequestOptions.h: 43 (WebCore::PublicKeyCredentialRequestOptions::encode const): 44 (WebCore::PublicKeyCredentialRequestOptions::decode): 45 * Modules/webauthn/PublicKeyCredentialRequestOptions.idl: 46 * Modules/webauthn/fido/DeviceResponseConverter.cpp: 47 (fido::readCTAPMakeCredentialResponse): 48 (fido::readCTAPGetAssertionResponse): 49 * Modules/webauthn/fido/U2fCommandConstructor.cpp: 50 (fido::convertToU2fSignCommand): 51 * Modules/webauthn/fido/U2fCommandConstructor.h: 52 * Modules/webauthn/fido/U2fResponseConverter.cpp: 53 (fido::readU2fRegisterResponse): 54 (fido::readU2fSignResponse): 55 * Sources.txt: 56 * WebCore.xcodeproj/project.pbxproj: 57 1 58 2019-03-19 Devin Rousso <drousso@apple.com> 2 59 -
trunk/Source/WebCore/DerivedSources-input.xcfilelist
r243014 r243193 305 305 $(PROJECT_DIR)/Modules/webaudio/ScriptProcessorNode.idl 306 306 $(PROJECT_DIR)/Modules/webaudio/WaveShaperNode.idl 307 $(PROJECT_DIR)/Modules/webauthn/AuthenticationExtensionsClientInputs.idl 307 308 $(PROJECT_DIR)/Modules/webauthn/AuthenticatorAssertionResponse.idl 308 309 $(PROJECT_DIR)/Modules/webauthn/AuthenticatorAttestationResponse.idl -
trunk/Source/WebCore/DerivedSources-output.xcfilelist
r243014 r243193 155 155 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAudioTrackMediaSource.cpp 156 156 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAudioTrackMediaSource.h 157 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAuthenticationExtensionsClientInputs.cpp 158 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAuthenticationExtensionsClientInputs.h 157 159 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAuthenticatorAssertionResponse.cpp 158 160 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/JSAuthenticatorAssertionResponse.h -
trunk/Source/WebCore/DerivedSources.make
r243169 r243193 352 352 $(WebCore)/Modules/webaudio/ScriptProcessorNode.idl \ 353 353 $(WebCore)/Modules/webaudio/WaveShaperNode.idl \ 354 $(WebCore)/Modules/webauthn/AuthenticationExtensionsClientInputs.idl \ 354 355 $(WebCore)/Modules/webauthn/AuthenticatorAssertionResponse.idl \ 355 356 $(WebCore)/Modules/webauthn/AuthenticatorAttestationResponse.idl \ -
trunk/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.h
r243192 r243193 1 1 /* 2 * Copyright (C) 201 7Apple Inc. All rights reserved.2 * Copyright (C) 2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 typedef boolean AuthenticationExtensions; 26 #pragma once 27 27 28 [ 29 Conditional=WEB_AUTHN, 30 EnabledAtRuntime=WebAuthentication, 31 Exposed=Window, 32 SecureContext, 33 ] interface PublicKeyCredential : BasicCredential { 34 [SameObject] readonly attribute ArrayBuffer rawId; 35 [SameObject] readonly attribute AuthenticatorResponse response; 36 [MayThrowException] AuthenticationExtensions getClientExtensionResults(); 28 #if ENABLE(WEB_AUTHN) 37 29 38 [CallWith=Document] static Promise<boolean> isUserVerifyingPlatformAuthenticatorAvailable(); 30 #include <wtf/text/WTFString.h> 31 32 namespace WebCore { 33 34 struct AuthenticationExtensionsClientInputs { 35 String appid; 36 37 template<class Encoder> void encode(Encoder&) const; 38 template<class Decoder> static Optional<AuthenticationExtensionsClientInputs> decode(Decoder&); 39 39 }; 40 41 template<class Encoder> 42 void AuthenticationExtensionsClientInputs::encode(Encoder& encoder) const 43 { 44 encoder << appid; 45 } 46 47 template<class Decoder> 48 Optional<AuthenticationExtensionsClientInputs> AuthenticationExtensionsClientInputs::decode(Decoder& decoder) 49 { 50 AuthenticationExtensionsClientInputs result; 51 52 Optional<String> appid; 53 decoder >> appid; 54 if (!appid) 55 return WTF::nullopt; 56 result.appid = WTFMove(*appid); 57 58 return result; 59 } 60 61 } // namespace WebCore 62 63 #endif // ENABLE(WEB_AUTHN) -
trunk/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.idl
r243192 r243193 1 1 /* 2 * Copyright (C) 201 8Apple Inc. All rights reserved.2 * Copyright (C) 2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 26 26 [ 27 27 Conditional=WEB_AUTHN, 28 ] dictionary PublicKeyCredentialRequestOptions { 29 required BufferSource challenge; 30 unsigned long timeout; 31 USVString rpId; 32 sequence<PublicKeyCredentialDescriptor> allowCredentials = []; 33 UserVerificationRequirement userVerification = "preferred"; 34 // Not support yet. 35 // AuthenticationExtensions extensions; 28 ] dictionary AuthenticationExtensionsClientInputs { 29 USVString appid; 36 30 }; -
trunk/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp
r239665 r243193 38 38 #include "PublicKeyCredentialData.h" 39 39 #include "PublicKeyCredentialRequestOptions.h" 40 #include "RegistrableDomain.h" 41 #include "SchemeRegistry.h" 40 42 #include "SecurityOrigin.h" 41 43 #include <pal/crypto/CryptoDigest.h> … … 79 81 } 80 82 83 // The following roughly implements Step 1-3 of the spec to avoid the complexity of making unnecessary network requests: 84 // https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-appid-and-facets-v2.0-id-20180227.html#determining-if-a-caller-s-facetid-is-authorized-for-an-appid 85 // It follows what Chrome and Firefox do, see: 86 // https://bugzilla.mozilla.org/show_bug.cgi?id=1244959#c8 87 // https://bugs.chromium.org/p/chromium/issues/detail?id=818303 88 static String processAppIdExtension(const SecurityOrigin& facetId, const String& appId) 89 { 90 // Step 1. Skipped since facetId should always be secure origins. 91 ASSERT(SchemeRegistry::shouldTreatURLSchemeAsSecure(facetId.protocol())); 92 93 // Step 2. Follow Chrome and Firefox to use the origin directly without adding a trailing slash. 94 if (appId.isEmpty()) 95 return facetId.toString(); 96 97 // Step 3. Relax the comparison to same site. 98 URL appIdURL(URL(), appId); 99 if (!appIdURL.isValid() || facetId.protocol() != appIdURL.protocol() || RegistrableDomain(appIdURL) != RegistrableDomain::uncheckedCreateFromHost(facetId.host())) 100 return String(); 101 return appId; 102 } 103 81 104 } // namespace AuthenticatorCoordinatorInternal 82 105 … … 96 119 97 120 // The following implements https://www.w3.org/TR/webauthn/#createCredential as of 5 December 2017. 98 // FIXME: Extensions are not supported yet. Skip Step 11-12.121 // Extensions are not supported. Skip Step 11-12. 99 122 // Step 1, 3, 16 are handled by the caller. 100 123 // Step 2. … … 159 182 160 183 // The following implements https://www.w3.org/TR/webauthn/#createCredential as of 5 December 2017. 161 // FIXME: Extensions are not supported yet. Skip Step 8-9.162 184 // Step 1, 3, 13 are handled by the caller. 163 185 // Step 2. … … 177 199 if (options.rpId.isEmpty()) 178 200 options.rpId = callerOrigin.host(); 201 202 // Step 8-9. 203 // Only FIDO AppID Extension is supported. 204 if (options.extensions && !options.extensions->appid.isNull()) { 205 // The following implements https://www.w3.org/TR/webauthn/#sctn-appid-extension as of 4 March 2019. 206 auto appid = processAppIdExtension(callerOrigin, options.extensions->appid); 207 if (!appid) { 208 promise.reject(Exception { SecurityError, "The origin of the document is not authorized for the provided App ID."_s }); 209 return; 210 } 211 options.extensions->appid = appid; 212 } 179 213 180 214 // Step 10-12. -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp
r238238 r243193 41 41 namespace WebCore { 42 42 43 Ref<PublicKeyCredential> PublicKeyCredential::create(Ref<ArrayBuffer>&& id, Ref<AuthenticatorResponse>&& response)44 {45 return adoptRef(*new PublicKeyCredential(WTFMove(id), WTFMove(response)));46 }47 48 43 RefPtr<PublicKeyCredential> PublicKeyCredential::tryCreate(const PublicKeyCredentialData& data) 49 44 { … … 55 50 return nullptr; 56 51 57 return adoptRef(*new PublicKeyCredential(data.rawId.releaseNonNull(), AuthenticatorAttestationResponse::create(data.clientDataJSON.releaseNonNull(), data.attestationObject.releaseNonNull()) ));52 return adoptRef(*new PublicKeyCredential(data.rawId.releaseNonNull(), AuthenticatorAttestationResponse::create(data.clientDataJSON.releaseNonNull(), data.attestationObject.releaseNonNull()), { data.appid })); 58 53 } 59 54 … … 61 56 return nullptr; 62 57 63 return adoptRef(*new PublicKeyCredential(data.rawId.releaseNonNull(), AuthenticatorAssertionResponse::create(data.clientDataJSON.releaseNonNull(), data.authenticatorData.releaseNonNull(), data.signature.releaseNonNull(), WTFMove(data.userHandle)) ));58 return adoptRef(*new PublicKeyCredential(data.rawId.releaseNonNull(), AuthenticatorAssertionResponse::create(data.clientDataJSON.releaseNonNull(), data.authenticatorData.releaseNonNull(), data.signature.releaseNonNull(), WTFMove(data.userHandle)), { data.appid })); 64 59 } 65 60 66 PublicKeyCredential::PublicKeyCredential(Ref<ArrayBuffer>&& id, Ref<AuthenticatorResponse>&& response )61 PublicKeyCredential::PublicKeyCredential(Ref<ArrayBuffer>&& id, Ref<AuthenticatorResponse>&& response, AuthenticationExtensionsClientOutputs&& extensions) 67 62 : BasicCredential(WTF::base64URLEncode(id->data(), id->byteLength()), Type::PublicKey, Discovery::Remote) 68 63 , m_rawId(WTFMove(id)) 69 64 , m_response(WTFMove(response)) 65 , m_extensions(WTFMove(extensions)) 70 66 { 71 67 } 72 68 73 ExceptionOr<bool>PublicKeyCredential::getClientExtensionResults() const69 PublicKeyCredential::AuthenticationExtensionsClientOutputs PublicKeyCredential::getClientExtensionResults() const 74 70 { 75 return Exception { NotSupportedError };71 return m_extensions; 76 72 } 77 73 -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.h
r235888 r243193 43 43 class PublicKeyCredential final : public BasicCredential { 44 44 public: 45 static Ref<PublicKeyCredential> create(Ref<ArrayBuffer>&& id, Ref<AuthenticatorResponse>&&); 45 struct AuthenticationExtensionsClientOutputs { 46 Optional<bool> appid; 47 }; 48 46 49 static RefPtr<PublicKeyCredential> tryCreate(const PublicKeyCredentialData&); 47 50 48 51 ArrayBuffer* rawId() const { return m_rawId.ptr(); } 49 52 AuthenticatorResponse* response() const { return m_response.ptr(); } 50 // Not support yet. Always throws. 51 ExceptionOr<bool> getClientExtensionResults() const; 53 AuthenticationExtensionsClientOutputs getClientExtensionResults() const; 52 54 53 55 static void isUserVerifyingPlatformAuthenticatorAvailable(Document&, DOMPromiseDeferred<IDLBoolean>&&); 54 56 55 57 private: 56 PublicKeyCredential(Ref<ArrayBuffer>&& id, Ref<AuthenticatorResponse>&& );58 PublicKeyCredential(Ref<ArrayBuffer>&& id, Ref<AuthenticatorResponse>&&, AuthenticationExtensionsClientOutputs&&); 57 59 58 60 Type credentialType() const final { return Type::PublicKey; } … … 60 62 Ref<ArrayBuffer> m_rawId; 61 63 Ref<AuthenticatorResponse> m_response; 64 AuthenticationExtensionsClientOutputs m_extensions; 62 65 }; 63 66 -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredential.idl
r235888 r243193 24 24 */ 25 25 26 typedef boolean AuthenticationExtensions;27 28 26 [ 29 27 Conditional=WEB_AUTHN, … … 34 32 [SameObject] readonly attribute ArrayBuffer rawId; 35 33 [SameObject] readonly attribute AuthenticatorResponse response; 36 [MayThrowException] AuthenticationExtensions getClientExtensionResults();34 AuthenticationExtensionsClientOutputs getClientExtensionResults(); 37 35 38 36 [CallWith=Document] static Promise<boolean> isUserVerifyingPlatformAuthenticatorAvailable(); 39 37 }; 38 39 [ 40 Conditional=WEB_AUTHN, 41 JSGenerateToJSObject, 42 ] dictionary AuthenticationExtensionsClientOutputs { 43 boolean appid; 44 }; -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h
r239427 r243193 28 28 #if ENABLE(WEB_AUTHN) 29 29 30 #include "AuthenticationExtensionsClientInputs.h" 30 31 #include "BufferSource.h" 31 32 #include "PublicKeyCredentialDescriptor.h" … … 84 85 Vector<PublicKeyCredentialDescriptor> excludeCredentials; 85 86 Optional<AuthenticatorSelectionCriteria> authenticatorSelection; 87 Optional<AuthenticationExtensionsClientInputs> extensions; // A place holder, but never used. 86 88 87 89 template<class Encoder> void encode(Encoder&) const; -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.idl
r237983 r243193 40 40 // Always "direct" for us. 41 41 // AttestationConveyancePreference attestation = "none"; 42 // Not support yet. 43 // AuthenticationExtensions extensions; 42 AuthenticationExtensionsClientInputs extensions; 44 43 }; 45 44 -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialData.h
r239427 r243193 50 50 mutable RefPtr<ArrayBuffer> userHandle; 51 51 52 // Extensions 53 Optional<bool> appid; 54 52 55 template<class Encoder> void encode(Encoder&) const; 53 56 template<class Decoder> static Optional<PublicKeyCredentialData> decode(Decoder&); … … 81 84 encoder << static_cast<uint64_t>(signature->byteLength()); 82 85 encoder.encodeFixedLengthData(reinterpret_cast<const uint8_t*>(signature->data()), signature->byteLength(), 1); 86 87 // Encode AppID before user handle to avoid the userHandle flag. 88 encoder << appid; 83 89 84 90 if (!userHandle) { … … 149 155 return WTF::nullopt; 150 156 157 Optional<Optional<bool>> appid; 158 decoder >> appid; 159 if (!appid) 160 return WTF::nullopt; 161 result.appid = WTFMove(*appid); 162 151 163 Optional<bool> hasUserHandle; 152 164 decoder >> hasUserHandle; -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialRequestOptions.h
r239427 r243193 28 28 #if ENABLE(WEB_AUTHN) 29 29 30 #include "AuthenticationExtensionsClientInputs.h" 30 31 #include "BufferSource.h" 31 32 #include "PublicKeyCredentialDescriptor.h" … … 41 42 Vector<PublicKeyCredentialDescriptor> allowCredentials; 42 43 UserVerificationRequirement userVerification { UserVerificationRequirement::Preferred }; 44 mutable Optional<AuthenticationExtensionsClientInputs> extensions; 43 45 44 46 template<class Encoder> void encode(Encoder&) const; … … 50 52 void PublicKeyCredentialRequestOptions::encode(Encoder& encoder) const 51 53 { 52 encoder << timeout << rpId << allowCredentials << userVerification ;54 encoder << timeout << rpId << allowCredentials << userVerification << extensions; 53 55 } 54 56 … … 75 77 result.userVerification = WTFMove(*userVerification); 76 78 79 Optional<Optional<AuthenticationExtensionsClientInputs>> extensions; 80 decoder >> extensions; 81 if (!extensions) 82 return WTF::nullopt; 83 result.extensions = WTFMove(*extensions); 84 77 85 return result; 78 86 } -
trunk/Source/WebCore/Modules/webauthn/PublicKeyCredentialRequestOptions.idl
r237983 r243193 32 32 sequence<PublicKeyCredentialDescriptor> allowCredentials = []; 33 33 UserVerificationRequirement userVerification = "preferred"; 34 // Not support yet. 35 // AuthenticationExtensions extensions; 34 AuthenticationExtensionsClientInputs extensions; 36 35 }; -
trunk/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp
r239665 r243193 122 122 auto attestationObject = cbor::CBORWriter::write(CBOR(WTFMove(attestationObjectMap))); 123 123 124 return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.value().data(), attestationObject.value().size()), nullptr, nullptr, nullptr };124 return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.value().data(), attestationObject.value().size()), nullptr, nullptr, nullptr, WTF::nullopt }; 125 125 } 126 126 … … 171 171 } 172 172 173 return PublicKeyCredentialData { WTFMove(credentialId), false, nullptr, nullptr, ArrayBuffer::create(authData.data(), authData.size()), ArrayBuffer::create(signature.data(), signature.size()), WTFMove(userHandle) };173 return PublicKeyCredentialData { WTFMove(credentialId), false, nullptr, nullptr, ArrayBuffer::create(authData.data(), authData.size()), ArrayBuffer::create(signature.data(), signature.size()), WTFMove(userHandle), WTF::nullopt }; 174 174 } 175 175 -
trunk/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.cpp
r242776 r243193 115 115 } 116 116 117 Optional<Vector<uint8_t>> convertToU2fSignCommand(const Vector<uint8_t>& clientDataHash, const PublicKeyCredentialRequestOptions& request, const Vector<uint8_t>& keyHandle, bool checkOnly)117 Optional<Vector<uint8_t>> convertToU2fSignCommand(const Vector<uint8_t>& clientDataHash, const PublicKeyCredentialRequestOptions& request, const Vector<uint8_t>& keyHandle, bool isAppId) 118 118 { 119 119 if (!isConvertibleToU2fSignCommand(request)) 120 120 return WTF::nullopt; 121 121 122 return constructU2fSignCommand(produceRpIdHash(request.rpId), clientDataHash, keyHandle, checkOnly); 122 if (!isAppId) 123 return constructU2fSignCommand(produceRpIdHash(request.rpId), clientDataHash, keyHandle, false); 124 ASSERT(request.extensions && !request.extensions->appid.isNull()); 125 return constructU2fSignCommand(produceRpIdHash(request.extensions->appid), clientDataHash, keyHandle, false); 123 126 } 124 127 -
trunk/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.h
r242776 r243193 63 63 64 64 // Extracts APDU encoded U2F sign command from PublicKeyCredentialRequestOptions. 65 WEBCORE_EXPORT Optional<Vector<uint8_t>> convertToU2fSignCommand(const Vector<uint8_t>& clientDataHash, const WebCore::PublicKeyCredentialRequestOptions&, const Vector<uint8_t>& keyHandle, bool checkOnly= false);65 WEBCORE_EXPORT Optional<Vector<uint8_t>> convertToU2fSignCommand(const Vector<uint8_t>& clientDataHash, const WebCore::PublicKeyCredentialRequestOptions&, const Vector<uint8_t>& keyHandle, bool isAppId = false); 66 66 67 67 WEBCORE_EXPORT Vector<uint8_t> constructBogusU2fRegistrationCommand(); -
trunk/Source/WebCore/Modules/webauthn/fido/U2fResponseConverter.cpp
r239752 r243193 171 171 auto attestationObject = buildAttestationObject(WTFMove(authData), "fido-u2f", WTFMove(fidoAttestationStatement)); 172 172 173 return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr };173 return PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr, WTF::nullopt }; 174 174 } 175 175 … … 187 187 auto authData = buildAuthData(rpId, flags, counter, { }); 188 188 189 return PublicKeyCredentialData { ArrayBuffer::create(keyHandle.data(), keyHandle.size()), false, nullptr, nullptr, ArrayBuffer::create(authData.data(), authData.size()), ArrayBuffer::create(u2fData.data() + signatureIndex, u2fData.size() - signatureIndex), nullptr };189 return PublicKeyCredentialData { ArrayBuffer::create(keyHandle.data(), keyHandle.size()), false, nullptr, nullptr, ArrayBuffer::create(authData.data(), authData.size()), ArrayBuffer::create(u2fData.data() + signatureIndex, u2fData.size() - signatureIndex), nullptr, WTF::nullopt }; 190 190 } 191 191 -
trunk/Source/WebCore/Sources.txt
r243185 r243193 2568 2568 JSAudioParam.cpp 2569 2569 JSAudioProcessingEvent.cpp 2570 JSAuthenticationExtensionsClientInputs.cpp 2570 2571 JSAuthenticatorAssertionResponse.cpp 2571 2572 JSAuthenticatorAttestationResponse.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r243185 r243193 1865 1865 57D8462E1FEAF69900CA3682 /* PublicKeyCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D8462B1FEAF68F00CA3682 /* PublicKeyCredential.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1866 1866 57D846351FEAFCD300CA3682 /* JSPublicKeyCredential.h in Headers */ = {isa = PBXBuildFile; fileRef = 57D846301FEAFC2F00CA3682 /* JSPublicKeyCredential.h */; }; 1867 57DA47B0224034E4002A4612 /* AuthenticationExtensionsClientInputs.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DA47A522401E0F002A4612 /* AuthenticationExtensionsClientInputs.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1867 1868 57DCED74214305F00016B847 /* PublicKeyCredentialData.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DCED72214305F00016B847 /* PublicKeyCredentialData.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1868 1869 57DCED9021487FF70016B847 /* AuthenticatorTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 57DCED8C21487EDB0016B847 /* AuthenticatorTransport.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 8866 8867 57D846301FEAFC2F00CA3682 /* JSPublicKeyCredential.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPublicKeyCredential.h; sourceTree = "<group>"; }; 8867 8868 57D846311FEAFC2F00CA3682 /* JSPublicKeyCredential.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPublicKeyCredential.cpp; sourceTree = "<group>"; }; 8869 57DA47A522401E0F002A4612 /* AuthenticationExtensionsClientInputs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthenticationExtensionsClientInputs.h; sourceTree = "<group>"; }; 8870 57DA47A722401E0F002A4612 /* AuthenticationExtensionsClientInputs.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = AuthenticationExtensionsClientInputs.idl; sourceTree = "<group>"; }; 8871 57DA47AC224032DC002A4612 /* JSAuthenticationExtensionsClientInputs.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSAuthenticationExtensionsClientInputs.cpp; sourceTree = "<group>"; }; 8872 57DA47AD224032DD002A4612 /* JSAuthenticationExtensionsClientInputs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSAuthenticationExtensionsClientInputs.h; sourceTree = "<group>"; }; 8868 8873 57DCED72214305F00016B847 /* PublicKeyCredentialData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PublicKeyCredentialData.h; sourceTree = "<group>"; }; 8869 8874 57DCED8C21487EDB0016B847 /* AuthenticatorTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthenticatorTransport.h; sourceTree = "<group>"; }; … … 19880 19885 57303BB32006C6ED00355965 /* cbor */, 19881 19886 578A4BFA2166AE0000D08F34 /* fido */, 19887 57DA47A522401E0F002A4612 /* AuthenticationExtensionsClientInputs.h */, 19888 57DA47A722401E0F002A4612 /* AuthenticationExtensionsClientInputs.idl */, 19882 19889 57303C272009B2FC00355965 /* AuthenticatorAssertionResponse.h */, 19883 19890 57303C292009B2FC00355965 /* AuthenticatorAssertionResponse.idl */, … … 19916 19923 isa = PBXGroup; 19917 19924 children = ( 19925 57DA47AC224032DC002A4612 /* JSAuthenticationExtensionsClientInputs.cpp */, 19926 57DA47AD224032DD002A4612 /* JSAuthenticationExtensionsClientInputs.h */, 19918 19927 57303C2E2009B7DA00355965 /* JSAuthenticatorAssertionResponse.cpp */, 19919 19928 57303C2D2009B7D900355965 /* JSAuthenticatorAssertionResponse.h */, … … 28609 28618 934F713A0D5A6F1000018D69 /* AuthenticationChallengeBase.h in Headers */, 28610 28619 E124748410AA161D00B79493 /* AuthenticationClient.h in Headers */, 28620 57DA47B0224034E4002A4612 /* AuthenticationExtensionsClientInputs.h in Headers */, 28611 28621 514C764C0CE9234E007EF3CD /* AuthenticationMac.h in Headers */, 28612 28622 57303C2C2009B4A800355965 /* AuthenticatorAssertionResponse.h in Headers */, -
trunk/Source/WebKit/ChangeLog
r243186 r243193 1 2019-03-19 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Implement FIDO AppID extension 4 https://bugs.webkit.org/show_bug.cgi?id=143491 5 <rdar://problem/48298273> 6 7 Reviewed by Brent Fulgham. 8 9 In U2fHidAuthenticator::continueSignCommandAfterResponseReceived, it will retry the current command 10 with the AppID if it exists when SW_WRONG_DATA is received from devices. Noted, it will not set 11 the AuthenticationExtensionsClientOutputs::appid to false in any circumstances. In other words, the 12 field will be empty if AppID is supplied in AuthenticationExtensionsClientInputs and not used. 13 14 * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm: 15 (WebKit::LocalAuthenticator::continueMakeCredentialAfterAttested): 16 (WebKit::LocalAuthenticator::continueGetAssertionAfterUserConsented): 17 * UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp: 18 (WebKit::U2fHidAuthenticator::issueSignCommand): 19 (WebKit::U2fHidAuthenticator::continueSignCommandAfterResponseReceived): 20 * UIProcess/WebAuthentication/fido/U2fHidAuthenticator.h: 21 1 22 2019-03-19 Ross Kirsling <ross.kirsling@sony.com> 2 23 -
trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm
r242308 r243193 327 327 auto attestationObject = buildAttestationObject(WTFMove(authData), "Apple", WTFMove(attestationStatementMap)); 328 328 329 receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr });329 receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr, WTF::nullopt }); 330 330 #endif // !PLATFORM(IOS_FAMILY) 331 331 } … … 464 464 465 465 // Step 13. 466 receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), false, nullptr, nullptr, ArrayBuffer::create(authData.data(), authData.size()), ArrayBuffer::create(signature.data(), signature.size()), ArrayBuffer::create(userhandle.data(), userhandle.size()) });466 receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), false, nullptr, nullptr, ArrayBuffer::create(authData.data(), authData.size()), ArrayBuffer::create(signature.data(), signature.size()), ArrayBuffer::create(userhandle.data(), userhandle.size()), WTF::nullopt }); 467 467 #endif // !PLATFORM(IOS_FAMILY) 468 468 } -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fHidAuthenticator.cpp
r239752 r243193 102 102 return; 103 103 } 104 auto u2fCmd = convertToU2fSignCommand(requestData().hash, requestData().requestOptions, requestData().requestOptions.allowCredentials[index].idVector );104 auto u2fCmd = convertToU2fSignCommand(requestData().hash, requestData().requestOptions, requestData().requestOptions.allowCredentials[index].idVector, m_isAppId); 105 105 ASSERT(u2fCmd); 106 106 issueNewCommand(WTFMove(*u2fCmd), CommandType::SignCommand); … … 201 201 switch (apduResponse.status()) { 202 202 case ApduResponse::Status::SW_NO_ERROR: { 203 auto response = readU2fSignResponse(requestData().requestOptions.rpId, requestData().requestOptions.allowCredentials[m_nextListIndex - 1].idVector, apduResponse.data()); 203 Optional<PublicKeyCredentialData> response; 204 if (m_isAppId) { 205 ASSERT(requestData().requestOptions.extensions && !requestData().requestOptions.extensions->appid.isNull()); 206 response = readU2fSignResponse(requestData().requestOptions.extensions->appid, requestData().requestOptions.allowCredentials[m_nextListIndex - 1].idVector, apduResponse.data()); 207 } else 208 response = readU2fSignResponse(requestData().requestOptions.rpId, requestData().requestOptions.allowCredentials[m_nextListIndex - 1].idVector, apduResponse.data()); 204 209 if (!response) { 205 210 receiveRespond(ExceptionData { UnknownError, "Couldn't parse the U2F sign response."_s }); 206 211 return; 207 212 } 213 if (m_isAppId) 214 response->appid = m_isAppId; 215 208 216 receiveRespond(WTFMove(*response)); 209 217 return; … … 213 221 m_retryTimer.startOneShot(Seconds::fromMilliseconds(retryTimeOutValueMs)); 214 222 return; 215 default: 223 case ApduResponse::Status::SW_WRONG_DATA: 224 if (requestData().requestOptions.extensions && !requestData().requestOptions.extensions->appid.isNull()) { 225 if (!m_isAppId) { 226 m_isAppId = true; 227 issueSignCommand(m_nextListIndex - 1); 228 return; 229 } 230 m_isAppId = false; 231 } 216 232 issueSignCommand(m_nextListIndex++); 233 return; 234 default: 235 issueSignCommand(m_nextListIndex++); 217 236 } 218 237 } -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/U2fHidAuthenticator.h
r239752 r243193 75 75 CommandType m_lastCommandType; 76 76 size_t m_nextListIndex { 0 }; 77 bool m_isAppId { false }; 77 78 }; 78 79 -
trunk/Tools/ChangeLog
r243188 r243193 1 2019-03-19 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Implement FIDO AppID extension 4 https://bugs.webkit.org/show_bug.cgi?id=143491 5 <rdar://problem/48298273> 6 7 Reviewed by Brent Fulgham. 8 9 Add a test that covers the new flag of convertToU2fSignCommand. 10 11 * TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp: 12 (TestWebKitAPI::TEST): 13 * TestWebKitAPI/Tests/WebCore/FidoTestData.h: 14 * TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp: 15 (TestWebKitAPI::TEST): 16 1 17 2019-03-19 Keith Rollin <krollin@apple.com> 2 18 -
trunk/Tools/TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp
r239427 r243193 60 60 PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria selection { PublicKeyCredentialCreationOptions::AuthenticatorAttachment::Platform, true, UserVerificationRequirement::Preferred }; 61 61 62 PublicKeyCredentialCreationOptions options { rp, user, { }, params, WTF::nullopt, { }, selection };62 PublicKeyCredentialCreationOptions options { rp, user, { }, params, WTF::nullopt, { }, selection, WTF::nullopt }; 63 63 Vector<uint8_t> hash; 64 64 hash.append(TestData::kClientDataHash, sizeof(TestData::kClientDataHash)); -
trunk/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h
r239752 r243193 101 101 0xB6, 0x59, 0x5C, 0xFD, 0x70, 0xA5, 0x0D, 0x70, 0xC6, 0x40, 0x7B, 0xCF, 102 102 0x01, 0x3D, 0xE9, 0x6D, 0x4E, 0xFB, 0x17, 0xDE, 103 // Key handle length 104 0x40, 105 // Key handle 106 0x3E, 0xBD, 0x89, 0xBF, 0x77, 0xEC, 0x50, 0x97, 0x55, 0xEE, 0x9C, 0x26, 107 0x35, 0xEF, 0xAA, 0xAC, 0x7B, 0x2B, 0x9C, 0x5C, 0xEF, 0x17, 0x36, 0xC3, 108 0x71, 0x7D, 0xA4, 0x85, 0x34, 0xC8, 0xC6, 0xB6, 0x54, 0xD7, 0xFF, 0x94, 109 0x5F, 0x50, 0xB5, 0xCC, 0x4E, 0x78, 0x05, 0x5B, 0xDD, 0x39, 0x6B, 0x64, 110 0xF7, 0x8D, 0xA2, 0xC5, 0xF9, 0x62, 0x00, 0xCC, 0xD4, 0x15, 0xCD, 0x08, 111 0xFE, 0x42, 0x00, 0x38, 112 // Max response length 113 0x00, 0x00, 114 }; 115 116 constexpr uint8_t kU2fAppIDSignCommandApdu[] = { 117 // CLA, INS, P1, P2 APDU instruction parameters 118 0x00, 0x02, 0x03, 0x00, 119 // Data Length (3 bytes in big endian order) 120 0x00, 0x00, 0x81, 121 // Challenge parameter -- see kClientDataHash 122 0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e, 0x42, 123 0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05, 124 0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41, 125 // Application parameter 126 0xc9, 0x34, 0x02, 0x87, 0x08, 0x3d, 0x64, 0xde, 0xed, 0x17, 0x1b, 0xbb, 127 0xd7, 0x60, 0x10, 0xae, 0xc5, 0x65, 0x3e, 0x78, 0xfc, 0xd0, 0x31, 0x88, 128 0xd0, 0xbf, 0x70, 0x16, 0x9a, 0x46, 0x91, 0xda, 103 129 // Key handle length 104 130 0x40, -
trunk/Tools/TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp
r239665 r243193 177 177 } 178 178 179 TEST(U2fCommandConstructorTest, TestConvertCtapGetAssertionWithAppIDToU2fSignRequest) 180 { 181 auto getAssertionReq = constructGetAssertionRequest(); 182 PublicKeyCredentialDescriptor credentialDescriptor; 183 credentialDescriptor.type = PublicKeyCredentialType::PublicKey; 184 credentialDescriptor.idVector = convertBytesToVector(TestData::kU2fSignKeyHandle, sizeof(TestData::kU2fSignKeyHandle)); 185 Vector<PublicKeyCredentialDescriptor> allowedList; 186 allowedList.append(WTFMove(credentialDescriptor)); 187 getAssertionReq.allowCredentials = WTFMove(allowedList); 188 EXPECT_TRUE(isConvertibleToU2fSignCommand(getAssertionReq)); 189 190 // AppID 191 WebCore::AuthenticationExtensionsClientInputs extensions; 192 extensions.appid = "https://www.example.com/appid"; 193 getAssertionReq.extensions = WTFMove(extensions); 194 195 const auto u2fSignCommand = convertToU2fSignCommand(convertBytesToVector(TestData::kClientDataHash, sizeof(TestData::kClientDataHash)), getAssertionReq, convertBytesToVector(TestData::kU2fSignKeyHandle, sizeof(TestData::kU2fSignKeyHandle)), true); 196 ASSERT_TRUE(u2fSignCommand); 197 EXPECT_EQ(*u2fSignCommand, convertBytesToVector(TestData::kU2fAppIDSignCommandApdu, sizeof(TestData::kU2fAppIDSignCommandApdu))); 198 } 199 179 200 TEST(U2fCommandConstructorTest, TestU2fSignAllowListRequirement) 180 201 {
Note: See TracChangeset
for help on using the changeset viewer.