Aktualizacje FedCM: wersje próbne źródła dla pakietu Continuation API i automatyczne przyznawanie interfejsu Storage Access API

Od wersji Chrome 126 deweloperzy mogą rozpocząć testowanie origin pakietu funkcji interfejsu Federated Credential Management API (FedCM) na komputery, które umożliwiają niektórych przypadków użycia autoryzacji. Pakiet składa się z interfejsu Continuation API i interfejsu Parameters API, które zapewniają interfejs przypominający przepływ autoryzacji OAuth obejmujący okno uprawnień dostarczone przez dostawcę tożsamości. Pakiet zawiera też inne zmiany, np. interfejs Fields API, wiele adresów configURL i etykiety kont niestandardowych. W Chrome 126 wprowadzamy też wersję próbną origin interfejsu Storage Access API (SAA), który automatycznie przyznaje żądania SAA, jeśli użytkownik zalogował się przy użyciu FedCM w przeszłości.

Wersja próbna origin: pakiet FedCM Continuation API

Pakiet FedCM Continuation API składa się z wielu rozszerzeń FedCM:

Interfejs API Continuation

Użytkownik loguje się w RP, a następnie autoryzuj za pomocą trybu przycisku.

Możesz zobaczyć wersję demonstracyjną interfejsu API w Glitch.

Interfejs Continuation API pozwala punktowi końcowemu potwierdzenia identyfikatora dostawcy tożsamości opcjonalnie zwrócić adres URL wyrenderowany przez FedCM, aby umożliwić użytkownikowi kontynuowanie wieloetapowego procesu logowania. Dzięki temu dostawca tożsamości może zażądać od użytkownika przyznania uprawnień strony zależnej (RP) wykraczających poza możliwości w istniejącym interfejsie FedCM, na przykład do zasobów po stronie serwera użytkownika.

Zwykle punkt końcowy potwierdzenia identyfikatora zwraca token wymagany do uwierzytelniania.

{
  "token": "***********"
}

Jednak w interfejsie Continuation API punkt końcowy asercji identyfikatora może zwrócić właściwość continue_on ze ścieżką bezwzględną lub ścieżką względną do punktu końcowego potwierdzenia identyfikatora.

{
  // In the id_assertion_endpoint, instead of returning a typical
  // "token" response, the IdP decides that it needs the user to
  // continue on a pop-up window:
  "continue_on": "/oauth/authorize?scope=..."
}

Gdy tylko przeglądarka otrzyma odpowiedź continue_on, otworzy się nowe wyskakujące okienko i przekieruje użytkownika pod określoną ścieżkę.

Gdy użytkownik wejdzie w interakcję ze stroną (np. przyzna dodatkowe uprawnienia do udostępniania dodatkowych informacji usłudze RP), strona dostawcy tożsamości może wywołać metodę IdentityProvider.resolve(), aby rozwiązać pierwotne wywołanie navigator.credentials.get() i zwrócić token jako argument.

document.getElementById('allow_btn').addEventListener('click', async () => {
  let accessToken = await fetch('/generate_access_token.cgi');
  // Closes the window and resolves the promise (that is still hanging
  // in the relying party's renderer) with the value that is passed.
  IdentityProvider.resolve(accessToken);
});

Następnie przeglądarka sama zamknie wyskakujące okienko i zwróci token do wywołującego interfejsu API.

Jeśli użytkownik odrzuci prośbę, możesz zamknąć okno, wywołując funkcję IdentityProvider.close().

IdentityProvider.close();

Jeśli z jakiegoś powodu użytkownik zmienił swoje konto w wyskakującym okienku (np. dostawca tożsamości oferuje funkcję zmiany użytkownika lub w przypadku delegacji), wywołanie rozstrzygania przyjmuje opcjonalny drugi argument, który pozwala na przykład:

IdentityProvider.resolve(token, {accountId: '1234');

Interfejs Parameters API

Interfejs Parameters API pozwala grupie docelowej dostarczać parametry do punktu końcowego potwierdzenia identyfikatora. Dzięki interfejsowi Parameters API usługi RP mogą przekazywać do dostawcy tożsamości dodatkowe parametry, by żądać uprawnień do zasobów wykraczających poza podstawowe logowanie. Użytkownik autoryzuje te uprawnienia w ramach procesu UX kontrolowanego przez dostawcę tożsamości, który uruchamia się za pomocą interfejsu API Continuation.

Aby korzystać z interfejsu API, dodaj parametry do właściwości params jako obiekt w wywołaniu navigator.credentials.get().

let {token} = await navigator.credentials.get({
  identity: {
    providers: [{
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      // Key/value pairs that need to be passed from the
      // RP to the IdP but that don't really play any role with
      // the browser.
      params: {
        IDP_SPECIFIC_PARAM: '1',
        foo: 'BAR',
        ETC: 'MOAR',
        scope: 'calendar.readonly photos.write',
      }
    },
  }
});

Nazwy właściwości w obiekcie params mają przedrostek param_. W powyższym przykładzie właściwość params zawiera IDP_SPECIFIC_PARAM jako '1', foo jako 'BAR', ETC jako 'MOAR' i scope jako 'calendar.readonly photos.write'. Zostanie on przetłumaczony jako param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write w treści żądania HTTP:

POST /fedcm_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity

account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false&param_IDP_SPECIFIC_PARAM=1&param_foo=BAR&param_ETC=MOAR&param_scope=calendar.readonly%20photos.write

Dynamiczne uzyskiwanie uprawnień

Ogólnie rzecz biorąc, użytkownikom najlepiej jest prosić o uprawnienia wtedy, gdy są potrzebne, a nie wtedy, gdy deweloper uzna, że wdrożenie jest łatwiejsze. Na przykład prośba o dostęp do aparatu, gdy użytkownik chce zrobić zdjęcie, jest preferowana niż prośba o pozwolenie od razu po przejściu do strony internetowej. To samo dotyczy zasobów serwera. Pilnuj uprawnień tylko wtedy, gdy są potrzebne użytkownikowi. Jest to tzw. „dynamiczna autoryzacja”.

Aby dynamicznie żądać autoryzacji za pomocą FedCM, dostawca tożsamości może:

  1. Wywołaj funkcję navigator.credentials.get() z wymaganymi parametrami odczytywanymi przez dostawcę tożsamości, na przykład scope.
  2. Punkt końcowy potwierdzenia identyfikatora potwierdza, że użytkownik jest już zalogowany, i w odpowiedzi przesyła adres URL continue_on.
  3. Przeglądarka otworzy wyskakujące okienko ze stroną uprawnień dostawcy tożsamości z prośbą o dodatkowe uprawnienia pasujące do żądanych zakresów.
  4. Po autoryzacji przez IdentityProvider.resolve() przez dostawcę tożsamości okno zostaje zamknięte, a pierwotne wywołanie navigator.credentials.get() punktu dostępu otrzymuje odpowiedni token lub kod autoryzacji, aby dostawca ten mógł wymienić go odpowiednim tokenem dostępu.

Interfejs Fields API

Interfejs Fields API umożliwia RP deklarowanie atrybutów konta, do których dostawca tożsamości może wysyłać żądania. Dzięki temu przeglądarka może wyświetlić odpowiedni interfejs użytkownika w oknie FedCM. To dostawca tożsamości ma obowiązek umieścić żądane pola w zwróconym tokenie. Rozważ zastosowanie „profilu podstawowego” w OpenID Connect i „zakresów” w OAuth.

Wiadomość o ujawnieniu w trybie widżetu.
Komunikat o zbieraniu danych w trybie widżetu.
Komunikat wyświetlany w trybie przycisku.
Komunikat wyświetlany w trybie przycisku.

Aby korzystać z interfejsu Fields API, dodaj parametry do właściwości fields w postaci tablicy w wywołaniu navigator.credentials.get(). Pola te mogą na razie zawierać 'name', 'email' i 'picture', ale można je rozszerzyć, by w przyszłości uwzględnić więcej wartości.

Żądanie z polem fields wygląda tak:

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: ['name', 'email', 'picture'],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

Żądanie HTTP do punktu końcowego potwierdzenia identyfikatora zawiera określony przez RP parametr fields z parametrem disclosure_text_shown ustawionym jako true, jeśli nie jest to powracający użytkownik, oraz pola, które przeglądarka ujawni użytkownikowi w parametrze disclosure_shown_for:

POST /id_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity

account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=true&fields=email,name,picture&disclosure_shown_for=email,name,picture

Jeśli grupa objęta ograniczeniami wymaga dostępu do jakichkolwiek dodatkowych danych od dostawcy tożsamości, takich jak dostęp do kalendarza, należy to zrobić za pomocą niestandardowego parametru (jak opisano powyżej). Dostawca tożsamości zwraca adres URL continue_on, aby poprosić o odpowiednie uprawnienia.

Jeśli fields jest pustą tablicą, żądanie wygląda tak:

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      fields: [],
      clientId: '1234',
      configURL: 'https://idp.example/fedcm.json',
      params: {
        scope: 'drive.readonly calendar.readonly',
      }
    },
  }
  mediation: 'optional',
});

Jeśli fields jest pustą tablicą, klient użytkownika pominie interfejs komunikatu.

Komunikat o zgłoszeniu nie jest wyświetlany w trybie widżetu. Podczas tworzenia przycisku interfejs komunikatu jest całkowicie pomijany.
Komunikat o zgłoszeniu nie wyświetla się w trybie widżetu. Podczas tworzenia przycisku interfejs komunikatu jest całkowicie pomijany.

Dzieje się tak nawet wtedy, gdy odpowiedź z punktu końcowego kont nie zawiera identyfikatora klienta pasującego do grupy objętej ograniczeniami w approved_clients.

W tym przypadku żądanie disclosure_text_shown wysłane do punktu końcowego asercji identyfikatora w treści HTTP ma wartość fałsz:

POST /id_assertion_endpoint HTTP/1.1
Host: idp.example
Origin: https://rp.example/
Content-Type: application/x-www-form-urlencoded
Cookie: 0x23223
Sec-Fetch-Dest: webidentity

account_id=123&client_id=client1234&nonce=234234&disclosure_text_shown=false

Wiele adresów configURL

Wiele adresów configURL umożliwia dostawcom tożsamości obsługę wielu plików konfiguracyjnych dostawcy tożsamości przez określenie accounts_endpoint i login_url w dobrze znanym pliku tak samo jak w plikach konfiguracji.

Jeśli do dobrze znanego pliku zostaną dodane accounts_endpoint i login_url, provider_urls są ignorowane, aby dostawca tożsamości mógł obsługiwać wiele plików konfiguracyjnych. W przeciwnym razie provider_urls będzie nadal działać, aby zapewnić zgodność wsteczną.

Dobrze znany plik, który obsługuje wiele adresów configURL, może wyglądać tak:

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

Dzięki temu możemy:

  1. Zachowuj wsteczną i do przodu zgodność z dotychczasowymi dobrze znanymi plikami oraz wcześniejszymi wersjami przeglądarek, które już działają na wolności.
  2. mieć dowolną liczbę plików konfiguracji – o ile wszystkie wskazują te same accounts_endpoint i login_url.
  3. Nie mogą mieć możliwości dodania entropii do żądania pobierania z danymi uwierzytelniania wysłanego do obiektu accounts_endpoint, ponieważ musi być ona określona na poziomie „.well-known”.

Obsługa wielu adresów URL konfiguracji jest opcjonalna, a istniejące implementacje FedCM mogą pozostać bez zmian.

Etykiety niestandardowe na koncie

Etykiety kont niestandardowych pozwalają dostawcom usług FedCM dodawać adnotacje do kont, dzięki czemu dostawcy RP mogą filtrować te konta przez określenie etykiety w pliku konfiguracji. Podobne filtrowanie można było filtrować za pomocą interfejsów Domain Hint API i Login Hint API przez określenie ich w wywołaniu navigator.credentials.get(). Etykiety kont niestandardowych mogą jednak filtrować użytkowników przez określenie pliku konfiguracji, co jest szczególnie przydatne w przypadku wielu adresów configURL. Etykiety konta niestandardowego różnią się też tym, że są dostarczane z serwera dostawcy tożsamości, a nie z grupy objętej ograniczeniami (np. z instrukcji logowania lub domeny).

Przykład

Dostawca tożsamości obsługuje 2 adresy URL konfiguracji odpowiednio dla klientów indywidualnych i firm. Plik konfiguracji klienta ma etykietę 'consumer', a plik konfiguracji firmy – etykietę 'enterprise'.

W takiej konfiguracji znany plik zawiera accounts_endpoint i login_url, który zezwala na wiele adresów configURL.

{
  "provider_urls": [ "https://idp.example/fedcm.json" ],
  "accounts_endpoint": "https://idp.example/accounts",
  "login_url": "https://idp.example/login"
}

Jeśli w znanym pliku podano accounts_endpoint, provider_urls są ignorowane. RP może wskazywać bezpośrednio odpowiednie pliki konfiguracyjne w wywołaniu navigator.credentials.get().

Plik konfiguracji konsumenta znajduje się pod adresem https://idp.example/fedcm.json, który zawiera właściwość accounts, która określa 'consumer' za pomocą include.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "consumer"
  }
}

Plik konfiguracji firmy znajduje się pod adresem https://idp.example/enterprise/fedcm.json. Zawiera on właściwość accounts, która wskazuje 'enterprise' za pomocą include.

{
  "accounts_endpoint": "https://idp.example/accounts",
  "client_metadata_endpoint": "/enterprise/client_metadata",
  "login_url": "https://idp.example/login",
  "id_assertion_endpoint": "/assertion",
  "accounts": {
    "include": "enterprise"
  }
}

Wspólny punkt końcowy kont dostawcy tożsamości (w tym przykładzie https://idp.example/accounts) zwraca w tablicy dla każdego konta listę kont zawierających właściwość etykiet z przypisaną wartością labels. Poniżej znajdziesz przykładową odpowiedź dla użytkownika, który ma 2 konta. Pierwszy z nich jest przeznaczony dla klientów indywidualnych, a drugi dla przedsiębiorstw:

{
 "accounts": [{
   "id": "123",
   "given_name": "John",
   "name": "John Doe",
   "email": "john_doe@idp.example",
   "picture": "https://idp.example/profile/123",
   "labels": ["consumer"]
  }], [{
   "id": "4567",
   "given_name": "Jane",
   "name": "Jane Doe",
   "email": "jane_doe@idp.example",
   "picture": "https://idp.example/profile/4567",
   "labels": ["enterprise"]
  }]
}

Gdy RP chce zezwolić użytkownikom 'enterprise' na logowanie się, może podać adres 'enterprise' configURL 'https://idp.example/enterprise/fedcm.json' w wywołaniu navigator.credentials.get():

let { token } = await navigator.credentials.get({
  identity: {
    providers: [{
      clientId: '1234',
      nonce: '234234',
      configURL: 'https://idp.example/enterprise/fedcm.json',
    },
  }
});

W związku z tym użytkownik może zalogować się tylko przy użyciu identyfikatora konta '4567'. Identyfikator konta '123' jest dyskretnie ukrywany przez przeglądarkę, więc użytkownik nie otrzyma konta, które nie jest obsługiwane przez dostawcę tożsamości w tej witrynie.

Wersja próbna origin: FedCM jako sygnał zaufania dla interfejsu Storage Access API

Chrome 126 rozpoczyna testowanie origin FedCM jako sygnału zaufania dla interfejsu Storage Access API. W związku z tą zmianą wcześniejsze uprawnienia przyznane przez FedCM stają się ważnym powodem, aby automatycznie zatwierdzać prośby o dostęp do pamięci masowej wysyłane przez interfejsy Storage Access API.

Jest to przydatne, gdy umieszczony element iframe chce uzyskać dostęp do spersonalizowanych zasobów, np. gdy plik idp.example jest umieszczony w pliku rp.example i musi wyświetlić spersonalizowany zasób. Jeśli przeglądarka ogranicza dostęp do plików cookie innych firm, to nawet jeśli użytkownik jest zalogowany do rp.example przy użyciu idp.example z użyciem FedCM, osadzony element iframe idp.example nie będzie mógł żądać spersonalizowanych zasobów, ponieważ nie będą one zawierać plików cookie innych firm.

Aby to osiągnąć, idp.example musi uzyskać dostęp do pamięci za pośrednictwem elementu iframe umieszczonego w witrynie. Można to uzyskać tylko za pomocą promptu z prośbą o zgodę.

Gdy FedCM jest sygnałem zaufania dla interfejsu Storage Access API, funkcje kontroli uprawnień interfejsu Storage Access API nie tylko akceptują uprawnienia przyznane w ramach prośby o dostęp do pamięci masowej, ale także te przyznane w ramach promptu FedCM.

// In top-level rp.example:

// Ensure FedCM permission has been granted.
const cred = await navigator.credentials.get({
  identity: {
    providers: [{
      configURL: 'https://idp.example/fedcm.json',
      clientId: '123',
    }],
  },
  mediation: 'optional',
});

// In an embedded IdP iframe:

// No user gesture is needed to call this, and the call will be auto-granted.
await document.requestStorageAccess();

// This returns `true`.
const hasAccess = await document.hasStorageAccess();

Gdy użytkownik zaloguje się w FedCM, uprawnienie zostanie przyznane automatycznie, dopóki uwierzytelnianie FedCM będzie aktywne. Oznacza to, że gdy użytkownik się rozłączy, wyświetli się prośba o pozwolenie.

Weź udział w testowaniu origin

Możesz wypróbować pakiet FedCM Continuation API lokalnie, włączając flagę Chrome chrome://flags#fedcm-authz w przeglądarce Chrome 126 lub nowszej. Możesz też wypróbować FedCM jako sygnał zaufania dla interfejsu Storage Access API lokalnie, włączając #fedcm-with-storage-access-api w Chrome 126 lub nowszej wersji.

Te funkcje są również dostępne jako wersje testowe origin. Wersje próbne origin pozwalają testować nowe funkcje i przesyłać opinie na temat ich użyteczności, praktyczności i skuteczności. Więcej informacji znajdziesz w artykule o pierwszych krokach z testowaniem origin.

Aby wypróbować wersję próbną pakietu origin FedCM Continuation API, utwórz 2 tokeny próbne:

Jeśli chcesz włączyć interfejs Continuation API wraz z przepływem przycisków, włącz też test origin interfejsu Button Mode API:

Aby wypróbować FedCM jako sygnał zaufania na potrzeby testowania origin interfejsu Storage Access API:

Testy origin pakietu interfejsu Continuation API oraz FedCM jako sygnał zaufania na potrzeby testowania origin interfejsu Storage Access API są dostępne w Chrome 126.

Rejestrowanie wersji próbnej origin innych firm na potrzeby RP

  1. Otwórz stronę rejestracji wersji próbnej origin.
  2. Kliknij przycisk Zarejestruj i wypełnij formularz, aby poprosić o token.
  3. Wpisz źródło dostawcy tożsamości jako Web Origin.
  4. Zaznacz Dopasowanie zewnętrzne, aby wstawić token za pomocą JavaScriptu w innych źródłach.
  5. Kliknij Prześlij.
  6. Umieść wydany token na stronie internetowej innej firmy.

Aby umieścić token w witrynie zewnętrznej, dodaj poniższy kod do biblioteki JavaScript lub pakietu SDK dostawcy tożsamości udostępnianego ze źródła.

const tokenElement = document.createElement('meta');
tokenElement.httpEquiv = 'origin-trial';
tokenElement.content = 'TOKEN_GOES_HERE';
document.head.appendChild(tokenElement);

Zastąp TOKEN_GOES_HERE własnym tokenem.