<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[279856] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/279856">279856</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2021-07-12 16:43:14 -0700 (Mon, 12 Jul 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>_WKWebAuthenticationPanel escapes slashes in origin
https://bugs.webkit.org/show_bug.cgi?id=227724
rdar://80232742

Patch by Garrett Davidson <garrett_davidson@apple.com> on 2021-07-12
Reviewed by Kate Cheney.

Source/WebKit:

Tell NSJSONSerialization not to try to escapes slashes, like those in the scheme of an origin.

* UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
(produceClientDataJson):

Tools:

Update both the makeCredential and getAssertion tests to use an origin.

WebAuthenticationPanel.GetAssertionLA:
This test wasn't using an origin or RPID. Update it to use both. This means both
clientDataJSON and authenticatorData changed. Update both to the new expected
values, using as much plaintext as possible.

WebAuthenticationPanel.MakeCredentialLA:
This test should have caught this issue, but the origin being passed here isn't
valid, because it didn't have a scheme. Per the WebAuthn spec, origins used by
WebAuthn MUST start with "https://". Also update this test to use plaintext
instead of base64 for clientDataJSON.

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

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPICocoa_WKWebAuthenticationPanelmm">trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitCocoa_WKWebAuthenticationPanelmm">trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (279855 => 279856)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2021-07-12 23:07:14 UTC (rev 279855)
+++ trunk/Source/WebKit/ChangeLog       2021-07-12 23:43:14 UTC (rev 279856)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2021-07-12  Garrett Davidson  <garrett_davidson@apple.com>
+
+        _WKWebAuthenticationPanel escapes slashes in origin
+        https://bugs.webkit.org/show_bug.cgi?id=227724
+        rdar://80232742
+
+        Reviewed by Kate Cheney.
+
+        Tell NSJSONSerialization not to try to escapes slashes, like those in the scheme of an origin.
+
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
+        (produceClientDataJson):
+
</ins><span class="cx"> 2021-07-12  Chris Fleizach  <cfleizach@apple.com>
</span><span class="cx"> 
</span><span class="cx">         AX: Make WebKit observe spatial audio accessibility settings
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPICocoa_WKWebAuthenticationPanelmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm (279855 => 279856)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm     2021-07-12 23:07:14 UTC (rev 279855)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm        2021-07-12 23:43:14 UTC (rev 279856)
</span><span class="lines">@@ -73,7 +73,7 @@
</span><span class="cx">     [dictionary setObject:base64URLEncodeToString(challenge.bytes, challenge.length) forKey:@"challenge"];
</span><span class="cx">     [dictionary setObject:origin forKey:@"origin"];
</span><span class="cx"> 
</span><del>-    return [NSJSONSerialization dataWithJSONObject:dictionary.get() options:NSJSONWritingSortedKeys error:nil];
</del><ins>+    return [NSJSONSerialization dataWithJSONObject:dictionary.get() options:(NSJSONWritingSortedKeys | NSJSONWritingWithoutEscapingSlashes) error:nil];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static Vector<uint8_t> produceClientDataJsonHash(NSData *clientDataJson)
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (279855 => 279856)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2021-07-12 23:07:14 UTC (rev 279855)
+++ trunk/Tools/ChangeLog       2021-07-12 23:43:14 UTC (rev 279856)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2021-07-12  Garrett Davidson  <garrett_davidson@apple.com>
+
+        _WKWebAuthenticationPanel escapes slashes in origin
+        https://bugs.webkit.org/show_bug.cgi?id=227724
+        rdar://80232742
+
+        Reviewed by Kate Cheney.
+
+        Update both the makeCredential and getAssertion tests to use an origin.
+
+        WebAuthenticationPanel.GetAssertionLA:
+        This test wasn't using an origin or RPID. Update it to use both. This means both
+        clientDataJSON and authenticatorData changed. Update both to the new expected
+        values, using as much plaintext as possible.
+
+        WebAuthenticationPanel.MakeCredentialLA:
+        This test should have caught this issue, but the origin being passed here isn't
+        valid, because it didn't have a scheme. Per the WebAuthn spec, origins used by
+        WebAuthn MUST start with "https://". Also update this test to use plaintext
+        instead of base64 for clientDataJSON.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
+        (TestWebKitAPI::TEST):
+
</ins><span class="cx"> 2021-07-12  Tim Horton  <timothy_horton@apple.com>
</span><span class="cx"> 
</span><span class="cx">         BifurcatedGraphicsContext can't draw text
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitCocoa_WKWebAuthenticationPanelmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm (279855 => 279856)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm 2021-07-12 23:07:14 UTC (rev 279855)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm    2021-07-12 23:43:14 UTC (rev 279856)
</span><span class="lines">@@ -1776,7 +1776,7 @@
</span><span class="cx">     auto delegate = adoptNS([[TestWebAuthenticationPanelDelegate alloc] init]);
</span><span class="cx">     [panel setDelegate:delegate.get()];
</span><span class="cx"> 
</span><del>-    [panel makeCredentialWithChallenge:nsHash.get() origin:@"example.com" options:options.get() completionHandler:^(_WKAuthenticatorAttestationResponse *response, NSError *error) {
</del><ins>+    [panel makeCredentialWithChallenge:nsHash.get() origin:@"https://example.com" options:options.get() completionHandler:^(_WKAuthenticatorAttestationResponse *response, NSError *error) {
</ins><span class="cx">         webAuthenticationPanelRan = true;
</span><span class="cx">         cleanUpKeychain("example.com");
</span><span class="cx"> 
</span><span class="lines">@@ -1784,7 +1784,7 @@
</span><span class="cx">         EXPECT_NULL(error);
</span><span class="cx"> 
</span><span class="cx">         EXPECT_NOT_NULL(response);
</span><del>-        EXPECT_WK_STREQ([response.clientDataJSON base64EncodedStringWithOptions:0], "eyJjaGFsbGVuZ2UiOiJBUUlEQkFFQ0F3UUJBZ01FQVFJREJBRUNBd1FCQWdNRUFRSURCQUVDQXdRIiwib3JpZ2luIjoiZXhhbXBsZS5jb20iLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0=");
</del><ins>+        EXPECT_WK_STREQ([[NSString alloc] initWithData:response.clientDataJSON encoding:NSUTF8StringEncoding], "{\"challenge\":\"AQIDBAECAwQBAgMEAQIDBAECAwQBAgMEAQIDBAECAwQ\",\"origin\":\"https://example.com\",\"type\":\"webauthn.create\"}");
</ins><span class="cx">         EXPECT_WK_STREQ([response.rawId base64EncodedStringWithOptions:0], "SMSXHngF7hEOsElA73C3RY+8bR4=");
</span><span class="cx">         EXPECT_NULL(response.extensions);
</span><span class="cx">         EXPECT_WK_STREQ([response.attestationObject base64EncodedStringWithOptions:0], "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViYo3mm9u6vuaVeN4wRgDTidR5oL6ufLTCrE9ISVYbOGUdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAFEjElx54Be4RDrBJQO9wt0WPvG0epQECAyYgASFYIDj/zxSkzKgaBuS3cdWDF558of8AaIpgFpsjF/Qm1749IlggVBJPgqUIwfhWHJ91nb7UPH76c0+WFOzZKslPyyFse4g=");
</span><span class="lines">@@ -1897,13 +1897,13 @@
</span><span class="cx"> {
</span><span class="cx">     reset();
</span><span class="cx"> 
</span><del>-    ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "", testUserEntityBundleBase64));
</del><ins>+    ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "example.com", testUserEntityBundleBase64));
</ins><span class="cx"> 
</span><span class="cx">     uint8_t hash[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
</span><span class="cx">     NSData *nsHash = [NSData dataWithBytes:hash length:sizeof(hash)];
</span><span class="cx"> 
</span><span class="cx">     auto options = adoptNS([[_WKPublicKeyCredentialRequestOptions alloc] init]);
</span><del>-    [options setRelyingPartyIdentifier:@""];
</del><ins>+    [options setRelyingPartyIdentifier:@"example.com"];
</ins><span class="cx"> 
</span><span class="cx">     auto panel = adoptNS([[_WKWebAuthenticationPanel alloc] init]);
</span><span class="cx">     [panel setMockConfiguration:@{ }];
</span><span class="lines">@@ -1910,17 +1910,32 @@
</span><span class="cx">     auto delegate = adoptNS([[TestWebAuthenticationPanelDelegate alloc] init]);
</span><span class="cx">     [panel setDelegate:delegate.get()];
</span><span class="cx"> 
</span><del>-    [panel getAssertionWithChallenge:nsHash origin:@"" options:options.get() completionHandler:^(_WKAuthenticatorAssertionResponse *response, NSError *error) {
</del><ins>+    [panel getAssertionWithChallenge:nsHash origin:@"https://example.com" options:options.get() completionHandler:^(_WKAuthenticatorAssertionResponse *response, NSError *error) {
</ins><span class="cx">         webAuthenticationPanelRan = true;
</span><del>-        cleanUpKeychain("");
</del><ins>+        cleanUpKeychain("example.com");
</ins><span class="cx"> 
</span><span class="cx">         EXPECT_NULL(error);
</span><span class="cx"> 
</span><span class="cx">         EXPECT_NOT_NULL(response);
</span><del>-        EXPECT_WK_STREQ([[NSString alloc] initWithData:response.clientDataJSON encoding:NSUTF8StringEncoding], "{\"challenge\":\"AQIDBAECAwQBAgMEAQIDBAECAwQBAgMEAQIDBAECAwQ\",\"origin\":\"\",\"type\":\"webauthn.get\"}");
</del><ins>+        EXPECT_WK_STREQ([[NSString alloc] initWithData:response.clientDataJSON encoding:NSUTF8StringEncoding], "{\"challenge\":\"AQIDBAECAwQBAgMEAQIDBAECAwQBAgMEAQIDBAECAwQ\",\"origin\":\"https://example.com\",\"type\":\"webauthn.get\"}");
</ins><span class="cx">         EXPECT_WK_STREQ([response.rawId base64EncodedStringWithOptions:0], "SMSXHngF7hEOsElA73C3RY+8bR4=");
</span><span class="cx">         EXPECT_NULL(response.extensions);
</span><del>-        EXPECT_WK_STREQ([response.authenticatorData base64EncodedStringWithOptions:0], "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFUFAAAAAA==");
</del><ins>+
+        // echo -n "example.com" | shasum -a 256 | xxd -r -p | base64
+        NSString *base64RPIDHash = @"o3mm9u6vuaVeN4wRgDTidR5oL6ufLTCrE9ISVYbOGUc=";
+        constexpr uint8_t additionalAuthenticatorData[] = {
+            0x05, // 'flags': UV=1, UP=1
+
+            // 32-bit 'signCount'
+            0x00,
+            0x00,
+            0x00,
+            0x00,
+        };
+        NSMutableData *expectedAuthenticatorData = [[NSMutableData alloc] initWithBase64EncodedString:base64RPIDHash options:0];
+        [expectedAuthenticatorData appendBytes:additionalAuthenticatorData length:sizeof(additionalAuthenticatorData)];
+
+        EXPECT_WK_STREQ([response.authenticatorData base64EncodedStringWithOptions:0], [expectedAuthenticatorData base64EncodedStringWithOptions:0]);
</ins><span class="cx">         EXPECT_NOT_NULL(response.signature);
</span><span class="cx">         EXPECT_WK_STREQ([response.userHandle base64EncodedStringWithOptions:0], "AAECAwQFBgcICQ==");
</span><span class="cx">     }];
</span></span></pre>
</div>
</div>

</body>
</html>