From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Sun, 7 Apr 2024 21:33:14 +0200
Subject: Adding upstream version 115.7.0esr.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 .../identity/tests/mochitest/head.js               | 24 ++++++++
 .../tests/mochitest/helper_set_cookie.html         |  8 +++
 .../mochitest/helper_set_cookie.html^headers^      |  1 +
 .../identity/tests/mochitest/mochitest.ini         | 48 ++++++++++++++++
 .../mochitest/server_accounts_error_accounts.sjs   |  9 +++
 .../mochitest/server_accounts_error_idtoken.sjs    | 15 +++++
 .../server_accounts_redirect_accounts.sjs          | 10 ++++
 .../mochitest/server_accounts_redirect_idtoken.sjs | 15 +++++
 .../mochitest/server_idtoken_error_accounts.sjs    | 24 ++++++++
 .../mochitest/server_idtoken_error_idtoken.sjs     |  9 +++
 .../mochitest/server_idtoken_redirect_accounts.sjs | 24 ++++++++
 .../mochitest/server_idtoken_redirect_idtoken.sjs  | 10 ++++
 .../identity/tests/mochitest/server_manifest.sjs   | 46 +++++++++++++++
 .../server_manifest_wrong_provider_in_manifest.sjs | 19 +++++++
 .../identity/tests/mochitest/server_metadata.json  |  4 ++
 .../tests/mochitest/server_metadata.json^headers^  |  2 +
 .../mochitest/server_no_accounts_accounts.sjs      | 38 +++++++++++++
 .../tests/mochitest/server_no_accounts_idtoken.sjs | 66 ++++++++++++++++++++++
 .../tests/mochitest/server_simple_accounts.sjs     | 47 +++++++++++++++
 .../tests/mochitest/server_simple_idtoken.sjs      | 66 ++++++++++++++++++++++
 .../mochitest/server_two_accounts_accounts.sjs     | 55 ++++++++++++++++++
 .../mochitest/server_two_accounts_idtoken.sjs      | 66 ++++++++++++++++++++++
 .../mochitest/server_two_providers_accounts.sjs    | 48 ++++++++++++++++
 .../mochitest/server_two_providers_idtoken.sjs     | 59 +++++++++++++++++++
 .../tests/mochitest/test_accounts_error.html       | 37 ++++++++++++
 .../tests/mochitest/test_accounts_redirect.html    | 37 ++++++++++++
 .../tests/mochitest/test_delay_reject.html         | 39 +++++++++++++
 .../tests/mochitest/test_empty_provider_list.html  | 34 +++++++++++
 .../mochitest/test_get_without_providers.html      | 32 +++++++++++
 .../tests/mochitest/test_idtoken_error.html        | 37 ++++++++++++
 .../tests/mochitest/test_idtoken_redirect.html     | 37 ++++++++++++
 .../identity/tests/mochitest/test_no_accounts.html | 37 ++++++++++++
 .../identity/tests/mochitest/test_simple.html      | 46 +++++++++++++++
 .../tests/mochitest/test_two_accounts.html         | 46 +++++++++++++++
 .../tests/mochitest/test_two_providers.html        | 52 +++++++++++++++++
 .../mochitest/test_wrong_provider_in_manifest.html | 37 ++++++++++++
 .../identity/tests/mochitest/web-identity          |  1 +
 .../identity/tests/mochitest/web-identity^headers^ |  2 +
 38 files changed, 1187 insertions(+)
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/head.js
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html^headers^
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/mochitest.ini
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_manifest_wrong_provider_in_manifest.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_metadata.json
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_metadata.json^headers^
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_simple_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_simple_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_two_providers_accounts.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/server_two_providers_idtoken.sjs
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_accounts_error.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_accounts_redirect.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_delay_reject.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_empty_provider_list.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_get_without_providers.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_idtoken_error.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_idtoken_redirect.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_no_accounts.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_simple.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_two_accounts.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_two_providers.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/test_wrong_provider_in_manifest.html
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/web-identity
 create mode 100644 dom/credentialmanagement/identity/tests/mochitest/web-identity^headers^

(limited to 'dom/credentialmanagement/identity/tests/mochitest')

diff --git a/dom/credentialmanagement/identity/tests/mochitest/head.js b/dom/credentialmanagement/identity/tests/mochitest/head.js
new file mode 100644
index 0000000000..393ba9fa23
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/head.js
@@ -0,0 +1,24 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+var idp_host = "https://example.net";
+var test_path = "/tests/dom/credentialmanagement/identity/tests/mochitest";
+var idp_api = idp_host + test_path;
+
+async function setupTest(testName) {
+  ok(
+    window.location.pathname.includes(testName),
+    `Must set the right test name when setting up. Test name "${testName}" must be in URL path "${window.location.pathname}"`
+  );
+  let fetchPromise = fetch(
+    `${idp_api}/server_manifest.sjs?set_test=${testName}`
+  );
+  let focusPromise = SimpleTest.promiseFocus();
+  window.open(`${idp_api}/helper_set_cookie.html`, "_blank");
+  await focusPromise;
+  return fetchPromise;
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html b/dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html
new file mode 100644
index 0000000000..9f8e410b90
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script>
+    window.close();
+</script>
+
+See ya! (This window will close itself)
+The cookie was set via HTTP.
diff --git a/dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html^headers^ b/dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html^headers^
new file mode 100644
index 0000000000..c221facafc
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/helper_set_cookie.html^headers^
@@ -0,0 +1 @@
+Set-Cookie: credential=authcookieval; SameSite=None; Secure; Path=/
diff --git a/dom/credentialmanagement/identity/tests/mochitest/mochitest.ini b/dom/credentialmanagement/identity/tests/mochitest/mochitest.ini
new file mode 100644
index 0000000000..27f210cc9e
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/mochitest.ini
@@ -0,0 +1,48 @@
+[DEFAULT]
+prefs =
+  dom.security.credentialmanagement.identity.enabled=true
+  dom.security.credentialmanagement.identity.select_first_in_ui_lists=true
+  dom.security.credentialmanagement.identity.reject_delay.enabled=false
+  privacy.antitracking.enableWebcompat=false # disables opener heuristic
+scheme = https
+skip-if = xorigin || http3 #  Bug 1838420
+
+support-files =
+  head.js
+  helper_set_cookie.html
+  helper_set_cookie.html^headers^
+  /.well-known/web-identity
+  /.well-known/web-identity^headers^
+  server_manifest.sjs
+  server_manifest_wrong_provider_in_manifest.sjs
+  server_metadata.json
+  server_metadata.json^headers^
+  server_simple_accounts.sjs
+  server_simple_idtoken.sjs
+  server_no_accounts_accounts.sjs
+  server_no_accounts_idtoken.sjs
+  server_two_accounts_accounts.sjs
+  server_two_accounts_idtoken.sjs
+  server_two_providers_accounts.sjs
+  server_two_providers_idtoken.sjs
+  server_accounts_error_accounts.sjs
+  server_accounts_error_idtoken.sjs
+  server_idtoken_error_accounts.sjs
+  server_idtoken_error_idtoken.sjs
+  server_accounts_redirect_accounts.sjs
+  server_accounts_redirect_idtoken.sjs
+  server_idtoken_redirect_accounts.sjs
+  server_idtoken_redirect_idtoken.sjs
+
+[test_accounts_error.html]
+[test_accounts_redirect.html]
+[test_delay_reject.html]
+[test_empty_provider_list.html]
+[test_get_without_providers.html]
+[test_idtoken_error.html]
+[test_idtoken_redirect.html]
+[test_no_accounts.html]
+[test_simple.html]
+[test_two_accounts.html]
+[test_two_providers.html]
+[test_wrong_provider_in_manifest.html]
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_accounts.sjs
new file mode 100644
index 0000000000..d0a11ce469
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_accounts.sjs
@@ -0,0 +1,9 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setStatusLine(request.httpVersion, 503, "Service Unavailable");
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_idtoken.sjs
new file mode 100644
index 0000000000..a6f6f7c4b1
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_error_idtoken.sjs
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let responseContent = {
+    token: "should not be returned",
+  };
+  let body = JSON.stringify(responseContent);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_accounts.sjs
new file mode 100644
index 0000000000..f33da643a0
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_accounts.sjs
@@ -0,0 +1,10 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Location", "server_simple_accounts.sjs");
+  response.setStatusLine(request.httpVersion, 302, "Found");
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_idtoken.sjs
new file mode 100644
index 0000000000..a6f6f7c4b1
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_accounts_redirect_idtoken.sjs
@@ -0,0 +1,15 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let responseContent = {
+    token: "should not be returned",
+  };
+  let body = JSON.stringify(responseContent);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_accounts.sjs
new file mode 100644
index 0000000000..9baeb51ba5
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_accounts.sjs
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts: [
+      {
+        id: "1234",
+        given_name: "John",
+        name: "John Doe",
+        email: "john_doe@idp.example",
+        picture: "https://idp.example/profile/123",
+        approved_clients: ["123", "456", "789"],
+      },
+    ],
+  };
+  let body = JSON.stringify(content);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_idtoken.sjs
new file mode 100644
index 0000000000..653207672b
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_error_idtoken.sjs
@@ -0,0 +1,9 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setStatusLine(request.httpVersion, 503, "Service Unavailable");
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_accounts.sjs
new file mode 100644
index 0000000000..9baeb51ba5
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_accounts.sjs
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts: [
+      {
+        id: "1234",
+        given_name: "John",
+        name: "John Doe",
+        email: "john_doe@idp.example",
+        picture: "https://idp.example/profile/123",
+        approved_clients: ["123", "456", "789"],
+      },
+    ],
+  };
+  let body = JSON.stringify(content);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_idtoken.sjs
new file mode 100644
index 0000000000..66456eb687
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_idtoken_redirect_idtoken.sjs
@@ -0,0 +1,10 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Location", "server_simple_idtoken.sjs");
+  response.setStatusLine(request.httpVersion, 302, "Found");
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs
new file mode 100644
index 0000000000..20d5aa058f
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+Cu.importGlobalProperties(["URLSearchParams"]);
+
+function handleRequest(request, response) {
+  let params = new URLSearchParams(request.queryString);
+  let test = params.get("set_test");
+  if (test === null) {
+    test = getState("test");
+  } else {
+    setState("test", test);
+    response.setHeader("Access-Control-Allow-Origin", "*");
+    response.setStatusLine(request.httpVersion, 200, "OK");
+    return;
+  }
+
+  if (request.hasHeader("Cookie")) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Origin") && request.getHeader("Origin") != "null") {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Referer")) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts_endpoint:
+      "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_TESTNAME_accounts.sjs",
+    client_metadata_endpoint:
+      "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_metadata.json",
+    id_assertion_endpoint:
+      "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_TESTNAME_idtoken.sjs",
+  };
+  let bodyFormat = JSON.stringify(content);
+  let body = bodyFormat.replaceAll("TESTNAME", test);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_manifest_wrong_provider_in_manifest.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_manifest_wrong_provider_in_manifest.sjs
new file mode 100644
index 0000000000..94c60fb731
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_manifest_wrong_provider_in_manifest.sjs
@@ -0,0 +1,19 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts_endpoint:
+      "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_simple_accounts.sjs",
+    client_metadata_endpoint:
+      "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_simple_metadata.sjs",
+    id_assertion_endpoint:
+      "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_simple_idtoken.sjs",
+  };
+  let body = JSON.stringify(content);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_metadata.json b/dom/credentialmanagement/identity/tests/mochitest/server_metadata.json
new file mode 100644
index 0000000000..1e16c942b5
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_metadata.json
@@ -0,0 +1,4 @@
+{
+  "privacy_policy_url": "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/null.txt",
+  "terms_of_service_url": "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/null.txt"
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_metadata.json^headers^ b/dom/credentialmanagement/identity/tests/mochitest/server_metadata.json^headers^
new file mode 100644
index 0000000000..75875a7cf3
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_metadata.json^headers^
@@ -0,0 +1,2 @@
+Content-Type: application/json
+Access-Control-Allow-Origin: *
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_accounts.sjs
new file mode 100644
index 0000000000..dac20e4466
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_accounts.sjs
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Sec-Fetch-Dest") ||
+    request.getHeader("Sec-Fetch-Dest") != "webidentity"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Origin") && request.getHeader("Origin") != "null") {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Referer")) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts: [],
+  };
+  let body = JSON.stringify(content);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_idtoken.sjs
new file mode 100644
index 0000000000..a3ca4ce31d
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_no_accounts_idtoken.sjs
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const BinaryInputStream = Components.Constructor(
+  "@mozilla.org/binaryinputstream;1",
+  "nsIBinaryInputStream",
+  "setInputStream"
+);
+
+function readStream(inputStream) {
+  let available = 0;
+  let result = [];
+  while ((available = inputStream.available()) > 0) {
+    result.push(inputStream.readBytes(available));
+  }
+  return result.join("");
+}
+
+function handleRequest(request, response) {
+  if (request.method != "POST") {
+    response.setStatusLine(request.httpVersion, 405, "Method Not Allowed");
+    return;
+  }
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Sec-Fetch-Dest") ||
+    request.getHeader("Sec-Fetch-Dest") != "webidentity"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Referer") ||
+    request.getHeader("Referer") != "https://example.com/"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Origin") ||
+    request.getHeader("Origin") != "https://example.com"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let requestContent = readStream(
+    new BinaryInputStream(request.bodyInputStream)
+  );
+  let responseContent = {
+    token: requestContent,
+  };
+  let body = JSON.stringify(responseContent);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_simple_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_simple_accounts.sjs
new file mode 100644
index 0000000000..6ebce36802
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_simple_accounts.sjs
@@ -0,0 +1,47 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Sec-Fetch-Dest") ||
+    request.getHeader("Sec-Fetch-Dest") != "webidentity"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Origin") && request.getHeader("Origin") != "null") {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Referer")) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts: [
+      {
+        id: "1234",
+        given_name: "John",
+        name: "John Doe",
+        email: "john_doe@idp.example",
+        picture: "https://idp.example/profile/123",
+        approved_clients: ["123", "456", "789"],
+      },
+    ],
+  };
+  let body = JSON.stringify(content);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_simple_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_simple_idtoken.sjs
new file mode 100644
index 0000000000..a3ca4ce31d
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_simple_idtoken.sjs
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const BinaryInputStream = Components.Constructor(
+  "@mozilla.org/binaryinputstream;1",
+  "nsIBinaryInputStream",
+  "setInputStream"
+);
+
+function readStream(inputStream) {
+  let available = 0;
+  let result = [];
+  while ((available = inputStream.available()) > 0) {
+    result.push(inputStream.readBytes(available));
+  }
+  return result.join("");
+}
+
+function handleRequest(request, response) {
+  if (request.method != "POST") {
+    response.setStatusLine(request.httpVersion, 405, "Method Not Allowed");
+    return;
+  }
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Sec-Fetch-Dest") ||
+    request.getHeader("Sec-Fetch-Dest") != "webidentity"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Referer") ||
+    request.getHeader("Referer") != "https://example.com/"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Origin") ||
+    request.getHeader("Origin") != "https://example.com"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let requestContent = readStream(
+    new BinaryInputStream(request.bodyInputStream)
+  );
+  let responseContent = {
+    token: requestContent,
+  };
+  let body = JSON.stringify(responseContent);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_accounts.sjs
new file mode 100644
index 0000000000..f9d60183a1
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_accounts.sjs
@@ -0,0 +1,55 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Sec-Fetch-Dest") ||
+    request.getHeader("Sec-Fetch-Dest") != "webidentity"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Origin") && request.getHeader("Origin") != "null") {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Referer")) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts: [
+      {
+        id: "1234",
+        given_name: "John",
+        name: "John Doe",
+        email: "john_doe@idp.example",
+        picture: "https://idp.example/profile/123",
+        approved_clients: ["123", "456", "789"],
+      },
+      {
+        id: "5678",
+        given_name: "Johnny",
+        name: "Johnny",
+        email: "johnny@idp.example",
+        picture: "https://idp.example/profile/456",
+        approved_clients: ["abc", "def", "ghi"],
+      },
+    ],
+  };
+  let body = JSON.stringify(content);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_idtoken.sjs
new file mode 100644
index 0000000000..a3ca4ce31d
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_two_accounts_idtoken.sjs
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const BinaryInputStream = Components.Constructor(
+  "@mozilla.org/binaryinputstream;1",
+  "nsIBinaryInputStream",
+  "setInputStream"
+);
+
+function readStream(inputStream) {
+  let available = 0;
+  let result = [];
+  while ((available = inputStream.available()) > 0) {
+    result.push(inputStream.readBytes(available));
+  }
+  return result.join("");
+}
+
+function handleRequest(request, response) {
+  if (request.method != "POST") {
+    response.setStatusLine(request.httpVersion, 405, "Method Not Allowed");
+    return;
+  }
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Sec-Fetch-Dest") ||
+    request.getHeader("Sec-Fetch-Dest") != "webidentity"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Referer") ||
+    request.getHeader("Referer") != "https://example.com/"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Origin") ||
+    request.getHeader("Origin") != "https://example.com"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let requestContent = readStream(
+    new BinaryInputStream(request.bodyInputStream)
+  );
+  let responseContent = {
+    token: requestContent,
+  };
+  let body = JSON.stringify(responseContent);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_two_providers_accounts.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_two_providers_accounts.sjs
new file mode 100644
index 0000000000..25060b850e
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_two_providers_accounts.sjs
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Origin") && request.getHeader("Origin") != "null") {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (request.hasHeader("Referer")) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "*");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let content = {
+    accounts: [
+      {
+        id: "1234",
+        given_name: "John",
+        name: "John Doe",
+        email: "john_doe@idp.example",
+        picture: "https://idp.example/profile/123",
+        approved_clients: ["123", "456", "789"],
+      },
+      {
+        id: "5678",
+        given_name: "Johnny",
+        name: "Johnny",
+        email: "johnny@idp.example",
+        picture: "https://idp.example/profile/456",
+        approved_clients: ["abc", "def", "ghi"],
+      },
+    ],
+  };
+  let body = JSON.stringify(content);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/server_two_providers_idtoken.sjs b/dom/credentialmanagement/identity/tests/mochitest/server_two_providers_idtoken.sjs
new file mode 100644
index 0000000000..01b61ff33d
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/server_two_providers_idtoken.sjs
@@ -0,0 +1,59 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const BinaryInputStream = Components.Constructor(
+  "@mozilla.org/binaryinputstream;1",
+  "nsIBinaryInputStream",
+  "setInputStream"
+);
+
+function readStream(inputStream) {
+  let available = 0;
+  let result = [];
+  while ((available = inputStream.available()) > 0) {
+    result.push(inputStream.readBytes(available));
+  }
+  return result.join("");
+}
+
+function handleRequest(request, response) {
+  if (request.method != "POST") {
+    response.setStatusLine(request.httpVersion, 405, "Method Not Allowed");
+    return;
+  }
+  if (
+    !request.hasHeader("Cookie") ||
+    request.getHeader("Cookie") != "credential=authcookieval"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Referer") ||
+    request.getHeader("Referer") != "https://example.com/"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+  if (
+    !request.hasHeader("Origin") ||
+    request.getHeader("Origin") != "https://example.com"
+  ) {
+    response.setStatusLine(request.httpVersion, 400, "Bad Request");
+    return;
+  }
+
+  response.setHeader("Access-Control-Allow-Origin", "https://example.com");
+  response.setHeader("Access-Control-Allow-Credentials", "true");
+  response.setHeader("Content-Type", "application/json");
+  let requestContent = readStream(
+    new BinaryInputStream(request.bodyInputStream)
+  );
+  let responseContent = {
+    token: requestContent,
+  };
+  let body = JSON.stringify(responseContent);
+  response.setStatusLine(request.httpVersion, 200, "OK");
+  response.write(body);
+}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_accounts_error.html b/dom/credentialmanagement/identity/tests/mochitest/test_accounts_error.html
new file mode 100644
index 0000000000..ca0f85b110
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_accounts_error.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Server Error On Accounts Endpoint</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("accounts_error").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test verifies that we do not get a credential when the accounts endpoint returns an error.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_accounts_redirect.html b/dom/credentialmanagement/identity/tests/mochitest/test_accounts_redirect.html
new file mode 100644
index 0000000000..99b897d35e
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_accounts_redirect.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Server Redirect On Accounts Endpoint</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("accounts_redirect").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test verifies that we do not get a credential when the accounts endpoint redirects to another (entirely functional) accounts endpoint.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_delay_reject.html b/dom/credentialmanagement/identity/tests/mochitest/test_delay_reject.html
new file mode 100644
index 0000000000..0151f4b6c4
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_delay_reject.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Delay Reject</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+
+    SpecialPowers.pushPrefEnv({ set: [
+      ["dom.security.credentialmanagement.identity.reject_delay.enabled", "true" ],
+      ["dom.security.credentialmanagement.identity.reject_delay.duration_ms", "1000" ],
+    ] })
+      .then(() => {setupTest("delay_reject")})
+      .then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: []
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test verifies that our rejections are delayed, checking for >500ms.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_empty_provider_list.html b/dom/credentialmanagement/identity/tests/mochitest/test_empty_provider_list.html
new file mode 100644
index 0000000000..ad5b6ea28c
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_empty_provider_list.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Empty Provider List</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("empty_provider_list")
+      .then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: []
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test verifies that we do not get a credential when we give no providers to support.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_get_without_providers.html b/dom/credentialmanagement/identity/tests/mochitest/test_get_without_providers.html
new file mode 100644
index 0000000000..4425abf5aa
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_get_without_providers.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>No Providers Specified</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("get_without_providers").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test verifies that we do not get a credential when we give no providers field in the JSON. This is mostly to make sure we don't have any nullptr derefs.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_idtoken_error.html b/dom/credentialmanagement/identity/tests/mochitest/test_idtoken_error.html
new file mode 100644
index 0000000000..ddc6716081
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_idtoken_error.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Server Error On Token Endpoint</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("idtoken_error").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test verifies that we do not get a credential when the idtoken endpoint returns an error.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_idtoken_redirect.html b/dom/credentialmanagement/identity/tests/mochitest/test_idtoken_redirect.html
new file mode 100644
index 0000000000..88512a1d22
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_idtoken_redirect.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Server Redirect On Token Endpoint</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("idtoken_redirect").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test verifies that we do not get a credential when the idtoken endpoint redirects to another (entirely functional) idtoken endpoint.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_no_accounts.html b/dom/credentialmanagement/identity/tests/mochitest/test_no_accounts.html
new file mode 100644
index 0000000000..90c3335eda
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_no_accounts.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>No Accounts in the List</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("no_accounts").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test validates that if a provider returns no accounts, we throw an error from our credential request.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_simple.html b/dom/credentialmanagement/identity/tests/mochitest/test_simple.html
new file mode 100644
index 0000000000..39d34f3d5f
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_simple.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Happypath Test</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("simple").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(true, "successfully got a credential");
+      is(cred.token,
+        "account_id=1234&client_id=mochitest&nonce=nonce&disclosure_text_shown=false",
+        "Correct token on the credential.");
+      is(cred.id,
+        "1234",
+        "Correct id on the credential");
+      is(cred.type,
+        "identity",
+        "Correct type on the credential");
+    }).catch((err) => {
+      ok(false, "must not have an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This is the main happypath test. We get a credential in a way that should work. This includes simplifying some logic like exactly one account and provider.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_two_accounts.html b/dom/credentialmanagement/identity/tests/mochitest/test_two_accounts.html
new file mode 100644
index 0000000000..36e99adf75
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_two_accounts.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Two Accounts in the List</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("two_accounts").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(true, "successfully got a credential");
+      is(cred.token,
+        "account_id=1234&client_id=mochitest&nonce=nonce&disclosure_text_shown=false",
+        "Correct token on the credential.");
+      is(cred.id,
+        "1234",
+        "Correct id on the credential");
+      is(cred.type,
+        "identity",
+        "Correct type on the credential");
+    }).catch((err) => {
+      ok(false, "must not have an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test is temporary until we have an account chooser. It verifies that when we get more than one account from the IDP we just pick the first one.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_two_providers.html b/dom/credentialmanagement/identity/tests/mochitest/test_two_providers.html
new file mode 100644
index 0000000000..5533f71064
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_two_providers.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Two Providers in a Credential.get()</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("two_providers").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            },
+            {
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce2"
+            }
+          ]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(true, "successfully got a credential");
+      is(cred.token,
+        "account_id=1234&client_id=mochitest&nonce=nonce&disclosure_text_shown=false",
+        "Correct token on the credential.");
+      is(cred.id,
+        "1234",
+        "Correct id on the credential");
+      is(cred.type,
+        "identity",
+        "Correct type on the credential");
+    }).catch((err) => {
+      ok(false, "must not have an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/test_wrong_provider_in_manifest.html b/dom/credentialmanagement/identity/tests/mochitest/test_wrong_provider_in_manifest.html
new file mode 100644
index 0000000000..8ff1afe04d
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/test_wrong_provider_in_manifest.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Manifest Disagreement</title>
+  <script src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script src="head.js"></script>
+  <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+  <script>
+    SimpleTest.waitForExplicitFinish();
+    setupTest("wrong_provider_in_manifest").then(
+      function () {
+        return navigator.credentials.get({
+          identity: {
+            providers: [{
+              configURL: "https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest_wrong_provider_in_manifest.sjs",
+              clientId: "mochitest",
+              nonce: "nonce"
+            }]
+          }
+        });
+      }
+    ).then((cred) => {
+      ok(false, "incorrectly got a credential");
+    }).catch((err) => {
+      ok(true, "correctly got an error");
+    }).finally(() => {
+      SimpleTest.finish();
+    })
+  </script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">This test is an important privacy check. We make sure the manifest from the argument to credentials.get matches the IDP's root manifest.</div>
+<pre id="test"></pre>
+</body>
+</html>
diff --git a/dom/credentialmanagement/identity/tests/mochitest/web-identity b/dom/credentialmanagement/identity/tests/mochitest/web-identity
new file mode 100644
index 0000000000..33dc9c455b
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/web-identity
@@ -0,0 +1 @@
+{"provider_urls": ["https://example.net/tests/dom/credentialmanagement/identity/tests/mochitest/server_manifest.sjs"]}
diff --git a/dom/credentialmanagement/identity/tests/mochitest/web-identity^headers^ b/dom/credentialmanagement/identity/tests/mochitest/web-identity^headers^
new file mode 100644
index 0000000000..75875a7cf3
--- /dev/null
+++ b/dom/credentialmanagement/identity/tests/mochitest/web-identity^headers^
@@ -0,0 +1,2 @@
+Content-Type: application/json
+Access-Control-Allow-Origin: *
-- 
cgit v1.2.3