commit 150b5ab5962b9310e3ac8ea353b22046b826b1ab
parent a0e3f69676ee309b3fb1298ea5d6c43ca7226c08
Author: Daniel Rubery <drubery@chromium.org>
Date: Thu, 9 Oct 2025 20:33:45 +0000
Bug 1992165 [wpt PR 55180] - Add WPT for challenge alongside DBSC session instructions, a=testonly
Automatic update from web-platform-tests
Add WPT for challenge alongside DBSC session instructions
Registration endpoints should be able to set the challenge for the first
refresh by providing a challenge alongside the session
instructions. This WPT validates that.
Fixed: 438783634
Change-Id: I955b42e7fbb8a7a31aee0ca67d4cc9f40962df5f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6995386
Commit-Queue: Daniel Rubery <drubery@chromium.org>
Reviewed-by: thefrog <thefrog@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1523647}
--
wpt-commits: 5da57e8b7ae6d847e344450c67b25f368e800212
wpt-pr: 55180
Diffstat:
4 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/testing/web-platform/tests/device-bound-session-credentials/refresh_session.py b/testing/web-platform/tests/device-bound-session-credentials/refresh_session.py
@@ -38,6 +38,10 @@ def main(request, response):
if early_challenge is not None:
challenge = early_challenge
+ if test_session_manager.get_registration_sends_challenge_with_instructions():
+ test_session_manager.reset_registration_sends_challenge_with_instructions()
+ challenge = "login_challenge_value"
+
if not verified or jwt_payload.get("jti") != challenge:
return (400, response.headers, "")
diff --git a/testing/web-platform/tests/device-bound-session-credentials/registration-sends-challenge.https.html b/testing/web-platform/tests/device-bound-session-credentials/registration-sends-challenge.https.html
@@ -13,9 +13,9 @@
const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${location.hostname};Path=/device-bound-session-credentials`;
addCookieAndSessionCleanup(t);
- // Configure server to send back a challenge during registration.
+ // Configure server to send back a challenge before the session instructions.
await configureServer({
- registrationSendsChallenge: true,
+ registrationSendsChallengeBeforeInstructions: true,
// Since registration fails, we use a cookie to tell us that the
// response was received.
registrationExtraCookies: [
@@ -36,5 +36,38 @@
const authResponseAfterExpiry = await fetch('verify_authenticated.py');
assert_equals(authResponseAfterExpiry.status, 403);
assert_false(documentHasCookie(expectedCookieAndValue));
-}, "Registration can't send back 403 with challenge");
+ }, "Registration can't send back 403 with challenge");
+
+ promise_test(async t => {
+ await setupShardedServerState();
+ const expectedCookieAndValue = "auth_cookie=abcdef0123";
+ const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${location.hostname};Path=/device-bound-session-credentials`;
+ addCookieAndSessionCleanup(t);
+
+ // Configure server to send back a challenge alongside the session instructions.
+ await configureServer({
+ registrationSendsChallengeWithInstructions: true,
+ // Since registration fails, we use a cookie to tell us that the
+ // response was received.
+ registrationExtraCookies: [
+ {
+ nameAndValue: "dbsc_registration=done",
+ }
+ ]
+ });
+
+ // Prompt starting a session, and wait until registration completes.
+ const loginResponse = await fetch('login.py');
+ assert_equals(loginResponse.status, 200);
+ await waitForCookie("dbsc_registration=done", /*expectCookie=*/true);
+
+ // Confirm that expiring the cookie does a refresh because registration succeeded.
+ expireCookie(expectedCookieAndAttributes);
+ assert_false(documentHasCookie(expectedCookieAndValue));
+ const authResponseAfterExpiry = await fetch('verify_authenticated.py');
+ // The server verifies during refresh that the challenge value is the custom
+ // one set at registration time.
+ assert_equals(authResponseAfterExpiry.status, 200);
+ assert_true(documentHasCookie(expectedCookieAndValue));
+ }, "Registration can send back challenge with session instructions");
</script>
diff --git a/testing/web-platform/tests/device-bound-session-credentials/session_manager.py b/testing/web-platform/tests/device-bound-session-credentials/session_manager.py
@@ -35,7 +35,8 @@ class SessionManager:
self.should_refresh_end_session = False
self.authorization_value = None
self.scope_origin = None
- self.registration_sends_challenge = False
+ self.registration_sends_challenge_before_instructions = False
+ self.registration_sends_challenge_with_instructions = False
self.cookie_details = None
self.session_to_cookie_details_map = {}
self.session_to_early_challenge_map = {}
@@ -86,9 +87,13 @@ class SessionManager:
if scope_origin is not None:
self.scope_origin = scope_origin
- registration_sends_challenge = configuration.get("registrationSendsChallenge")
- if registration_sends_challenge is not None:
- self.registration_sends_challenge = registration_sends_challenge
+ registration_sends_challenge_before_instructions = configuration.get("registrationSendsChallengeBeforeInstructions")
+ if registration_sends_challenge_before_instructions is not None:
+ self.registration_sends_challenge_before_instructions = registration_sends_challenge_before_instructions
+
+ registration_sends_challenge_with_instructions = configuration.get("registrationSendsChallengeWithInstructions")
+ if registration_sends_challenge_with_instructions is not None:
+ self.registration_sends_challenge_with_instructions = registration_sends_challenge_with_instructions
cookie_details = configuration.get("cookieDetails")
if cookie_details is not None:
@@ -165,11 +170,17 @@ class SessionManager:
def get_authorization_value(self):
return self.authorization_value
- def get_registration_sends_challenge(self):
- return self.registration_sends_challenge
+ def get_registration_sends_challenge_before_instructions(self):
+ return self.registration_sends_challenge_before_instructions
+
+ def reset_registration_sends_challenge_before_instructions(self):
+ self.registration_sends_challenge_before_instructions = False
+
+ def get_registration_sends_challenge_with_instructions(self):
+ return self.registration_sends_challenge_with_instructions
- def reset_registration_sends_challenge(self):
- self.registration_sends_challenge = False
+ def reset_registration_sends_challenge_with_instructions(self):
+ self.registration_sends_challenge_with_instructions = False
def get_refresh_sends_challenge(self):
return self.refresh_sends_challenge
diff --git a/testing/web-platform/tests/device-bound-session-credentials/start_session.py b/testing/web-platform/tests/device-bound-session-credentials/start_session.py
@@ -5,9 +5,9 @@ session_manager = importlib.import_module('device-bound-session-credentials.sess
def main(request, response):
test_session_manager = session_manager.find_for_request(request)
extra_cookie_headers = test_session_manager.get_set_cookie_headers(test_session_manager.registration_extra_cookies, request)
- if test_session_manager.get_registration_sends_challenge():
+ if test_session_manager.get_registration_sends_challenge_before_instructions():
# Only send back a challenge on the first call.
- test_session_manager.reset_registration_sends_challenge()
+ test_session_manager.reset_registration_sends_challenge_before_instructions()
return (403, [('Secure-Session-Challenge', '"login_challenge_value"')] + extra_cookie_headers, "")
jwt_header, jwt_payload, verified = jwt_helper.decode_jwt(request.headers.get("Secure-Session-Response").decode('utf-8'))
@@ -24,4 +24,7 @@ def main(request, response):
return (400, response.headers + extra_cookie_headers, "")
(code, headers, body) = test_session_manager.get_session_instructions_response(session_id, request)
- return (code, headers + extra_cookie_headers, body)
+ headers += extra_cookie_headers
+ if test_session_manager.get_registration_sends_challenge_with_instructions():
+ headers.append(('Secure-Session-Challenge', f'"login_challenge_value";id="{session_id}"'))
+ return (code, headers, body)