Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

<!DOCTYPE html>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="helper.js" type="module"></script>
<script type="module">
import {
expireCookie,
documentHasCookie,
waitForCookie,
addCookieAndSessionCleanup,
setupShardedServerState,
configureServer,
crossSiteFetch
} from "./helper.js";
promise_test(async t => {
await setupShardedServerState({crossSite: true});
const expectedCookieAndValue = "auth_cookie=abcdef0123";
const expectedCookieAttributes = `Domain=${location.hostname};Path=/device-bound-session-credentials;SameSite=Lax`;
const expectedCookieAndAttributes = `${expectedCookieAndValue};${expectedCookieAttributes}`;
addCookieAndSessionCleanup(t);
configureServer({
// Set cookie details in order to specify that we should only bind a SameSite=Lax cookie for this test.
cookieDetails: [
{
nameAndValue: expectedCookieAndValue,
attributes: expectedCookieAttributes,
}
],
// Since registration happens from a third-party context, we need
// a SameSite=None cookie to tell us that registration completed.
registrationExtraCookies: [
{
nameAndValue: "get_session_instructions=done",
attributes: "SameSite=None;Secure",
}
]
});
// Prompt starting a session in a third-party context, and wait until registration completes.
const loginStatus = await crossSiteFetch(get_host_info().HTTPS_NOTSAMESITE_ORIGIN, `${location.protocol}//${location.host}/device-bound-session-credentials/login.py`, {credentials: "include"});
assert_equals(loginStatus, 200);
await waitForCookie("get_session_instructions=done", /*expectCookie=*/true);
// Since all cookies in the session are first-party, registration
// from a third-party context should fail.
expireCookie(expectedCookieAndAttributes);
assert_false(documentHasCookie(expectedCookieAndValue));
const authResponseAfterExpiry = await fetch('verify_authenticated.py');
assert_equals(authResponseAfterExpiry.status, 401);
assert_false(documentHasCookie(expectedCookieAndValue));
}, "Registration of first-party session not allowed in third-party context");
promise_test(async t => {
await setupShardedServerState({crossSite: true});
const expectedCookieAndValueSameSiteLax = "auth_cookie_lax=abcdef0123";
const expectedCookieAttributesSameSiteLax = `Domain=${location.hostname};Path=/device-bound-session-credentials;SameSite=Lax`;
const expectedCookieAndAttributesSameSiteLax = `${expectedCookieAndValueSameSiteLax};${expectedCookieAttributesSameSiteLax}`;
const expectedCookieAndValueSameSiteNone = "auth_cookie=abcdef0123";
const expectedCookieAttributesSameSiteNone = `Domain=${location.hostname};Path=/device-bound-session-credentials;SameSite=None;Secure`;
const expectedCookieAndAttributesSameSiteNone = `${expectedCookieAndValueSameSiteNone};${expectedCookieAttributesSameSiteNone}`;
addCookieAndSessionCleanup(t);
configureServer({
// Configure the server to bind both a SameSite=Lax and SameSite=None cookie
cookieDetails: [
{
nameAndValue: expectedCookieAndValueSameSiteLax,
attributes: expectedCookieAttributesSameSiteLax,
},
{
nameAndValue: expectedCookieAndValueSameSiteNone,
attributes: expectedCookieAttributesSameSiteNone,
}
],
// Since registration happens from a third-party context, we need
// a SameSite=None cookie to tell us that registration completed.
registrationExtraCookies: [
{
nameAndValue: "get_session_instructions=done",
attributes: "SameSite=None;Secure",
}
]
});
// Prompt starting a session in a third-party context, and wait until registration completes.
const loginStatus = await crossSiteFetch(get_host_info().HTTPS_NOTSAMESITE_ORIGIN, `${location.protocol}//${location.host}/device-bound-session-credentials/login.py`, {credentials: "include"});
assert_equals(loginStatus, 200);
await waitForCookie("get_session_instructions=done", /*expectCookie=*/true);
// Because registration is happenin from a third-party context, only the
// SameSite=None cookie will be set.
assert_false(documentHasCookie(expectedCookieAndValueSameSiteLax));
assert_true(documentHasCookie(expectedCookieAndValueSameSiteNone));
// Since one cookies in the session is third-party, registration
// from a third-party context should succeed.
expireCookie(expectedCookieAndAttributesSameSiteLax);
expireCookie(expectedCookieAndAttributesSameSiteNone);
assert_false(documentHasCookie(expectedCookieAndValueSameSiteLax));
assert_false(documentHasCookie(expectedCookieAndValueSameSiteNone));
const authResponseAfterExpiry = await fetch('verify_authenticated.py');
assert_equals(authResponseAfterExpiry.status, 200);
// While the registration was from a third-party context, the
// refresh triggered by fetching verify_authenticated.py is
// happening in a first-party context. So we get both cookies from
// the refresh.
assert_true(documentHasCookie(expectedCookieAndValueSameSiteLax));
assert_true(documentHasCookie(expectedCookieAndValueSameSiteNone));
}, "Registration of session with third-party cookies allowed in third-party context");
promise_test(async t => {
await setupShardedServerState({crossSite: true});
const expectedCookieAndValue = "auth_cookie=abcdef0123";
const expectedCookieAttributes = `Domain=${location.hostname};Path=/device-bound-session-credentials;SameSite=Lax`;
const expectedCookieAndAttributes = `${expectedCookieAndValue};${expectedCookieAttributes}`;
addCookieAndSessionCleanup(t);
configureServer({
// Set cookie details in order to specify that we should only bind a SameSite=Lax cookie for this test.
cookieDetails: [
{
nameAndValue: expectedCookieAndValue,
attributes: expectedCookieAttributes,
},
],
earlyChallengeForNextRegisteredSession: "early_challenge",
});
// Prompt starting a session in a first-party context, and wait until registration completes.
const loginResponse = await fetch('login.py');
assert_equals(loginResponse.status, 200);
await waitForCookie(expectedCookieAndValue, /*expectCookie=*/true);
// Try to set the challenge from a third-party context
const challengeStatus = await crossSiteFetch(get_host_info().HTTPS_NOTSAMESITE_ORIGIN, `${location.protocol}//${location.host}/device-bound-session-credentials/request_early_challenge.py`, {method: 'POST', body: JSON.stringify({ useSingleHeader: true}), credentials: "include"});
assert_equals(challengeStatus, 200);
// Since all cookies in the session are first-party, our attempt to
// set a challenge from a third-party context should fail. This
// causes a challenge mismatch at registration time.
expireCookie(expectedCookieAndAttributes);
assert_false(documentHasCookie(expectedCookieAndValue));
const authResponseAfterExpiry = await fetch('verify_authenticated.py');
assert_equals(authResponseAfterExpiry.status, 401);
assert_false(documentHasCookie(expectedCookieAndValue));
}, "Set challenge of first-party not allowed in third-party context");
promise_test(async t => {
await setupShardedServerState({crossSite: true});
const expectedCookieAndValueSameSiteLax = "auth_cookie_lax=abcdef0123";
const expectedCookieAttributesSameSiteLax = `Domain=${location.hostname};Path=/device-bound-session-credentials;SameSite=Lax`;
const expectedCookieAndAttributesSameSiteLax = `${expectedCookieAndValueSameSiteLax};${expectedCookieAttributesSameSiteLax}`;
const expectedCookieAndValueSameSiteNone = "auth_cookie=abcdef0123";
const expectedCookieAttributesSameSiteNone = `Domain=${location.hostname};Path=/device-bound-session-credentials;SameSite=None;Secure`;
const expectedCookieAndAttributesSameSiteNone = `${expectedCookieAndValueSameSiteNone};${expectedCookieAttributesSameSiteNone}`;
addCookieAndSessionCleanup(t);
configureServer({
// Configure the server to bind both a SameSite=Lax and SameSite=None cookie
cookieDetails: [
{
nameAndValue: expectedCookieAndValueSameSiteLax,
attributes: expectedCookieAttributesSameSiteLax,
},
{
nameAndValue: expectedCookieAndValueSameSiteNone,
attributes: expectedCookieAttributesSameSiteNone,
}
],
earlyChallengeForNextRegisteredSession: "early_challenge",
});
// Prompt starting a session in a first-party context, and wait until registration completes.
const loginResponse = await fetch('login.py');
assert_equals(loginResponse.status, 200);
await waitForCookie(expectedCookieAndValueSameSiteNone, /*expectCookie=*/true);
// Try to set the challenge from a third-party context
const challengeStatus = await crossSiteFetch(get_host_info().HTTPS_NOTSAMESITE_ORIGIN, `${location.protocol}//${location.host}/device-bound-session-credentials/request_early_challenge.py`, {method: 'POST', body: JSON.stringify({ useSingleHeader: true}), credentials: "include"});
assert_equals(challengeStatus, 200);
// Since one cookie in the session is third-party, our attempt to
// set a challenge from a third-party context should succeed.
expireCookie(expectedCookieAndAttributesSameSiteLax);
expireCookie(expectedCookieAndAttributesSameSiteNone);
assert_false(documentHasCookie(expectedCookieAndValueSameSiteLax));
assert_false(documentHasCookie(expectedCookieAndValueSameSiteNone));
const authResponseAfterExpiry = await fetch('verify_authenticated.py');
assert_equals(authResponseAfterExpiry.status, 200);
// While the challenge was set in a third-party context, the refresh
// triggered by fetching verify_authenticated.py is happening in a
// first-party context. So we get both cookies from the refresh.
assert_true(documentHasCookie(expectedCookieAndValueSameSiteLax));
assert_true(documentHasCookie(expectedCookieAndValueSameSiteNone));
}, "Set challenge of session with third-party cookies allowed in third-party context");
</script>