tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mtesting/web-platform/tests/device-bound-session-credentials/refresh_session.py | 4++++
Mtesting/web-platform/tests/device-bound-session-credentials/registration-sends-challenge.https.html | 39++++++++++++++++++++++++++++++++++++---
Mtesting/web-platform/tests/device-bound-session-credentials/session_manager.py | 27+++++++++++++++++++--------
Mtesting/web-platform/tests/device-bound-session-credentials/start_session.py | 9++++++---
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)