From e40e7e0043824d384d9fd0a71cc6000ca75e1236 Mon Sep 17 00:00:00 2001 From: Christian Biesinger Date: Mon, 13 May 2024 13:47:41 -0700 Subject: [PATCH] [FedCM] Replace the scopes API with the fields API This implements the new proposal here: https://github.com/fedidcg/FedCM/issues/559 If one or two but not all of ["name", "email", "picture"] are requested, we reject the promise. Otherwise, we show the disclosure text if either field is not specified or contains the three default fields. All specified fields are passed to the server in the "fields" parameter; if fields was unspecified we pass the default fields here. All this is for forwards compatibility. Bug: 40262526, 340194462 Change-Id: I13833691e5f2851f0dc8e9568d007e57a47b8127 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5529071 Reviewed-by: Yi Gu Reviewed-by: Brendon Tiszka Commit-Queue: Christian Biesinger Cr-Commit-Position: refs/heads/main@{#1300264} --- .../fedcm-disclosure-text-shown.https.html | 36 +++++++++++++++++-- .../manifest_check_disclosure_shown_true.json | 7 ++++ .../token_check_disclosure_shown_false.py | 6 ++++ .../token_check_disclosure_shown_true.py | 22 ++++++++++++ 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 credential-management/support/fedcm/manifest_check_disclosure_shown_true.json create mode 100644 credential-management/support/fedcm/token_check_disclosure_shown_true.py diff --git a/credential-management/fedcm-authz/fedcm-disclosure-text-shown.https.html b/credential-management/fedcm-authz/fedcm-disclosure-text-shown.https.html index e3f303ec4c9ff5..513ef258e18a68 100644 --- a/credential-management/fedcm-authz/fedcm-disclosure-text-shown.https.html +++ b/credential-management/fedcm-authz/fedcm-disclosure-text-shown.https.html @@ -16,10 +16,42 @@ fedcm_test(async t => { let options = request_options_with_mediation_required("manifest_check_disclosure_shown_false.json"); options.identity.providers[0].clientId = "0"; - options.identity.providers[0].scope = ["non_default_scope"]; + options.identity.providers[0].fields = ["non_default_field"]; + options.identity.providers[0].nonce = "non_default_field"; const cred = await fedcm_get_and_select_first_account(t, options); assert_equals(cred.token, "token"); assert_equals(cred.isAutoSelected, false); -}, "We should send disclosure_text_shown=false when custom scopes are passed."); +}, "We should send disclosure_text_shown=false when custom fields are passed."); + +fedcm_test(async t => { + let options = request_options_with_mediation_required("manifest_check_disclosure_shown_false.json"); + options.identity.providers[0].clientId = "0"; + options.identity.providers[0].fields = []; + options.identity.providers[0].nonce = ""; + const cred = await fedcm_get_and_select_first_account(t, options); + assert_equals(cred.token, "token"); + assert_equals(cred.isAutoSelected, false); +}, "We should send disclosure_text_shown=false when an empty custom fields array is passed."); + + +fedcm_test(async t => { + let options = request_options_with_mediation_required("manifest_check_disclosure_shown_true.json"); + options.identity.providers[0].clientId = "0"; + options.identity.providers[0].nonce = "name,email,picture"; + const cred = await fedcm_get_and_select_first_account(t, options); + assert_equals(cred.token, "token"); + assert_equals(cred.isAutoSelected, false); +}, "We should send disclosure_text_shown=true when no custom fields are passed."); + +fedcm_test(async t => { + let options = request_options_with_mediation_required("manifest_check_disclosure_shown_true.json"); + options.identity.providers[0].clientId = "0"; + options.identity.providers[0].fields = ["name", "email", "picture", "locale"]; + options.identity.providers[0].nonce = "name,email,picture,locale"; + const cred = await fedcm_get_and_select_first_account(t, options); + assert_equals(cred.token, "token"); + assert_equals(cred.isAutoSelected, false); +}, "We should send disclosure_text_shown=true when custom fields are passed in addition to standard fields."); + diff --git a/credential-management/support/fedcm/manifest_check_disclosure_shown_true.json b/credential-management/support/fedcm/manifest_check_disclosure_shown_true.json new file mode 100644 index 00000000000000..7d7004c3cffee4 --- /dev/null +++ b/credential-management/support/fedcm/manifest_check_disclosure_shown_true.json @@ -0,0 +1,7 @@ +{ + "accounts_endpoint": "accounts.py", + "client_metadata_endpoint": "client_metadata.py", + "id_assertion_endpoint": "token_check_disclosure_shown_true.py", + "login_url": "login.html" +} + diff --git a/credential-management/support/fedcm/token_check_disclosure_shown_false.py b/credential-management/support/fedcm/token_check_disclosure_shown_false.py index f4b732053ff0f2..a25a14af694848 100644 --- a/credential-management/support/fedcm/token_check_disclosure_shown_false.py +++ b/credential-management/support/fedcm/token_check_disclosure_shown_false.py @@ -6,8 +6,14 @@ def main(request, response): if (request_error): return request_error + nonce = request.POST.get(b"nonce") or b"" if request.POST.get(b"disclosure_text_shown") != b"false": return (560, [], "disclosure_text_shown is not false") + if request.POST.get(b"disclosure_shown_for") is not None: + return (561, [], "disclosure_shown_for is not None") + fields = request.POST.get(b"fields") or b"" + if fields != nonce: + return (562, [], "fields does not match nonce") response.headers.set(b"Content-Type", b"application/json") response.headers.set(b"Access-Control-Allow-Origin", request.headers.get(b"Origin")) diff --git a/credential-management/support/fedcm/token_check_disclosure_shown_true.py b/credential-management/support/fedcm/token_check_disclosure_shown_true.py new file mode 100644 index 00000000000000..00b755b920cd99 --- /dev/null +++ b/credential-management/support/fedcm/token_check_disclosure_shown_true.py @@ -0,0 +1,22 @@ +import importlib +error_checker = importlib.import_module("credential-management.support.fedcm.request-params-check") + +def main(request, response): + request_error = error_checker.tokenCheck(request) + if (request_error): + return request_error + + nonce = request.POST.get(b"nonce") or b"" + if request.POST.get(b"disclosure_text_shown") != b"true": + return (560, [], "disclosure_text_shown is not true") + if request.POST.get(b"disclosure_shown_for") != b"name,email,picture": + return (561, [], "disclosure_shown_for is not name,email,picture") + fields = request.POST.get(b"fields") or b"" + if fields != nonce: + return (562, [], "fields does not match nonce") + + response.headers.set(b"Content-Type", b"application/json") + response.headers.set(b"Access-Control-Allow-Origin", request.headers.get(b"Origin")) + response.headers.set(b"Access-Control-Allow-Credentials", "true") + + return "{\"token\": \"token\"}"