// META: script=/common/utils.js // META: script=resources/support.sub.js // // Spec: https://wicg.github.io/private-network-access/#integration-fetch // // This test verifies that Private Network Access checks are applied to all // the endpoints in a redirect chain, relative to the same client context. // local -> private -> public // // Request 1 (local -> private): no preflight. // Request 2 (local -> public): no preflight. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL }, target: { server: Server.HTTPS_PRIVATE, behavior: { response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_PUBLIC, behavior: { response: ResponseBehavior.allowCrossOrigin() }, }), } }, expected: FetchTestResult.SUCCESS, }), "local to private to public: success."); // local -> private -> local // // Request 1 (local -> private): no preflight. // Request 2 (local -> local): no preflight. // // This checks that the client for the second request is still the initial // context, not the redirector. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL }, target: { server: Server.HTTPS_PRIVATE, behavior: { response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { response: ResponseBehavior.allowCrossOrigin() }, }), } }, expected: FetchTestResult.SUCCESS, }), "local to private to local: success."); // private -> private -> local // // Request 1 (private -> private): no preflight. // Request 2 (private -> local): preflight required. // // This verifies that PNA checks are applied after redirects. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PRIVATE }, target: { server: Server.HTTPS_PRIVATE, behavior: { redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { response: ResponseBehavior.allowCrossOrigin() }, }), } }, expected: FetchTestResult.FAILURE, }), "private to private to local: failed preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PRIVATE }, target: { server: Server.HTTPS_PRIVATE, behavior: { redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.SUCCESS, }), "private to private to local: success."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PRIVATE }, target: { server: Server.HTTPS_PRIVATE, behavior: { redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()) }, }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.OPAQUE, }), "private to private to local: no-cors success."); // private -> local -> private // // Request 1 (private -> local): preflight required. // Request 2 (private -> private): no preflight. // // This verifies that PNA checks are applied independently to every step in a // redirect chain. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PRIVATE }, target: { server: Server.HTTPS_LOCAL, behavior: { response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, }), } }, expected: FetchTestResult.FAILURE, }), "private to local to private: failed preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PRIVATE }, target: { server: Server.HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { response: ResponseBehavior.allowCrossOrigin() }, }), } }, expected: FetchTestResult.SUCCESS, }), "private to local to private: success."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PRIVATE }, target: { server: Server.HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.HTTPS_PRIVATE }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.OPAQUE, }), "private to local to private: no-cors success."); // public -> private -> local // // Request 1 (public -> private): preflight required. // Request 2 (public -> local): preflight required. // // This verifies that PNA checks are applied to every step in a redirect chain. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PUBLIC }, target: { server: Server.HTTPS_PRIVATE, behavior: { response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.FAILURE, }), "public to private to local: failed first preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PUBLIC }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.FAILURE, }), "public to private to local: failed second preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PUBLIC }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.SUCCESS, }), "public to private to local: success."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_PUBLIC }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()) }, }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.OPAQUE, }), "public to private to local: no-cors success."); // treat-as-public -> local -> private // Request 1 (treat-as-public -> local): preflight required. // Request 2 (treat-as-public -> private): preflight required. // This verifies that PNA checks are applied to every step in a redirect chain. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.OTHER_HTTPS_LOCAL, behavior: { redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), response: ResponseBehavior.allowCrossOrigin(), } }, expected: FetchTestResult.FAILURE, }), "treat-as-public to local to private: failed first preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.noPnaHeader(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), response: ResponseBehavior.allowCrossOrigin(), } }, expected: FetchTestResult.FAILURE, }), "treat-as-public to local to private: failed second preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), response: ResponseBehavior.allowCrossOrigin(), } }, expected: FetchTestResult.SUCCESS, }), "treat-as-public to local to private: success."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.OTHER_HTTPS_LOCAL, behavior: { redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()) }, }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.FAILURE, }), "treat-as-public to local to private: no-cors failed first preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.HTTPS_PRIVATE }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.FAILURE, }), "treat-as-public to local to private: no-cors failed second preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()) }, }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.OPAQUE, }), "treat-as-public to local to private: no-cors success."); // treat-as-public -> local (same-origin) -> private // Request 1 (treat-as-public -> local (same-origin)): no preflight required. // Request 2 (treat-as-public -> private): preflight required. // This verifies that PNA checks are applied only to the second step in a // redirect chain if the first step is same-origin and the origin is potentially // trustworthy. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_LOCAL, behavior: { redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.noPnaHeader(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.FAILURE, }), "treat-as-public to local (same-origin) to private: failed second preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_LOCAL, behavior: { redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.SUCCESS, }), "treat-as-public to local (same-origin) to private: success."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_LOCAL, behavior: { redirect: preflightUrl({ server: Server.HTTPS_PRIVATE }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.FAILURE, }), "treat-as-public to local (same-origin) to private: no-cors failed second preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_LOCAL, behavior: { redirect: preflightUrl({ server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()) }, }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.OPAQUE, }), "treat-as-public to local (same-origin) to private: no-cors success."); // treat-as-public -> private -> local // Request 1 (treat-as-public -> private): preflight required. // Request 2 (treat-as-public -> local): preflight required. // This verifies that PNA checks are applied to every step in a redirect chain. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.noPnaHeader(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.FAILURE, }), "treat-as-public to private to local: failed first preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.OTHER_HTTPS_LOCAL, behavior: { response: ResponseBehavior.allowCrossOrigin() }, }), } }, expected: FetchTestResult.FAILURE, }), "treat-as-public to private to local: failed second preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), }, }), } }, expected: FetchTestResult.SUCCESS, }), "treat-as-public to private to local: success."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { redirect: preflightUrl({ server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()) }, }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.FAILURE, }), "treat-as-public to private to local: no-cors failed first preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.OTHER_HTTPS_LOCAL }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.FAILURE, }), "treat-as-public to private to local: no-cors failed second preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.OTHER_HTTPS_LOCAL, behavior: { preflight: PreflightBehavior.success(token()) }, }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.OPAQUE, }), "treat-as-public to private to local: no-cors success."); // treat-as-public -> private -> local (same-origin) // Request 1 (treat-as-public -> private): preflight required. // Request 2 (treat-as-public -> local (same-origin)): no preflight required. // This verifies that PNA checks are only applied to the first step in a // redirect chain if the second step is same-origin and the origin is // potentially trustworthy. promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.noPnaHeader(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { response: ResponseBehavior.allowCrossOrigin() }, }), } }, expected: FetchTestResult.FAILURE, }), "treat-as-public to private to local (same-origin): failed first preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), response: ResponseBehavior.allowCrossOrigin(), redirect: preflightUrl({ server: Server.HTTPS_LOCAL, behavior: { response: ResponseBehavior.allowCrossOrigin() }, }), } }, expected: FetchTestResult.SUCCESS, }), "treat-as-public to private to local (same-origin): success."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { redirect: preflightUrl({ server: Server.HTTPS_LOCAL }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.FAILURE, }), "treat-as-public to private to local (same-origin): no-cors failed first preflight."); promise_test(t => fetchTest(t, { source: { server: Server.HTTPS_LOCAL, treatAsPublic: true, }, target: { server: Server.HTTPS_PRIVATE, behavior: { preflight: PreflightBehavior.success(token()), redirect: preflightUrl({ server: Server.HTTPS_LOCAL }), } }, fetchOptions: { mode: "no-cors" }, expected: FetchTestResult.OPAQUE, }), "treat-as-public to private to local (same-origin): no-cors success.");