CINXE.COM

Federated Credential Management API Developer's Guide  |  Privacy Sandbox  |  Google for Developers

<!doctype html> <html lang="en" dir="ltr"> <head> <meta name="google-signin-client-id" content="721724668570-nbkv1cfusk7kk4eni4pjvepaus73b13t.apps.googleusercontent.com"> <meta name="google-signin-scope" content="profile email https://www.googleapis.com/auth/developerprofiles https://www.googleapis.com/auth/developerprofiles.award"> <meta property="og:site_name" content="Google for Developers"> <meta property="og:type" content="website"><meta name="theme-color" content="#fff"><meta charset="utf-8"> <meta content="IE=Edge" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="manifest" href="/_pwa/developers/manifest.json" crossorigin="use-credentials"> <link rel="preconnect" href="//www.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.gstatic.com" crossorigin> <link rel="preconnect" href="//fonts.googleapis.com" crossorigin> <link rel="preconnect" href="//apis.google.com" crossorigin> <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"> <link rel="stylesheet" href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/developers/css/app.css"> <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/developers/images/favicon-new.png"> <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/developers/images/touchicon-180-new.png"><link rel="canonical" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide"><link rel="search" type="application/opensearchdescription+xml" title="Google for Developers" href="https://developers.google.com/s/opensearch.xml"> <link rel="alternate" hreflang="en" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide" /><link rel="alternate" hreflang="x-default" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide" /><link rel="alternate" hreflang="ar" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=ar" /><link rel="alternate" hreflang="bn" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=bn" /><link rel="alternate" hreflang="zh-Hans" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=zh-tw" /><link rel="alternate" hreflang="fa" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=fa" /><link rel="alternate" hreflang="fr" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=fr" /><link rel="alternate" hreflang="de" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=de" /><link rel="alternate" hreflang="he" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=he" /><link rel="alternate" hreflang="hi" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=hi" /><link rel="alternate" hreflang="id" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=id" /><link rel="alternate" hreflang="it" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=it" /><link rel="alternate" hreflang="ja" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=ja" /><link rel="alternate" hreflang="ko" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=ko" /><link rel="alternate" hreflang="pl" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=pl" /><link rel="alternate" hreflang="pt-BR" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=pt-br" /><link rel="alternate" hreflang="ru" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=ru" /><link rel="alternate" hreflang="es-419" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=es-419" /><link rel="alternate" hreflang="th" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=th" /><link rel="alternate" hreflang="tr" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=tr" /><link rel="alternate" hreflang="vi" href="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide?hl=vi" /><title>Federated Credential Management API Developer&#39;s Guide &nbsp;|&nbsp; Privacy Sandbox &nbsp;|&nbsp; Google for Developers</title> <meta property="og:title" content="Federated Credential Management API Developer&#39;s Guide &nbsp;|&nbsp; Privacy Sandbox &nbsp;|&nbsp; Google for Developers"><meta property="og:url" content="https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide"><meta property="og:image" content="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-for-developers.png"> <meta property="og:image:width" content="1600"> <meta property="og:image:height" content="900"><meta property="og:locale" content="en"><meta name="twitter:card" content="summary_large_image"><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Article", "dateModified": "2024-04-18", "headline": "Federated Credential Management API Developer&#39;s Guide" } </script><script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [{ "@type": "ListItem", "position": 1, "name": "Privacy Sandbox", "item": "https://developers.google.com/privacy-sandbox" },{ "@type": "ListItem", "position": 2, "name": "Federated Credential Management API Developer&amp;#39;s Guide", "item": "https://developers.google.com/privacy-sandbox/cookies/fedcm-developer-guide" }] } </script> <link rel="stylesheet" href="/extras.css"></head> <body class="" template="page" theme="white" type="article" layout="docs" concierge='closed' display-toc pending> <devsite-progress type="indeterminate" id="app-progress"></devsite-progress> <section class="devsite-wrapper"> <devsite-cookie-notification-bar></devsite-cookie-notification-bar><devsite-header role="banner"> <div class="devsite-header--inner nocontent"> <div class="devsite-top-logo-row-wrapper-wrapper"> <div class="devsite-top-logo-row-wrapper"> <div class="devsite-top-logo-row"> <button type="button" id="devsite-hamburger-menu" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Navigation menu button" visually-hidden aria-label="Open menu"> </button> <div class="devsite-product-name-wrapper"> <a href="https://developers.google.com/privacy-sandbox"> <div class="devsite-product-logo-container" size="medium" > <picture> <img class="devsite-product-logo" alt="Privacy Sandbox" src="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo.png" srcset="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_36.png 36w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_48.png 48w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_72.png 72w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_96.png 96w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_480.png 480w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_720.png 720w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_856.png 856w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_960.png 960w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_1440.png 1440w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_1920.png 1920w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_2880.png 2880w" sizes="64px" loading="lazy" > </picture> </div> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> <a href="https://developers.google.com/privacy-sandbox" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Upper Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Privacy Sandbox" > Privacy Sandbox </a> </li> </ul> </span> </div> <div class="devsite-top-logo-row-middle"> <div class="devsite-header-upper-tabs"> <devsite-tabs class="upper-tabs"> <nav class="devsite-tabs-wrapper" aria-label="Upper tabs"> <tab > <a href="https://developers.google.com/privacy-sandbox" track-metadata-eventdetail="https://developers.google.com/privacy-sandbox" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - overview" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" > Overview </a> </tab> <tab class="devsite-active"> <a href="https://developers.google.com/privacy-sandbox/cookies" track-metadata-eventdetail="https://developers.google.com/privacy-sandbox/cookies" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - cookies" track-metadata-module="primary nav" aria-label="Cookies, selected" data-category="Site-Wide Custom Events" data-label="Tab: Cookies" track-name="cookies" > Cookies </a> </tab> <tab > <a href="https://developers.google.com/privacy-sandbox/private-advertising" track-metadata-eventdetail="https://developers.google.com/privacy-sandbox/private-advertising" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - private advertising" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Private advertising" track-name="private advertising" > Private advertising </a> </tab> <tab > <a href="https://developers.google.com/privacy-sandbox/protections" track-metadata-eventdetail="https://developers.google.com/privacy-sandbox/protections" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - privacy protections" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Privacy protections" track-name="privacy protections" > Privacy protections </a> </tab> <tab > <a href="https://developers.google.com/privacy-sandbox/learn" track-metadata-eventdetail="https://developers.google.com/privacy-sandbox/learn" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - learn" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" > Learn </a> </tab> <tab > <a href="https://developers.google.com/privacy-sandbox/blog" track-metadata-eventdetail="https://developers.google.com/privacy-sandbox/blog" class="devsite-tabs-content gc-analytics-event " track-type="nav" track-metadata-position="nav - blog" track-metadata-module="primary nav" data-category="Site-Wide Custom Events" data-label="Tab: Blog" track-name="blog" > Blog </a> </tab> </nav> </devsite-tabs> </div> <devsite-search enable-signin enable-search enable-suggestions enable-query-completion project-name="Privacy Sandbox" tenant-name="Google for Developers" project-scope="/privacy-sandbox" url-scoped="https://developers.google.com/s/results/privacy-sandbox" > <form class="devsite-search-form" action="https://developers.google.com/s/results" method="GET"> <div class="devsite-search-container"> <button type="button" search-open class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Open search"></button> <div class="devsite-searchbox"> <input aria-activedescendant="" aria-autocomplete="list" aria-label="Search" aria-expanded="false" aria-haspopup="listbox" autocomplete="off" class="devsite-search-field devsite-search-query" name="q" placeholder="Search" role="combobox" type="text" value="" > <div class="devsite-search-image material-icons" aria-hidden="true"> </div> <div class="devsite-search-shortcut-icon-container" aria-hidden="true"> <kbd class="devsite-search-shortcut-icon">/</kbd> </div> </div> </div> </form> <button type="button" search-close class="devsite-search-button devsite-header-icon-button button-flat material-icons" aria-label="Close search"></button> </devsite-search> </div> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es" >Español</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> <a class="devsite-header-link devsite-top-button button gc-analytics-event" href="//privacysandbox.com/" data-category="Site-Wide Custom Events" data-label="Site header link" > Home </a> <devsite-user enable-profiles fp-auth id="devsite-user"> <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span> </devsite-user> </div> </div> </div> <div class="devsite-collapsible-section devsite-header-no-lower-tabs "> <div class="devsite-header-background"> <div class="devsite-product-id-row" > <div class="devsite-product-description-row"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> <a href="https://developers.google.com/privacy-sandbox/cookies" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Lower Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="" > Cookies </a> </li> </ul> </div> </div> </div> </div> </div> </devsite-header> <devsite-book-nav scrollbars > <div class="devsite-book-nav-filter" > <span class="filter-list-icon material-icons" aria-hidden="true"></span> <input type="text" placeholder="Filter" aria-label="Type to filter" role="searchbox"> <span class="filter-clear-button hidden" data-title="Clear filter" aria-label="Clear filter" role="button" tabindex="0"></span> </div> <nav class="devsite-book-nav devsite-nav nocontent" aria-label="Side menu"> <div class="devsite-mobile-header"> <button type="button" id="devsite-close-nav" class="devsite-header-icon-button button-flat material-icons gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Close navigation" aria-label="Close navigation"> </button> <div class="devsite-product-name-wrapper"> <a href="https://developers.google.com/privacy-sandbox"> <div class="devsite-product-logo-container" size="medium" > <picture> <img class="devsite-product-logo" alt="Privacy Sandbox" src="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo.png" srcset="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_36.png 36w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_48.png 48w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_72.png 72w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_96.png 96w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_480.png 480w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_720.png 720w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_856.png 856w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_960.png 960w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_1440.png 1440w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_1920.png 1920w, https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo_2880.png 2880w" sizes="64px" loading="lazy" > </picture> </div> </a> <span class="devsite-product-name"> <ul class="devsite-breadcrumb-list" > <li class="devsite-breadcrumb-item "> <a href="https://developers.google.com/privacy-sandbox" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Upper Header" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="Privacy Sandbox" > Privacy Sandbox </a> </li> </ul> </span> </div> </div> <div class="devsite-book-nav-wrapper"> <div class="devsite-mobile-nav-top"> <ul class="devsite-nav-list"> <li class="devsite-nav-item"> <a href="/privacy-sandbox" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Overview" track-name="overview" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Overview" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Overview </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/privacy-sandbox/cookies" class="devsite-nav-title gc-analytics-event devsite-nav-has-children devsite-nav-active" data-category="Site-Wide Custom Events" data-label="Tab: Cookies" track-name="cookies" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Cookies" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Cookies </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/privacy-sandbox/private-advertising" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Private advertising" track-name="private advertising" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Private advertising" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Private advertising </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/privacy-sandbox/protections" class="devsite-nav-title gc-analytics-event devsite-nav-has-children " data-category="Site-Wide Custom Events" data-label="Tab: Privacy protections" track-name="privacy protections" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Privacy protections" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Privacy protections </span> <span class="devsite-nav-icon material-icons" data-icon="forward" > </span> </a> </li> <li class="devsite-nav-item"> <a href="/privacy-sandbox/learn" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Learn" track-name="learn" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Learn" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Learn </span> </a> </li> <li class="devsite-nav-item"> <a href="/privacy-sandbox/blog" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Tab: Blog" track-name="blog" data-category="Site-Wide Custom Events" data-label="Responsive Tab: Blog" track-type="globalNav" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Blog </span> </a> </li> <li class="devsite-nav-item"> <a href="//privacysandbox.com/" class="devsite-nav-title gc-analytics-event " data-category="Site-Wide Custom Events" data-label="Responsive Tab: Home" track-type="navMenu" track-metadata-eventDetail="globalMenu" track-metadata-position="nav"> <span class="devsite-nav-text" tooltip > Home </span> </a> </li> </ul> </div> <div class="devsite-mobile-nav-bottom"> <ul class="devsite-nav-list" menu="_book"> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies" ><span class="devsite-nav-text" tooltip>About third-party cookies</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Prepare for changes</span> </div></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/prepare/overview" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/prepare/overview" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/prepare/overview" ><span class="devsite-nav-text" tooltip>Overview</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/prepare/audit-cookies" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/prepare/audit-cookies" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/prepare/audit-cookies" ><span class="devsite-nav-text" tooltip>Audit cookies</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/prepare/test-for-breakage" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/prepare/test-for-breakage" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/prepare/test-for-breakage" ><span class="devsite-nav-text" tooltip>Test for breakage</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/prepare/debug" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/prepare/debug" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/prepare/debug" ><span class="devsite-nav-text" tooltip>Debug third-party cookie blocking</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Solutions</span> </div></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/chips" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/chips" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/chips" ><span class="devsite-nav-text" tooltip>CHIPS</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/chips-transition" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/chips-transition" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/chips-transition" ><span class="devsite-nav-text" tooltip>Transition to partitioned cookies</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/storage-access-api" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/storage-access-api" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/storage-access-api" ><span class="devsite-nav-text" tooltip>Storage Access API</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/related-website-sets" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/related-website-sets" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/related-website-sets" ><span class="devsite-nav-text" tooltip>Related Website Sets</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/related-website-sets-integration" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/related-website-sets-integration" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/related-website-sets-integration" ><span class="devsite-nav-text" tooltip>Related Website Sets Developer guide</span></a></li> <li class="devsite-nav-item devsite-nav-expandable"><div class="devsite-expandable-nav"> <a class="devsite-nav-toggle" aria-hidden="true"></a><div class="devsite-nav-title devsite-nav-title-no-path" tabindex="0" role="button"> <span class="devsite-nav-text" tooltip>Federated Credential Management API</span> </div><ul class="devsite-nav-section"><li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/fedcm" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/fedcm" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/fedcm" ><span class="devsite-nav-text" tooltip>Overview</span></a></li><li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/fedcm-developer-guide" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/fedcm-developer-guide" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/fedcm-developer-guide" ><span class="devsite-nav-text" tooltip>Developer guide</span></a></li><li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/fedcm-updates" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/fedcm-updates" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/fedcm-updates" ><span class="devsite-nav-text" tooltip>Updates</span></a></li><li class="devsite-nav-item"><a href="/privacy-sandbox/learn?api=federatedcredentialmanagement" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/learn?api=federatedcredentialmanagement" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/learn?api=federatedcredentialmanagement" ><span class="devsite-nav-text" tooltip>Tagged docs and blog posts</span></a></li></ul></div></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/storage-partitioning" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/storage-partitioning" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/storage-partitioning" ><span class="devsite-nav-text" tooltip>Storage partitioning</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Guides</span> </div></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/guides" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/guides" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/guides" ><span class="devsite-nav-text" tooltip>Overview</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/guides/identity" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/guides/identity" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/guides/identity" ><span class="devsite-nav-text" tooltip>Identity</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/guides/embeds" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/guides/embeds" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/guides/embeds" ><span class="devsite-nav-text" tooltip>Embeds</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/resources/case-studies/times-internet" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/resources/case-studies/times-internet" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/resources/case-studies/times-internet" ><span class="devsite-nav-text" tooltip>Case study: Times Internet</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/resources/case-studies/mercado-libre" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/resources/case-studies/mercado-libre" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/resources/case-studies/mercado-libre" ><span class="devsite-nav-text" tooltip>Case study: Mercado Libre</span></a></li> <li class="devsite-nav-item devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path"> <span class="devsite-nav-text" tooltip>Temporary exceptions</span> </div></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/temporary-exceptions/preserving-critical-user-experiences" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/temporary-exceptions/preserving-critical-user-experiences" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/temporary-exceptions/preserving-critical-user-experiences" ><span class="devsite-nav-text" tooltip>Overview</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/temporary-exceptions/grace-period" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/temporary-exceptions/grace-period" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/temporary-exceptions/grace-period" ><span class="devsite-nav-text" tooltip>Grace period</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/temporary-exceptions/grace-period-opt-out" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/temporary-exceptions/grace-period-opt-out" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/temporary-exceptions/grace-period-opt-out" ><span class="devsite-nav-text" tooltip>Grace period opt out</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/dashboard" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/dashboard" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/dashboard" ><span class="devsite-nav-text" tooltip>Compatibility lookup tool</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/temporary-exceptions/storage-partitioning-deprecation-trial" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/temporary-exceptions/storage-partitioning-deprecation-trial" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/temporary-exceptions/storage-partitioning-deprecation-trial" ><span class="devsite-nav-text" tooltip>Storage Partitioning deprecation trial</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/temporary-exceptions/heuristics-based-exceptions" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/temporary-exceptions/heuristics-based-exceptions" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/temporary-exceptions/heuristics-based-exceptions" ><span class="devsite-nav-text" tooltip>Heuristics based exceptions</span></a></li> <li class="devsite-nav-item"><a href="/privacy-sandbox/cookies/temporary-exceptions/chrome-enterprise" class="devsite-nav-title gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Book nav link, pathname: /privacy-sandbox/cookies/temporary-exceptions/chrome-enterprise" track-type="bookNav" track-name="click" track-metadata-eventdetail="/privacy-sandbox/cookies/temporary-exceptions/chrome-enterprise" ><span class="devsite-nav-text" tooltip>Chrome Enterprise policies</span></a></li> </ul> </div> </div> </nav> </devsite-book-nav> <section id="gc-wrapper"> <main role="main" class="devsite-main-content" has-book-nav > <devsite-content> <article class="devsite-article"> <div class="devsite-article-meta nocontent" role="navigation"> <ul class="devsite-breadcrumb-list" aria-label="Breadcrumb"> <li class="devsite-breadcrumb-item "> <a href="https://developers.google.com/" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="1" track-type="globalNav" track-name="breadcrumb" track-metadata-position="1" track-metadata-eventdetail="" > Home </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developers.google.com/privacy-sandbox" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="2" track-type="globalNav" track-name="breadcrumb" track-metadata-position="2" track-metadata-eventdetail="Privacy Sandbox" > Privacy Sandbox </a> </li> <li class="devsite-breadcrumb-item "> <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div> <a href="https://developers.google.com/privacy-sandbox/cookies" class="devsite-breadcrumb-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Breadcrumbs" data-value="3" track-type="globalNav" track-name="breadcrumb" track-metadata-position="3" track-metadata-eventdetail="" > Cookies </a> </li> </ul> <devsite-thumb-rating position="header"> </devsite-thumb-rating> </div> <devsite-feedback position="header" project-name="Privacy Sandbox" product-id="5335444" bucket="" context="" version="t-devsite-webserver-20241114-r00-rc02.464922260396498922" data-label="Send Feedback Button" track-type="feedback" track-name="sendFeedbackLink" track-metadata-position="header" class="nocontent" disable-product-feedback project-icon="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo.png" > <button> Send feedback </button> </devsite-feedback> <h1 class="devsite-page-title" tabindex="-1"> Federated Credential Management API Developer&#39;s Guide </h1> <devsite-feature-tooltip ack-key="AckCollectionsBookmarkTooltipDismiss" analytics-category="Site-Wide Custom Events" analytics-action-show="Callout Profile displayed" analytics-action-close="Callout Profile dismissed" analytics-label="Create Collection Callout" class="devsite-page-bookmark-tooltip nocontent" dismiss-button="true" id="devsite-collections-dropdown" dismiss-button-text="Dismiss" close-button-text="Got it"> <devsite-bookmark></devsite-bookmark> <span slot="popout-heading"> Stay organized with collections </span> <span slot="popout-contents"> Save and categorize content based on your preferences. </span> </devsite-feature-tooltip> <div class="devsite-page-title-meta"><devsite-view-release-notes></devsite-view-release-notes></div> <devsite-toc class="devsite-nav" depth="2" devsite-toc-embedded > </devsite-toc> <div class="devsite-article-body clearfix "> <p>Learn how to use FedCM for privacy-preserving identity federation.</p> <p><a href="/privacy-sandbox/cookies/fedcm">FedCM (Federated Credential Management)</a> is a privacy-preserving approach to federated identity services (such as &quot;Sign in with...&quot;) where users can log into sites without sharing their personal information with the identity service or the site.</p> <p>To learn more about FedCM use cases, user flows, and API roadmap check out <a href="/privacy-sandbox/cookies/fedcm">the introduction to FedCM API</a>.</p> <h2 id="fedcm_development_environment" data-text="FedCM development environment" tabindex="-1">FedCM development environment</h2> <p>You need a secure context (HTTPS or localhost) both on the IdP and RP in Chrome to use the FedCM.</p> <h3 id="remote-debug-android" data-text="Debug code on Chrome on Android" tabindex="-1">Debug code on Chrome on Android</h3> <p>Set up and run a server locally to debug your FedCM code. You can <a href="https://developer.chrome.com/docs/devtools/remote-debugging/local-server/">access this server</a> in Chrome on an Android device connected using a USB cable with port forwarding.</p> <p>You can use DevTools on desktop to debug Chrome on Android by following the instructions at <a href="https://developer.chrome.com/docs/devtools/remote-debugging/">Remote debug Android devices</a>.</p> <h3 id="block-third-party-cookies" data-text="Block third-party cookies on Chrome" tabindex="-1">Block third-party cookies on Chrome</h3> <figure style="text-align:center; width: 300px; margin: auto;"> <img src="/static/privacy-sandbox/assets/images/simulate-third-party-cook-8416bea1ab2b.png" alt="Block third-party cookies from Chrome settings" width="800" height="908"> <figcaption>Block third-party cookies from Chrome settings</figcaption> </figure> <p>You can test how FedCM works without third-party cookies on Chrome before it&#39;s actually enforced.</p> <p>To block third-party cookies, use <a href="https://support.google.com/chrome/answer/95464">Incognito mode</a>, or choose &quot;Block third-party cookies&quot; in your desktop settings at <code translate="no" dir="ltr">chrome://settings/cookies</code> or on mobile by navigating to <strong>Settings</strong> &gt; <strong>Site settings</strong> &gt; <strong>Cookies</strong>.</p> <h2 id="use-api" data-text="Use the FedCM API" tabindex="-1">Use the FedCM API</h2> <p>You integrate with FedCM by creating <a href="#well-known-file">a well-known file</a>, <a href="#idp-config-file">config file and endpoints</a> for <a href="#accounts-list-endpoint">accounts list</a>, <a href="#id-assertion-endpoint">assertion issuance</a> and optionally <a href="#client-metadata-endpoint">client metadata</a>.</p> <p>From there, FedCM exposes JavaScript APIs that RPs can use to <a href="#sign-into-rp">sign in</a> with the IdP.</p> <h3 id="well-known-file" data-text="Create a well-known file" tabindex="-1">Create a well-known file</h3> <p>To prevent <a href="https://github.com/fedidcg/FedCM/issues/230">trackers from abusing the API</a>, a well-known file must be served from <code translate="no" dir="ltr">/.well-known/web-identity</code> of <a href="https://web.dev/articles/same-site-same-origin#same_site_cross_site">eTLD+1</a> of the IdP.</p> <p>For example, if the IdP endpoints are served under <code translate="no" dir="ltr">https://accounts.idp.example/</code>, they must serve a well-known file at <code translate="no" dir="ltr">https://idp.example/.well-known/web-identity</code> as well as <a href="#idp-config-file">an IdP config file</a>. Here&#39;s an example well-known file content:</p> <pre class="prettyprint lang-json" translate="no" dir="ltr"><code translate="no" dir="ltr">{ &#34;provider_urls&#34;: [&#34;https://accounts.idp.example/config.json&#34;] } </code></pre> <p>The JSON file must contain the <code translate="no" dir="ltr">provider_urls</code> property with an array of <a href="#idp-config-file">IdP config file</a> URLs that can be <a href="#sign-into-rp">specified as a path part of <code translate="no" dir="ltr">configURL</code> in <code translate="no" dir="ltr">navigator.credentials.get</code> by RPs</a>. The number of URL strings in the array is limited to one, but this may change with your feedback in the future.</p> <aside class="tip"><b>Tip:</b> Upon FedCM development, testing or staging RP server domains may be the subdomains of the production IdP server. For example, the production IdP server is at <code translate="no" dir="ltr">idp.example</code> and both the staging RP server and the staging IdP server are at <code translate="no" dir="ltr">staging.idp.example</code>. However, since the well-known file must be placed at the root of the IdP server's eTLD+1, it has to be at <code translate="no" dir="ltr">idp.example/.well-known/web-identity</code> and it's the production server. Since it's not necessarily possible for developers to place files in the production environment while under development, this prevents them from testing FedCM. If the RP domain and IdP domain are the same, Chrome can skip checking the well-known file starting from Chrome 122. You can also bypass the <code translate="no" dir="ltr">configURL</code> check by enabling <code translate="no" dir="ltr">chrome://flags#fedcm-without-well-known-enforcement</code> flag. This is useful when your development environment uses a DNS that is not publicly accessible. </aside> <h3 id="idp-config-file" data-text="Create an IdP config file and endpoints" tabindex="-1">Create an IdP config file and endpoints</h3> <p>The IdP config file provides a list of required endpoints for the browser. IdPs will host this config file and the required endpoints and URLs. All JSON responses must be served with <code translate="no" dir="ltr">application/json</code> content-type.</p> <p>The config file&#39;s URL is determined by the values provided to the <a href="#sign-into-rp"><code translate="no" dir="ltr">navigator.credentials.get</code> call executed on an RP</a>.</p> <pre class="prettyprint lang-javascript" translate="no" dir="ltr"><code translate="no" dir="ltr">const credential = await navigator.credentials.get({ identity: { context: &#39;signup&#39;, providers: [{ configURL: &#39;https://accounts.idp.example/config.json&#39;, clientId: &#39;********&#39;, nonce: &#39;******&#39; }] } }); const { token } = credential; </code></pre> <p>Specify a full URL of the IdP config file location as a <code translate="no" dir="ltr">configURL</code>. When <a href="#sign-into-rp"><code translate="no" dir="ltr">navigator.credentials.get()</code> is called</a> on the RP, the browser fetches the config file with a <code translate="no" dir="ltr">GET</code> request without the <code translate="no" dir="ltr">Origin</code> header or the <code translate="no" dir="ltr">Referer</code> header. The request doesn&#39;t have cookies and doesn&#39;t follow redirects. This effectively prevents the IdP from learning who made the request and which RP is attempting to connect. For example:</p> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">GET /config.json HTTP/1.1 Host: accounts.idp.example Accept: application/json Sec-Fetch-Dest: webidentity </code></pre> <aside class="caution"> <strong>Caution:</strong> All requests sent from the browser using FedCM include a <code translate="no" dir="ltr">Sec-Fetch-Dest: webidentity</code> header to prevent <a href="https://portswigger.net/web-security/csrf">CSRF attacks</a>. The following IdP endpoints must confirm this header is included: <ul> <li>accounts endpoint</li> <li>ID assertion endpoint</li> <li>disconnect endpoint</li> </ul> </aside> <p>The browser expects a JSON response from the IdP which includes the following properties:</p> <table class="with-heading-tint with-borders"> <thead> <tr> <th>Property</th> <th>Description</th> </tr> </thead> <tr> <td><code translate="no" dir="ltr">accounts_endpoint</code> (required)</td> <td>URL for the <a href="#accounts-list-endpoint">accounts endpoint</a>.</td> </tr> <tr> <td><code translate="no" dir="ltr">client_metadata_endpoint</code> (optional)</td> <td>URL for the <a href="#client-metadata-endpoint">client metadata endpoint</a>.</td> </tr> <tr> <td><code translate="no" dir="ltr">id_assertion_endpoint</code> (required)</td> <td>URL for the <a href="#id-assertion-endpoint">ID assertion endpoint</a>.</td> </tr> <tr> <td><code translate="no" dir="ltr">disconnect</code> (optional)</td> <td>URL for the <a href="#disconnect">disconnect endpoint</a>.</td> </tr> <tr> <td><code translate="no" dir="ltr">login_url</code> (required)</td> <td>The <a href="#login-url">login page URL</a> for the user to sign in to the IdP.</td> </tr> <tr> <td><code translate="no" dir="ltr">branding</code> (optional)</td> <td>Object which contains various branding options.</td> </tr> <tr> <td><code translate="no" dir="ltr">branding.background_color</code> (optional)</td> <td>Branding option which sets the background color of the "Continue as..." button. Use the relevant CSS syntax, namely <a href="https://drafts.csswg.org/css-color-4/#typedef-hex-color"><code translate="no" dir="ltr">hex-color</code></a>, <a href="https://drafts.csswg.org/css-color-5/#funcdef-hsl"><code translate="no" dir="ltr">hsl()</code></a>, <a href="https://drafts.csswg.org/css-color-5/#funcdef-rgb"><code translate="no" dir="ltr">rgb()</code></a>, or <a href="https://drafts.csswg.org/css-color-4/#typedef-named-color"><code translate="no" dir="ltr">named-color</code></a>.</td> </tr> <tr> <td><code translate="no" dir="ltr">branding.color</code> (optional)</td> <td>Branding option which sets the text color of the "Continue as..." button. Use the relevant CSS syntax, namely <a href="https://drafts.csswg.org/css-color-4/#typedef-hex-color"><code translate="no" dir="ltr">hex-color</code></a>, <a href="https://drafts.csswg.org/css-color-5/#funcdef-hsl"><code translate="no" dir="ltr">hsl()</code></a>, <a href="https://drafts.csswg.org/css-color-5/#funcdef-rgb"><code translate="no" dir="ltr">rgb()</code></a>, or <a href="https://drafts.csswg.org/css-color-4/#typedef-named-color"><code translate="no" dir="ltr">named-color</code></a>.</td> </tr> <tr> <td><code translate="no" dir="ltr">branding.icons</code> (optional)</td> <td>Branding option which sets the icon object, displayed in the sign-in dialog. The icon object is an array with two parameters: <ul> <li><code translate="no" dir="ltr">url</code> (required): URL of the icon image. This does not support SVG images.</li> <li><code translate="no" dir="ltr">size</code> (optional): icon dimensions, assumed by the application to be square and single resolution. This number must be greater than or equal to 25.</li> </ul> </td> </tr> </table> <p>RP could modify the string in the FedCM dialog UI using the <code translate="no" dir="ltr">identity.context</code> value for <code translate="no" dir="ltr">navigator.credentials.get()</code> to accommodate predefined authentication contexts. Optional property can be one of <code translate="no" dir="ltr">&quot;signin&quot;</code> (default), <code translate="no" dir="ltr">&quot;signup&quot;</code>, <code translate="no" dir="ltr">&quot;use&quot;</code> or <code translate="no" dir="ltr">&quot;continue&quot;</code>.</p> <figure style="width:487px; margin:auto;"> <img src="/static/privacy-sandbox/assets/images/RZwmFnyJChjlki8QsnBB.png" alt="How branding is applied to the FedCM dialog" width="487" height="244"> <figcaption>How branding is applied to the FedCM dialog</figcaption> </figure> <p>Here&#39;s an example response body from the IdP:</p> <pre class="prettyprint lang-json" translate="no" dir="ltr"><code translate="no" dir="ltr">{ &#34;accounts_endpoint&#34;: &#34;/accounts.php&#34;, &#34;client_metadata_endpoint&#34;: &#34;/client_metadata.php&#34;, &#34;id_assertion_endpoint&#34;: &#34;/assertion.php&#34;, &#34;disconnect_endpoint&#34;: &#34;/disconnect.php&#34;, &#34;login_url&#34;: &#34;/login&#34;, &#34;branding&#34;: { &#34;background_color&#34;: &#34;green&#34;, &#34;color&#34;: &#34;#FFEEAA&#34;, &#34;icons&#34;: [{ &#34;url&#34;: &#34;https://idp.example/icon.ico&#34;, &#34;size&#34;: 25 }] } } </code></pre> <p>Once the browser fetches the config file, it sends subsequent requests to the IdP endpoints:</p> <figure> <img src="/static/privacy-sandbox/assets/images/idp-endpoints-a67327f46da51.png" alt="IdP endpoints" width="800" height="1085"> <figcaption>IdP endpoints</figcaption> </figure> <aside class="caution"><strong>Caution:</strong><span> If the RP deploys <a href="https://developer.mozilla.org/docs/Web/HTTP/CSP">Content Security Policy (CSP)</a> on the page FedCM is called and enforce <code translate="no" dir="ltr">connect-src</code> directive, they must explicitly allow endpoints described in the config file.</span></aside> <h4 id="accounts-list-endpoint" data-text="Accounts endpoint" tabindex="-1">Accounts endpoint</h4> <p>The IdP&#39;s accounts endpoint returns a list of accounts that the user is signed in on the IdP. If the IdP supports multiple accounts, this endpoint will return all signed in accounts.</p> <p>The browser sends a <code translate="no" dir="ltr">GET</code> request with cookies with <code translate="no" dir="ltr">SameSite=None</code>, but without a <code translate="no" dir="ltr">client_id</code> parameter, the <code translate="no" dir="ltr">Origin</code> header or the <code translate="no" dir="ltr">Referer</code> header. This effectively prevents the IdP from learning which RP the user is trying to sign in to. For example:</p> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">GET /accounts.php HTTP/1.1 Host: accounts.idp.example Accept: application/json Cookie: 0x23223 Sec-Fetch-Dest: webidentity </code></pre> <p>Upon receiving the request, the server should:</p> <ol> <li>Verify that the request contains a <code translate="no" dir="ltr">Sec-Fetch-Dest: webidentity</code> HTTP header.</li> <li>Match the session cookies with the IDs of the already signed-in accounts.</li> <li>Respond with the list of accounts.</li> </ol> <p>The browser expects a JSON response that includes an <code translate="no" dir="ltr">accounts</code> property with an array of account information with following properties:</p> <table class="with-heading-tint with-borders"> <thead> <tr> <th>Property</th> <th>Description</th> </tr> </thead> <tr> <td><code translate="no" dir="ltr">id</code> (required)</td> <td>Unique ID of the user.</td> </tr> <tr> <td><code translate="no" dir="ltr">name</code> (required)</td> <td>Given and family name of the user.</td> </tr> <tr> <td><code translate="no" dir="ltr">email</code> (required)</td> <td>Email address of the user.</td> </tr> <tr> <td><code translate="no" dir="ltr">given_name</code> (optional)</td> <td>Given name of the user.</td> </tr> <tr> <td><code translate="no" dir="ltr">picture</code> (optional)</td> <td>URL of the user avatar image.</td> </tr> <tr> <td><code translate="no" dir="ltr">approved_clients</code> (optional)</td> <td>An array of RP client IDs which the user has registered with.</td> </tr> <tr> <td><code translate="no" dir="ltr">login_hints</code> (optional)</td> <td>An array of all possible filter types that the IdP supports to specify an account. The RP can invoke <code translate="no" dir="ltr">navigator.credentials.get()</code> with the <a href="#login-hint"><code translate="no" dir="ltr">loginHint</code></a> property to selectively show the specified account.</td> </tr> <tr> <td><code translate="no" dir="ltr">domain_hints</code> (optional)</td> <td>An array of all the domains the account is associated with. The RP can call <code translate="no" dir="ltr">navigator.credentials.get()</code> with a <a href="#domain-hint"><code translate="no" dir="ltr">domainHint</code></a> property to filter the accounts.</td> </tr> </table> <p>Example response body:</p> <pre class="prettyprint lang-json" translate="no" dir="ltr"><code translate="no" dir="ltr">{ &#34;accounts&#34;: [{ &#34;id&#34;: &#34;1234&#34;, &#34;given_name&#34;: &#34;John&#34;, &#34;name&#34;: &#34;John Doe&#34;, &#34;email&#34;: &#34;john_doe@idp.example&#34;, &#34;picture&#34;: &#34;https://idp.example/profile/123&#34;, &#34;approved_clients&#34;: [&#34;123&#34;, &#34;456&#34;, &#34;789&#34;], &#34;login_hints&#34;: [&#34;demo1&#34;, &#34;demo1@idp.example&#34;] }, { &#34;id&#34;: &#34;5678&#34;, &#34;given_name&#34;: &#34;Johnny&#34;, &#34;name&#34;: &#34;Johnny&#34;, &#34;email&#34;: &#34;johnny@idp.example&#34;, &#34;picture&#34;: &#34;https://idp.example/profile/456&#34;, &#34;approved_clients&#34;: [&#34;abc&#34;, &#34;def&#34;, &#34;ghi&#34;], &#34;login_hints&#34;: [&#34;demo2&#34;, &#34;demo2@idp.example&#34;], &#34;domain_hints&#34;: [&#34;corp.example&#34;] }] } </code></pre> <p>If the user is not signed in, respond with HTTP 401 (Unauthorized).</p> <p>The returned accounts list is consumed by the browser and won&#39;t be available to the RP.</p> <h4 id="client-metadata-endpoint" data-text="Client metadata endpoint" tabindex="-1">Client metadata endpoint</h4> <p>The IdP&#39;s client metadata endpoint returns the relying party&#39;s metadata such as the RP&#39;s privacy policy and terms of service. RPs should provide links to their privacy policy and terms of service to the IdP in advance. These links are displayed in the sign-in dialog when the user hasn&#39;t registered on the RP with the IdP yet.</p> <p>The browser sends a <code translate="no" dir="ltr">GET</code> request using the <code translate="no" dir="ltr">client_id</code> <a href="#sign-into-rp"><code translate="no" dir="ltr">navigator.credentials.get</code></a> without cookies. For example:</p> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">GET /client_metadata.php?client_id=1234 HTTP/1.1 Host: accounts.idp.example Origin: https://rp.example/ Accept: application/json Sec-Fetch-Dest: webidentity </code></pre> <p>Upon receiving the request, the server should:</p> <ol> <li>Determine the RP for the <code translate="no" dir="ltr">client_id</code>.</li> <li>Respond with the client metadata.</li> </ol> <p>The properties for the client metadata endpoint include:</p> <table class="with-heading-tint with-borders"> <thead> <tr> <th>Property</th> <th>Description</th> </tr> </thead> <tr> <td><code translate="no" dir="ltr">privacy_policy_url</code> (optional)</td> <td>RP privacy policy URL.</td> </tr> <tr> <td><code translate="no" dir="ltr">terms_of_service_url</code> (optional)</td> <td>RP terms of service URL.</td> </tr> </table> <p>The browser expects a JSON response from the endpoint:</p> <pre class="prettyprint lang-json" translate="no" dir="ltr"><code translate="no" dir="ltr">{ &#34;privacy_policy_url&#34;: &#34;https://rp.example/privacy_policy.html&#34;, &#34;terms_of_service_url&#34;: &#34;https://rp.example/terms_of_service.html&#34;, } </code></pre> <p>The returned client metadata is consumed by the browser and won&#39;t be available to the RP.</p> <h4 id="id-assertion-endpoint" data-text="ID assertion endpoint" tabindex="-1">ID assertion endpoint</h4> <p>The IdP&#39;s ID assertion endpoint returns an assertion for their signed-in user. When the user signs in to an RP website using <a href="#sign-into-rp"><code translate="no" dir="ltr">navigator.credentials.get()</code> call</a>, the browser sends a <code translate="no" dir="ltr">POST</code> request with cookies with <code translate="no" dir="ltr">SameSite=None</code> and a content-type of <code translate="no" dir="ltr">application/x-www-form-urlencoded</code> to this endpoint with the following information:</p> <table class="with-heading-tint with-borders"> <thead> <tr> <th>Property</th> <th>Description</th> </tr> </thead> <tr> <td><code translate="no" dir="ltr">client_id</code> (required)</td> <td>The RP's client identifier.</td> </tr> <tr> <td><code translate="no" dir="ltr">account_id</code> (required)</td> <td>The unique ID of the signing in user.</td> </tr> <tr> <td><code translate="no" dir="ltr">nonce</code> (optional)</td> <td>The request nonce, provided by the RP.</td> </tr> <tr> <td><code translate="no" dir="ltr">disclosure_text_shown</code></td> <td>Results in a string of <code translate="no" dir="ltr">"true"</code> or <code translate="no" dir="ltr">"false"</code> (rather than a boolean). The result is <code translate="no" dir="ltr">"false"</code> if the disclosure text was not shown. This happens when the RP's client ID was included in the <code translate="no" dir="ltr">approved_clients</code> property list of the response from the <a href="#accounts-list-endpoint">accounts endpoint</a> or if the browser has observed a sign-up moment in the past in the absence of <code translate="no" dir="ltr">approved_clients</code>.</td> </tr> <tr> <td><code translate="no" dir="ltr">is_auto_selected</code></td> <td>If <a href="#auto-reauthn">auto-reauthentication</a> is performed on the RP, <code translate="no" dir="ltr">is_auto_selected</code> indicates <code translate="no" dir="ltr">"true"</code>. Otherwise <code translate="no" dir="ltr">"false"</code>. This is helpful to support more security related features. For example, some users may prefer a higher security tier which requires explicit user mediation in authentication. If an IdP receives a token request without such mediation, they could handle the request differently. For example, return an error code such that the RP can call the FedCM API again with <code translate="no" dir="ltr">mediation: required</code>.</td> </tr> </table> <p>Example HTTP header:</p> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">POST /assertion.php HTTP/1.1 Host: accounts.idp.example Origin: https://rp.example/ Content-Type: application/x-www-form-urlencoded Cookie: 0x23223 Sec-Fetch-Dest: webidentity account_id=123&amp;client_id=client1234&amp;nonce=Ct60bD&amp;disclosure_text_shown=true&amp;is_auto_selected=true </code></pre> <p>Upon receiving the request, the server should:</p> <ol> <li>Respond to the request with <a href="https://web.dev/articles/cross-origin-resource-sharing">CORS (Cross-Origin Resource Sharing)</a>.</li> <li>Verify that the request contains a <code translate="no" dir="ltr">Sec-Fetch-Dest: webidentity</code> HTTP header.</li> <li>Match the <code translate="no" dir="ltr">Origin</code> header against the RP origin determine by the <code translate="no" dir="ltr">client_id</code>. Reject if they don&#39;t match.</li> <li>Match <code translate="no" dir="ltr">account_id</code> against the ID of the already signed-in account. Reject if they don&#39;t match.</li> <li>Respond with a token. If the request is rejected, respond with an <a href="#error-response">error response</a>.</li> </ol> <aside class="warning"><b>Warning:</b> The CORS request must be <a href="https://web.dev/articles/cross-origin-resource-sharing#share_credentials_with_cors">credentialed</a>, which means the <code translate="no" dir="ltr">Access-Control-Allow-Origin</code> response header must indicate an explicit origin rather than wildcard using <code translate="no" dir="ltr">"*"</code>. <pre class="prettyprint lang-http" translate="no" dir="ltr"> HTTP/1.1 200 OK Access-Control-Allow-Origin: https://rp.example Access-Control-Allow-Credentials: true </pre> </aside> <p>How the token is issued is up to the IdP, but in general, it&#39;s signed with information such as the account ID, client ID, issuer origin, <code translate="no" dir="ltr">nonce</code>, so that the RP can verify the token is genuine.</p> <aside class="warning"><strong>Warning:</strong><span> Since the domain verification on OAuth or OpenID Connect relies on a browser redirect, it&#39;s critical in FedCM that the IdP server checks an <code translate="no" dir="ltr">Origin</code> header value matches the RP&#39;s registered origin.</span></aside> <p>The browser expects a JSON response that includes the following property:</p> <table class="with-heading-tint with-borders"> <thead> <tr> <th>Property</th> <th>Description</th> </tr> </thead> <tr> <td><code translate="no" dir="ltr">token</code> (required)</td> <td>A token is a string that contains claims about the authentication.</td> </tr> </table> <pre class="prettyprint lang-json" translate="no" dir="ltr"><code translate="no" dir="ltr">{ &#34;token&#34;: &#34;***********&#34; } </code></pre> <p>The returned token is passed to the RP by the browser, so that the RP can validate the authentication.</p> <h5 id="error-response" data-text="Return an error response" tabindex="-1">Return an error response</h5> <p>The <a href="#id-assertion-endpoint"><code translate="no" dir="ltr">id_assertion_endpoint</code></a> can also return an &quot;error&quot; response, which has two optional fields:</p> <ul> <li><strong><code translate="no" dir="ltr">code</code></strong>: The IdP can choose one of the known errors from the <a href="https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1">OAuth 2.0 specified error list</a> (<code translate="no" dir="ltr">invalid_request</code>, <code translate="no" dir="ltr">unauthorized_client</code>, <code translate="no" dir="ltr">access_denied</code>, <code translate="no" dir="ltr">server_error</code> and <code translate="no" dir="ltr">temporarily_unavailable</code>) or use any arbitrary string. If the latter, Chrome renders the error UI with a generic error message and pass the code to the RP.</li> <li><strong><code translate="no" dir="ltr">url</code></strong>: It identifies a human-readable web page with information about the error to provide additional information about the error to users. This field is useful to users because browsers cannot provide rich error messages in a built-in UI. For example: links for next steps, or customer service contact information. If a user wants to learn more about the error details and how to fix it, they could visit the provided page from the browser UI for more details. The URL must be of the same-site as the IdP <code translate="no" dir="ltr">configURL</code>.</li> </ul> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">// id_assertion_endpoint response { &#34;error&#34; : { &#34;code&#34;: &#34;access_denied&#34;, &#34;url&#34; : &#34;https://idp.example/error?type=access_denied&#34; } } </code></pre><aside class="note"><strong>Note:</strong><span> Implementing the &quot;error&quot; response is optional. If an IdP doesn&#39;t notify the browser about the error type when it occurs, Chrome will show an error UI with a generic message. If the <code translate="no" dir="ltr">url</code> field is not provided, Chrome doesn&#39;t include <a href="#error-api">the <strong>More details</strong> button</a>.</span></aside> <h4 id="disconnect" data-text="Disconnect endpoint" tabindex="-1">Disconnect endpoint</h4> <p>By invoking <code translate="no" dir="ltr">IdentityCredential.disconnect()</code>, the browser sends a cross-origin <code translate="no" dir="ltr">POST</code> request with cookies with <code translate="no" dir="ltr">SameSite=None</code> and a content-type of <code translate="no" dir="ltr">application/x-www-form-urlencoded</code> to this disconnect endpoint with the following information:</p> <table class="with-heading-tint with-borders"> <thead> <tr> <th>Property</th> <th>Description</th> </tr> </thead> <tr> <td><code translate="no" dir="ltr">account_hint</code></td> <td>A hint for the IdP account..</td> </tr> <tr> <td><code translate="no" dir="ltr">client_id</code></td> <td>The RP's client identifier.</td> </tr> </table> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">POST /disconnect.php HTTP/1.1 Host: idp.example Origin: rp.example Content-Type: application/x-www-form-urlencoded Cookie: 0x123 Sec-Fetch-Dest: webidentity account_hint=account456&amp;client_id=rp123 </code></pre> <p>Upon receiving the request, the server should:</p> <ol> <li>Respond to the request with <a href="https://web.dev/articles/cross-origin-resource-sharing">CORS (Cross-Origin Resource Sharing)</a>.</li> <li>Verify that the request contains a <code translate="no" dir="ltr">Sec-Fetch-Dest: webidentity</code> HTTP header.</li> <li>Match the <code translate="no" dir="ltr">Origin</code> header against the RP origin determine by the <code translate="no" dir="ltr">client_id</code>. Reject if they don&#39;t match.</li> <li>Match <code translate="no" dir="ltr">account_hint</code> against the IDs of the already signed-in accounts.</li> <li>Disconnect the user account from the RP.</li> <li>Respond to the browser with the identified user account information in a JSON format.</li> </ol> <aside class="warning"><b>Warning:</b> The CORS request must be <a href="https://web.dev/articles/cross-origin-resource-sharing#share_credentials_with_cors">credentialed</a>, which means the <code translate="no" dir="ltr">Access-Control-Allow-Origin</code> response header must indicate an explicit origin rather than wildcard using <code translate="no" dir="ltr">"*"</code>. <pre class="prettyprint lang-http" translate="no" dir="ltr"> HTTP/1.1 200 OK Access-Control-Allow-Origin: https://rp.example Access-Control-Allow-Credentials: true </pre> </aside> <p>An example response JSON payload looks like this:</p> <pre class="prettyprint lang-json" translate="no" dir="ltr"><code translate="no" dir="ltr">{ &#34;account_id&#34;: &#34;account456&#34; } </code></pre> <p>Instead, if the IdP wishes the browser to disconnect all accounts associated with the RP, pass a string that does not match any account ID, for example <code translate="no" dir="ltr">&quot;*&quot;</code>.</p> <h4 id="login-url" data-text="Login URL" tabindex="-1">Login URL</h4> <p>With the <a href="#login-status-api">Login Status API</a>, the IdP must inform the user&#39;s login status to the browser. However, the status could be out of sync, such as when <a href="#idp-session-expires">the session expires</a>. In such a scenario, the browser can dynamically let the user sign in to the IdP through the login page URL specified with the <a href="#idp-config-file">idp config file</a>&#39;s <code translate="no" dir="ltr">login_url</code>.</p> <p>The FedCM dialog displays a message suggesting a sign in, as shown in the following image.</p> <figure style="max-width:400px; margin:auto;"> <img src="/static/privacy-sandbox/assets/images/blog/fedcm-120-1.png" alt="A" fedcm dialog suggesting to sign in to the idp." width="800"" height="449""> <figcaption>A FedCM dialog suggesting to sign in to the IdP.</figcaption> </figure> <p>When the user clicks the <strong>Continue</strong> button, the browser opens a popup window for the IdP&#39;s login page.</p> <figure> <img src="/static/privacy-sandbox/assets/images/fedcm-dialog-example.png" alt="An example FedCM dialog." width="900"> <figcaption>An example dialog shown after clicking on the sign in to the IdP button.</figcaption> </figure> <aside class="note"><strong>Note:</strong><span> The website can&#39;t control the size of the dialog before it&#39;s opened. By default, the size is set to 500 px in width and 600 px in height.</span></aside> <p>The dialog is a regular browser window that has first-party cookies. Whatever happens within the dialog is up to the IdP, and no window handles are available to make a cross-origin communication request to the RP page. After the user is signed in, the IdP should:</p> <ul> <li>Send the <code translate="no" dir="ltr">Set-Login: logged-in</code> header or call the <code translate="no" dir="ltr">navigator.login.setStatus(&quot;logged-in&quot;)</code> API to inform the browser that the user has been signed in.</li> <li>Call <code translate="no" dir="ltr">IdentityProvider.close()</code> to close the dialog.</li> </ul> <aside class="note"><strong>Note:</strong><span> Read <a href="#login-status-api">Inform the browser about the user&#39;s login status</a> to learn more about the <code translate="no" dir="ltr">Set-Login</code> HTTP header and <code translate="no" dir="ltr">IdentityProvider.close()</code> function.</span></aside> <figure> <video autoplay loop muted controls playsinline width="900" alt="An animation showing the UI as a user signs into an RP after signing in to the IdP using FedCM."> <source src="/static/privacy-sandbox/assets/videos/fedcm-sign-in-dialog.mp4" type="video/mp4" /> </video> <figcaption>A user signs into an RP after signing in to the IdP using FedCM.</figcaption> </figure> <h3 id="login-status-api" data-text="Inform the browser about the user's login status on the identity provider" tabindex="-1">Inform the browser about the user's login status on the identity provider</h3> <p>The <a href="https://github.com/fedidcg/login-status">Login Status API</a> is a mechanism where a website, especially an IdP, informs the browser the user&#39;s login status on the IdP. With this API, the browser can reduce unnecessary requests to the IdP and mitigate potential timing attacks.</p> <aside class="note"><strong>Note:</strong><span> FedCM introduces a credentialed request to the <a href="/privacy-sandbox/cookies/fedcm-developer-guide#accounts-list-endpoint">accounts list endpoint</a>. This request doesn&#39;t send data that identifies the requestor and doesn&#39;t allow passing-through data provided by the RP. Separately, the browser performs an uncredentialed request containing the RP information to the <code translate="no" dir="ltr">client_metadata_endpoint</code>, so the IdP server can correlate the uncredentialed request with the credentialed request (stochastically) using timestamps or other fingerprinting data. Read more details on <a href="https://github.com/fedidcg/FedCM/issues/447">GitHub</a>.</span></aside> <p>IdPs can signal the user&#39;s login status to the browser by sending an HTTP header or by calling a JavaScript API when the user is signed in on the IdP or when the user is signed out from all their IdP accounts. For each IdP (identified by its config URL) the browser keeps a tri-state variable representing the login state with possible values <code translate="no" dir="ltr">logged-in</code>, <code translate="no" dir="ltr">logged-out</code>, and <code translate="no" dir="ltr">unknown</code>. The default state is <code translate="no" dir="ltr">unknown</code>.</p> <p>To signal that the user is signed in, send an <code translate="no" dir="ltr">Set-Login: logged-in</code> HTTP header in a top-level navigation or a same-site subresource request at the IdP origin:</p> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">Set-Login: logged-in </code></pre> <p>Alternatively, call the JavaScript API <code translate="no" dir="ltr">navigator.login.setStatus(&quot;logged-in&quot;)</code> from the IdP origin in a top-level navigation:</p> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">navigator.login.setStatus(&#34;logged-in&#34;) </code></pre> <p>These calls record the user&#39;s login status as <code translate="no" dir="ltr">logged-in</code>. When the user&#39;s login status is set to <code translate="no" dir="ltr">logged-in</code>, the RP calling FedCM makes requests to the IdP&#39;s accounts endpoint and displays available accounts to the user in the FedCM dialog.</p> <p>To signal that the user is signed out from all their accounts, send <code translate="no" dir="ltr">Set-Login: logged-out</code> HTTP header in a top-level navigation or a same-site subresource request at the IdP origin:</p> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">Set-Login: logged-out </code></pre> <p>Alternatively, call the JavaScript API <code translate="no" dir="ltr">navigator.login.setStatus(&quot;logged-out&quot;)</code> from the IdP origin in a top-level navigation:</p> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">navigator.login.setStatus(&#34;logged-out&#34;) </code></pre> <p>These calls record the user&#39;s login status as <code translate="no" dir="ltr">logged-out</code>. When the user&#39;s login status is <code translate="no" dir="ltr">logged-out</code>, calling the FedCM silently fails without making a request to the IdP&#39;s accounts endpoint.</p> <p>The <code translate="no" dir="ltr">unknown</code> status is set before the IdP sends a signal using the Login Status API. <code translate="no" dir="ltr">Unknown</code> was introduced for a better transition, because a user may have already signed into the IdP when this API was shipped. The IdP may not have a chance to signal this to the browser by the time FedCM is first invoked. In this case, Chrome makes a request to the IdP&#39;s accounts endpoint and update the status based on the response from the accounts endpoint:</p> <ul> <li>If the endpoint returns a list of active accounts, update the status to <code translate="no" dir="ltr">logged-in</code> and open the FedCM dialog to show those accounts.</li> <li>If the endpoint returns no accounts, update the status to <code translate="no" dir="ltr">logged-out</code> and fail the FedCM call.</li> </ul> <aside class="note"> <b>Note:</b> Login status header can be sent from <a href="https://web.dev/articles/same-site-same-origin#same-site-cross-site">same-site</a> subresources as well, starting from Chrome 122. This is useful, for example, when a website that lets users enter their username and password on <code translate="no" dir="ltr">idp.example</code>, but the credentials are posted to <code translate="no" dir="ltr">login.idp.example</code> with <code translate="no" dir="ltr">fetch()</code>. The fetch response from <code translate="no" dir="ltr">login.idp.example</code> can still set the login status for <code translate="no" dir="ltr">idp.example</code> by sending <code translate="no" dir="ltr">Set-Login: logged-in</code> HTTP header. </aside> <h4 id="idp-session-expires" data-text="Let the user sign in through a dynamic login flow" tabindex="-1">Let the user sign in through a dynamic login flow</h4> <p>Even though the IdP keeps informing the user&#39;s login status to the browser, it could be out of sync, such as when the session expires. The browser tries to send a credentialed request to the accounts endpoint when the login status is <code translate="no" dir="ltr">logged-in</code>, but the server returns no accounts because the session is no longer available. In such a scenario, <a href="#login-url">the browser can dynamically let the user sign in to the IdP through a popup window</a>.</p> <aside> This dynamic login experience is intended for when an IdP session has expired without an explicit sign-out, causing the browser's login state to contradict the user's actual state. This isn't triggered for users who haven't signed in to the IdP yet. This flow is designed to cover the cases where the user's IdP login status on the browser is <code translate="no" dir="ltr">logged-in</code> but the IdP's <a href="#accounts-list-endpoint">accounts endpoint</a> returns no accounts. Assuming the <a href="#login-status-api">Login Status API</a> is called promptly, when FedCM is invoked, any of the following scenarios can occur: <ul> <li>If the user's login status is set to unknown, the status is updated (either <code translate="no" dir="ltr">logged-in</code> or <code translate="no" dir="ltr">logged-out</code>) depending on the IdP's response from the accounts endpoint. A dynamic login flow won't be triggered.</li> <li>If a user has signed in to the IdP in the browser and then explicitly signed out from the IdP, the dynamic login flow won't be triggered.</li> <li>If a user has signed in to the IdP in the browser, but the session expires without an explicit update to <code translate="no" dir="ltr">logged-out</code>, the dynamic login flow is triggered.</li> </ul> The Login Status API does not provide the ability for the RP to display a "Sign-in to the IdP" dialog to users who are not signed in to the IdP. This is a separate feature which may be added in the future. </aside> <h3 id="sign-into-rp" data-text="Sign in to the relying party with the identity provider" tabindex="-1">Sign in to the relying party with the identity provider</h3> <p>Once the IdP&#39;s configuration and endpoints are available, RPs can call <code translate="no" dir="ltr">navigator.credentials.get()</code> to request allowing users to sign in to the RP with the IdP.</p> <p><a name="feature-detection"></a></p> <p>Before calling the API, you need to confirm that <a href="https://developer.mozilla.org/docs/Web/API/FedCM_API#browser_compatibility">FedCM is available on the user&#39;s browser</a>. To check if FedCM is available, wrap this code around your FedCM implementation:</p> <pre class="prettyprint lang-javascript" translate="no" dir="ltr"><code translate="no" dir="ltr">if (&#39;IdentityCredential&#39; in window) { // If the feature is available, take action } </code></pre> <p>To request allowing users to sign in to the IdP from the RP, do the following, for example:</p> <pre class="prettyprint lang-javascript" translate="no" dir="ltr"><code translate="no" dir="ltr">const credential = await navigator.credentials.get({ identity: { providers: [{ configURL: &#39;https://accounts.idp.example/config.json&#39;, clientId: &#39;********&#39;, nonce: &#39;******&#39; }] } }); const { token } = credential; </code></pre> <p>The <code translate="no" dir="ltr">providers</code> property takes an array of <a href="https://www.w3.org/TR/fedcm/#browser-api-identity-provider-interface"><code translate="no" dir="ltr">IdentityProvider</code> objects</a> that have the following properties:</p> <table class="with-heading-tint with-borders"> <thead> <tr> <th>Property</th> <th>Description</th> </tr> </thead> <tr> <td><code translate="no" dir="ltr">configURL</code> (required)</td> <td>A full path of the IdP config file.</td> </tr> <tr> <td><code translate="no" dir="ltr">clientId</code> (required)</td> <td>The RP's client identifier, issued by the IdP.</td> </tr> <tr> <td><code translate="no" dir="ltr">nonce</code> (optional)</td> <td>A random string to ensure the response is issued for this specific request. Prevents replay attacks.</td> </tr> <tr> <td><code translate="no" dir="ltr">loginHint</code> (optional)</td> <td>By specifying one of <code translate="no" dir="ltr">login_hints</code> values provided by <a href="#accounts-list-endpoint">the accounts endpoints</a>, the FedCM dialog selectively shows the specified account.</td> </tr> <tr> <td><code translate="no" dir="ltr">domainHint</code> (optional)</td> <td>By specifying one of <code translate="no" dir="ltr">domain_hints</code> values provided by <a href="#accounts-list-endpoint">the accounts endpoints</a>, the FedCM dialog selectively show the specified account.</td> </tr> </table> <p>The browser handles sign-up and sign-in use cases differently depending on the existence of <code translate="no" dir="ltr">approved_clients</code> in the response from <a href="#accounts-list-endpoint">the accounts list endpoint</a>. The browser won&#39;t display a disclosure text <strong>&quot;To continue with ....&quot;</strong> if the user has already signed up to the RP.</p> <p>The sign-up state is determined based on whether the following conditions are fulfilled or not:</p> <ul> <li>If <code translate="no" dir="ltr">approved_clients</code> includes the RP&#39;s <code translate="no" dir="ltr">clientId</code>.</li> <li>If the browser remembers that the user has already signed up to the RP.</li> </ul> <figure> <video autoplay loop muted controls playsinline width="300" alt="An animation showing the UI as a user signs into a website with FedCM."> <source src="/static/privacy-sandbox/assets/videos/fedcm-sign-in-mobile.mp4" type="video/mp4" /> </video> <figcaption>A user signs into an RP using FedCM.</figcaption> </figure> <p>When the RP calls <code translate="no" dir="ltr">navigator.credentials.get()</code>, the following activities take place:</p> <ol> <li>The browser sends requests and fetches several documents: <ol> <li><a href="#well-known-file">The well-known file</a> and <a href="#idp-config-file">an IdP config file</a> which declare endpoints.</li> <li><a href="#accounts-list-endpoint">An accounts list</a>.</li> <li>Optional: URLs for the RP&#39;s privacy policy and terms of service, retrieved from the <a href="#client-metadata-endpoint">client metadata endpoint</a>.</li> </ol></li> <li>The browser displays the list of accounts that the user can use to sign-in, as well as the terms of service and privacy policy if available.</li> <li>Once the user chooses an account to sign in with, a request to <a href="#id-assertion-endpoint">the ID assertion endpoint</a> is sent to the IdP to retrieve a token.</li> <li>The RP can validate the token to authenticate the user.</li> </ol> <figure> <img src="/static/privacy-sandbox/assets/images/login-api-call-a55fdb8f753e8.png" alt="login API call" width="800" height="1085"> <figcaption>login API call</figcaption> </figure> <aside class="caution"><strong>Caution:</strong><span> FedCM is designed to not inform the RP of the user&#39;s IdP sign-in state until the user explicitly confirms to <strong>Continue as</strong> and signs in. This means RPs aren&#39;t informed of connection to the FedCM API if: the user isn&#39;t signed into the IdP, the accounts endpoint returns an empty list, or the endpoint returns an error.</span></aside> <p>RPs are expected to support browsers which don&#39;t support FedCM, therefore users should be able to use an existing, non-FedCM sign-in process. Until third-party cookies are no longer available in browsers, this should remain non-problematic.</p> <p>Once the token is validated by the RP server, the RP may register the user or let them sign-in and start a new session.</p> <h4 id="login-hint" data-text="Login Hint API" tabindex="-1">Login Hint API</h4> <p>After the user signs in, sometimes the relying party (RP) asks the user to reauthenticate. But the user may not be sure which account they&#39;ve been using. If the RP can specify which account to sign in with, it would be easier for the user to pick an account.</p> <p>RPs can selectively show a specific account by invoking <code translate="no" dir="ltr">navigator.credentials.get()</code> with the <code translate="no" dir="ltr">loginHint</code> property with one of <code translate="no" dir="ltr">login_hints</code> values fetched from <a href="#accounts-list-endpoint">the accounts list endpoint</a>, as shown in the following code sample:</p> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">return await navigator.credentials.get({ identity: { providers: [{ configURL: &#34;https://idp.example/manifest.json&#34;, clientId: &#34;123&#34;, nonce: nonce, loginHint : &#34;demo1@example.com&#34; }] } }); </code></pre> <p>When no accounts match the <code translate="no" dir="ltr">loginHint</code>, the FedCM dialog shows a login prompt, which allows the user to login to an IdP account matching the hint requested by the RP. When the user taps on the prompt, a popup window is opened with the login URL specified in the <a href="#idp-config-file">config file</a>. The link is then appended with the login hint and the domain hint query parameters.</p> <h4 id="domain-hint" data-text="Domain Hint API" tabindex="-1">Domain Hint API</h4> <p>There are cases where the RP already knows that only accounts associated with a certain domain are allowed to login to the site. This is particularly common in enterprise scenarios where the site being accessed is restricted to a corporate domain. To provide a better user experience, the FedCM API allows the RP to only show the accounts which may be used to login to the RP. This prevents scenarios where a user tries to login to the RP using an account outside of the corporate domain, only to be served with an error message later (or silence where the login did not work) because the right type of account was not used.</p> <p>RPs can selectively show only matching accounts by invoking <code translate="no" dir="ltr">navigator.credentials.get()</code> with the <code translate="no" dir="ltr">domainHint</code> property with one of <code translate="no" dir="ltr">domain_hints</code> values fetched from <a href="#accounts-list-endpoint">the accounts list endpoint</a>, as shown in the following code sample:</p> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">return await navigator.credentials.get({ identity: { providers: [{ configURL: &#34;https://idp.example/manifest.json&#34;, clientId: &#34;abc&#34;, nonce: nonce, domainHint : &#34;corp.example&#34; }] } }); </code></pre> <aside class="note"> <strong>Note:</strong> When <code translate="no" dir="ltr">domainHint: "any"</code> is used, Chrome filters out accounts which don't have any domains (that is, <code translate="no" dir="ltr">domain_hints</code> is not passed or is empty). For example, this allows use cases where the RP only allows managed accounts in its signup process. </aside> <p>When no accounts match the <code translate="no" dir="ltr">domainHint</code>, the FedCM dialog shows a login prompt, which allows the user to login to an IdP account matching the hint requested by the RP. When the user taps on the prompt, a popup window is opened with the login URL specified in the <a href="#idp-config-file">config file</a>. The link is then appended with the login hint and the domain hint query parameters.</p> <figure style="max-width:400px; margin:auto;"> <img src="/static/privacy-sandbox/assets/images/blog/fedcm-123.jpg" alt="An example login prompt when no accounts match the domainHint." width="806" height="410"> <figcaption>An example login prompt when no accounts match the <code translate="no" dir="ltr">domainHint</code>.</figcaption> </figure> <h4 id="error-api" data-text="Show an error message" tabindex="-1">Show an error message</h4> <p>Sometimes, the IdP may not be able to issue a token for legitimate reasons, such as when the client is unauthorized, the server is temporarily unavailable. If the IdP returns an &quot;error&quot; response, the RP can catch it, as well as Chrome notifies the user by showing a browser UI with the error information provided by the IdP.</p> <figure style="max-width:300px; margin:auto;"> <img src="/static/privacy-sandbox/assets/images/blog/fedcm-120-4.png" alt="A" fedcm dialog showing the error message after the user's sign-in attempt fails. the string is associated with the error type." width="600""> <figcaption>A FedCM dialog showing the error message after the user's sign-in attempt fails. The string is associated with <a href="#error-response">the error type</a>.</figcaption> </figure> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">try { const cred = await navigator.credentials.get({ identity: { providers: [ { configURL: &#34;https://idp.example/manifest.json&#34;, clientId: &#34;1234&#34;, }, ], } }); } catch (e) { const code = e.code; const url = e.url; } </code></pre> <h3 id="auto-reauthn" data-text="Auto-reauthenticate users after the initial authentication" tabindex="-1">Auto-reauthenticate users after the initial authentication</h3> <p><a href="https://github.com/fedidcg/FedCM/issues/429">FedCM auto-reauthentication</a> (&quot;auto-reauthn&quot; in short) can let users reauthenticate automatically, when they come back after their initial authentication using FedCM. &quot;The initial authentication&quot; here means the user creates an account or signs into the RP&#39;s website by tapping on the <strong>&quot;Continue as...&quot;</strong> button on FedCM&#39;s sign-in dialog for the first time on the same browser instance.</p> <p>While the explicit user experience makes sense before the user has created the federated account to prevent tracking (which is one of the main goals of FedCM), it is unnecessarily cumbersome after the user has gone through it once: after the user grants permission to allow communication between the RP and the IdP, there&#39;s no privacy or security benefit for enforcing another explicit user confirmation for something that they have already previously acknowledged.</p> <p>With auto-reauthn, the browser changes its behavior depending on the option you specify for the <code translate="no" dir="ltr">mediation</code> when calling <code translate="no" dir="ltr">navigator.credentials.get()</code>.</p> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">const cred = await navigator.credentials.get({ identity: { providers: [{ configURL: &#34;https://idp.example/fedcm.json&#34;, clientId: &#34;1234&#34;, }], }, mediation: &#39;optional&#39;, // this is the default }); // `isAutoSelected` is `true` if auto-reauthn was performed. const isAutoSelected = cred.isAutoSelected; </code></pre> <p>The <code translate="no" dir="ltr">mediation</code> is <a href="https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get#:%7E:text=mediation">a property in the Credential Management API</a>, it behaves in <a href="https://web.dev/articles/security-credential-management-retrieve-credentials">the same way</a> as it does for <a href="https://developer.mozilla.org/docs/Web/API/PasswordCredential">PasswordCredential</a> and <a href="https://developer.mozilla.org/docs/Web/API/FederatedCredential">FederatedCredential</a> and it&#39;s partially supported by <a href="https://developer.mozilla.org/docs/Web/API/PublicKeyCredential">PublicKeyCredential</a> as well. The property accepts the following four values:</p> <ul> <li><code translate="no" dir="ltr">&#39;optional&#39;</code>(default): Auto-reauthn if possible, requires a mediation if not. We recommend choosing this option on the sign-in page.</li> <li><code translate="no" dir="ltr">&#39;required&#39;</code>: Always requires a mediation to proceed, for example, clicking the &quot;Continue&quot; button on the UI. Choose this option if your users are expected to grant permission explicitly every time they need to be authenticated.</li> <li><code translate="no" dir="ltr">&#39;silent&#39;</code>: Auto-reauthn if possible, silently fail without requiring a mediation if not. We recommend choosing this option on the pages other than the dedicated sign-in page but where you want to keep users signed in—for example, an item page on a shipping website or an article page on a news website.</li> <li><code translate="no" dir="ltr">&#39;conditional&#39;</code>: Used for WebAuthn and not available for FedCM at the moment.</li> </ul> <p>With this call, auto-reauthn happens under the following conditions:</p> <ul> <li>FedCM is available to use. For example, the user has not <a href="#settings">disabled FedCM either globally</a> or for the RP in the settings.</li> <li>The user used only one account with FedCM API to sign into the website on this browser.</li> <li>The user is signed into the IdP with that account.</li> <li>The auto-reauthn didn&#39;t happen within the last 10 minutes.</li> <li>The RP hasn&#39;t called <a href="#prevent-silent-access"><code translate="no" dir="ltr">navigator.credentials.preventSilentAccess()</code></a> after the previous sign in.</li> </ul> <p>When these conditions are met, an attempt to automatically reauthenticate the user starts as soon as the FedCM <code translate="no" dir="ltr">navigator.credentials.get()</code> is invoked.</p> <p>When <code translate="no" dir="ltr">mediation: optional</code>, auto-reauthn may be <a href="/blog/fedcm-auto-reauthn#mediation-options">unavailable</a> due to reasons that only the browser knows; the RP can check whether auto-reauthn is performed by examining the <code translate="no" dir="ltr">isAutoSelected</code> property.</p> <p>This is helpful to evaluate the API performance and improve UX accordingly. Also, when it&#39;s unavailable, the user may be prompted to sign in with explicit user mediation, which is a flow with <code translate="no" dir="ltr">mediation: required</code>.</p> <figure> <video autoplay loop muted controls playsinline width="300" alt="An animation demonstrating the UI as a user automatically signs back into a website using FedCM"> <source src="/static/privacy-sandbox/assets/videos/fedcm-auto-reauth-mobile.mp4" type="video/mp4" /> </video> <figcaption>A user auto-reauthenticating through FedCM.</figcaption> </figure> <h4 id="prevent-silent-access" data-text="Enforce mediation with preventSilentAccess()" tabindex="-1">Enforce mediation with <code translate="no" dir="ltr">preventSilentAccess()</code></h4> <p>Auto-reauthenticating users immediately after they sign out wouldn&#39;t make for a very good user experience. That&#39;s why FedCM has a 10-minute quiet period after an auto-reauthn to prevent this behavior. This means that auto-reauthn happens at most once in every 10-minutes unless the user signs back in within 10-minutes. The RP should call <code translate="no" dir="ltr">navigator.credentials.preventSilentAccess()</code> to explicitly request the browser to disable auto-reauthn when a user signs out of the RP explicitly, for example, by clicking a sign-out button.</p> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">function signout() { navigator.credentials.preventSilentAccess(); location.href = &#39;/signout&#39;; } </code></pre> <h4 id="settings" data-text="Users can opt-out of auto-reauthn in settings" tabindex="-1">Users can opt-out of auto-reauthn in settings</h4> <p>Users can opt-out from auto-reauth from the settings menu:</p> <ul> <li>On desktop Chrome, go to <code translate="no" dir="ltr">chrome://password-manager/settings</code> &gt; Sign in automatically.</li> <li>On Android Chrome, open <strong>Settings</strong> &gt; <strong>Password Manager</strong> &gt; Tap on a cog at the top right corner &gt; Auto sign-in.</li> </ul> <p>By disabling the toggle, the user can opt-out from auto-reauthn behavior all together. This setting is stored and synchronized across devices, if the user is signed into a Google Account on the Chrome instance and synchronization is enabled.</p> <aside class="note"><strong>Note:</strong><span> Users can also <a href="/privacy-sandbox/cookies/fedcm#user-settings">opt-out from FedCM per domain</a>.</span></aside> <h3 id="disconnect_the_idp_from_the_rp" data-text="Disconnect the IdP from the RP" tabindex="-1">Disconnect the IdP from the RP</h3> <p>If a user has previously signed into the RP using the IdP through FedCM, the relationship is memorized by the browser locally as the list of connected accounts. The RP may initiate a disconnection by invoking the <code translate="no" dir="ltr">IdentityCredential.disconnect()</code> function. This function can be called from a top-level RP frame. The RP needs to pass a <code translate="no" dir="ltr">configURL</code>, the <code translate="no" dir="ltr">clientId</code> it uses under the IdP, and an <code translate="no" dir="ltr">accountHint</code> for the IdP to be disconnected. An account hint can be an arbitrary string as long as the disconnect endpoint can identify the account, for example an email address or user ID which does not necessarily match the account ID that the account list endpoint has provided:</p> <pre class="prettyprint lang-js" translate="no" dir="ltr"><code translate="no" dir="ltr">// Disconnect an IdP account &#34;account456&#34; from the RP &#34;https://idp.com/&#34;. This is invoked on the RP domain. IdentityCredential.disconnect({ configURL: &#34;https://idp.com/config.json&#34;, clientId: &#34;rp123&#34;, accountHint: &#34;account456&#34; }); </code></pre> <p><code translate="no" dir="ltr">IdentityCredential.disconnect()</code> returns a <code translate="no" dir="ltr">Promise</code>. This promise may throw an exception for the following reasons:</p> <ul> <li>The user hasn&#39;t signed in to the RP using the IdP through FedCM.</li> <li>The API is invoked from within an iframe without FedCM permissions policy.</li> <li>The configURL is invalid or missing the disconnect endpoint.</li> <li>Content Security Policy (CSP) check fails.</li> <li>There is a pending disconnect request.</li> <li>The user has disabled FedCM in the browser settings.</li> </ul> <p>When the <a href="#disconnect">IdP&#39;s disconnect endpoint returns a response</a>, the RP and the IdP are disconnected on the browser and the promise is resolved. The ID of the disconnected accounts are specified in <a href="#disconnect">the response from the disconnect endpoint</a>.</p> <aside class="note"><strong>Note:</strong><span> If no valid response from the disconnect endpoint is received or the account ID received does not match any account in the list of connected accounts, the user agent will remove <em>all</em> accounts matching the RP and IdP from the list of connected accounts.</span></aside> <h3 id="call_fedcm_from_within_a_cross-origin_iframe" data-text="Call FedCM from within a cross-origin iframe" tabindex="-1">Call FedCM from within a cross-origin iframe</h3> <p>FedCM can be invoked from within a cross-origin iframe using an <code translate="no" dir="ltr">identity-credentials-get</code> permissions policy, if the parent frame allows it. To do so, append the <code translate="no" dir="ltr">allow=&quot;identity-credentials-get&quot;</code> attribute to the iframe tag as follows:</p> <pre class="prettyprint lang-html" translate="no" dir="ltr"><code translate="no" dir="ltr">&lt;iframe src=&#34;https://fedcm-cross-origin-iframe.glitch.me&#34; allow=&#34;identity-credentials-get&#34;&gt;&lt;/iframe&gt; </code></pre> <p>You can see it in action in <a href="https://fedcm-top-frame.glitch.me/">an example</a>.</p> <p>Optionally, if the parent frame wants to restrict the origins to call FedCM, send a <code translate="no" dir="ltr">Permissions-Policy</code> header with a list of allowed origins.</p> <pre class="prettyprint lang-http" translate="no" dir="ltr"><code translate="no" dir="ltr">Permissions-Policy: identity-credentials-get=(self &#34;https://fedcm-cross-origin-iframe.glitch.me&#34;) </code></pre> <p>You can learn more about how the Permissions Policy works at <a href="https://developer.chrome.com/articles/permissions-policy/">Controlling browser features with Permissions Policy</a>.</p> </div> <devsite-recommendations display="in-page" hidden yield> </devsite-recommendations> <devsite-thumb-rating position="footer"> </devsite-thumb-rating> <devsite-feedback position="footer" project-name="Privacy Sandbox" product-id="5335444" bucket="" context="" version="t-devsite-webserver-20241114-r00-rc02.464922260396498922" data-label="Send Feedback Button" track-type="feedback" track-name="sendFeedbackLink" track-metadata-position="footer" class="nocontent" disable-product-feedback project-icon="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo.png" > <button> Send feedback </button> </devsite-feedback> <devsite-recommendations id="recommendations-link" yield></devsite-recommendations> <div class="devsite-floating-action-buttons"> </div> </article> <devsite-content-footer class="nocontent"> <p>Except as otherwise noted, the content of this page is licensed under the <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 License</a>, and code samples are licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>. For details, see the <a href="https://developers.google.com/site-policies">Google Developers Site Policies</a>. Java is a registered trademark of Oracle and/or its affiliates.</p> <p>Last updated 2024-04-18 UTC.</p> </devsite-content-footer> <devsite-notification > </devsite-notification> <div class="devsite-content-data"> <template class="devsite-thumb-rating-feedback"> <devsite-feedback position="thumb-rating" project-name="Privacy Sandbox" product-id="5335444" bucket="" context="" version="t-devsite-webserver-20241114-r00-rc02.464922260396498922" data-label="Send Feedback Button" track-type="feedback" track-name="sendFeedbackLink" track-metadata-position="thumb-rating" class="nocontent" disable-product-feedback project-icon="https://developers.google.com/static/privacy-sandbox/assets/images/privacy-sandbox-logo.png" > <button> Need to tell us more? </button> </devsite-feedback> </template> <template class="devsite-content-data-template"> [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2024-04-18 UTC."],[],[]] </template> </div> </devsite-content> </main> <devsite-footer-promos class="devsite-footer"> </devsite-footer-promos> <devsite-footer-linkboxes class="devsite-footer"> <nav class="devsite-footer-linkboxes nocontent" aria-label="Footer links"> <ul class="devsite-footer-linkboxes-list"> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Get support</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://github.com/privacysandbox/privacy-sandbox-dev-support" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Ask a question on our GitHub support repo </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://goo.gle/privacy-sandbox-feedback" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Submit project feedback </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Get updates</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="/privacy-sandbox/blog" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Developer blog </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://privacysandbox.com/news/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Project news </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Resources</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://privacysandbox.com/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Project site </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://privacysandbox.com/open-web/#the-privacy-sandbox-timeline" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Privacy Sandbox timeline </a> </li> </ul> </li> <li class="devsite-footer-linkbox "> <h3 class="devsite-footer-linkbox-heading no-link">Tools</h3> <ul class="devsite-footer-linkbox-list"> <li class="devsite-footer-linkbox-item"> <a href="https://goo.gle/psat" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 1)" > Privacy Sandbox Analysis Tool </a> </li> <li class="devsite-footer-linkbox-item"> <a href="https://privacy-sandbox-demos.dev/" class="devsite-footer-linkbox-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Link (index 2)" > Privacy Sandbox demos </a> </li> </ul> </li> </ul> </nav> </devsite-footer-linkboxes> <devsite-footer-utility class="devsite-footer"> <div class="devsite-footer-utility nocontent"> <nav class="devsite-footer-sites" aria-label="Other Google Developers websites"> <a href="https://developers.google.com/" class="devsite-footer-sites-logo-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Developers Link"> <picture> <img class="devsite-footer-sites-logo" src="https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/developers/images/lockup-google-for-developers.svg" loading="lazy" alt="Google Developers"> </picture> </a> <ul class="devsite-footer-sites-list"> <li class="devsite-footer-sites-item"> <a href="//developer.android.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Android Link" > Android </a> </li> <li class="devsite-footer-sites-item"> <a href="//developer.chrome.com/home" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Chrome Link" > Chrome </a> </li> <li class="devsite-footer-sites-item"> <a href="//firebase.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Firebase Link" > Firebase </a> </li> <li class="devsite-footer-sites-item"> <a href="//cloud.google.com" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google Cloud Platform Link" > Google Cloud Platform </a> </li> <li class="devsite-footer-sites-item"> <a href="//ai.google.dev/" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer Google AI Link" > Google AI </a> </li> <li class="devsite-footer-sites-item"> <a href="/products" class="devsite-footer-sites-link gc-analytics-event" data-category="Site-Wide Custom Events" data-label="Footer All products Link" > All products </a> </li> </ul> </nav> <nav class="devsite-footer-utility-links" aria-label="Utility links"> <ul class="devsite-footer-utility-list"> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="/terms/site-terms" data-category="Site-Wide Custom Events" data-label="Footer Terms link" > Terms </a> </li> <li class="devsite-footer-utility-item "> <a class="devsite-footer-utility-link gc-analytics-event" href="//policies.google.com/privacy" data-category="Site-Wide Custom Events" data-label="Footer Privacy link" > Privacy </a> </li> <li class="devsite-footer-utility-item glue-cookie-notification-bar-control"> <a class="devsite-footer-utility-link gc-analytics-event" href="#" data-category="Site-Wide Custom Events" data-label="Footer Manage cookies link" aria-hidden="true" > Manage cookies </a> </li> <li class="devsite-footer-utility-item devsite-footer-utility-button"> <span class="devsite-footer-utility-description">Sign up for the Google for Developers newsletter</span> <a class="devsite-footer-utility-link gc-analytics-event" href="/newsletter/subscribe" data-category="Site-Wide Custom Events" data-label="Footer Subscribe link" > Subscribe </a> </li> </ul> <devsite-language-selector> <ul role="presentation"> <li role="presentation"> <a role="menuitem" lang="en" >English</a> </li> <li role="presentation"> <a role="menuitem" lang="de" >Deutsch</a> </li> <li role="presentation"> <a role="menuitem" lang="es" >Español</a> </li> <li role="presentation"> <a role="menuitem" lang="es_419" >Español – América Latina</a> </li> <li role="presentation"> <a role="menuitem" lang="fr" >Français</a> </li> <li role="presentation"> <a role="menuitem" lang="id" >Indonesia</a> </li> <li role="presentation"> <a role="menuitem" lang="it" >Italiano</a> </li> <li role="presentation"> <a role="menuitem" lang="pl" >Polski</a> </li> <li role="presentation"> <a role="menuitem" lang="pt_br" >Português – Brasil</a> </li> <li role="presentation"> <a role="menuitem" lang="vi" >Tiếng Việt</a> </li> <li role="presentation"> <a role="menuitem" lang="tr" >Türkçe</a> </li> <li role="presentation"> <a role="menuitem" lang="ru" >Русский</a> </li> <li role="presentation"> <a role="menuitem" lang="he" >עברית</a> </li> <li role="presentation"> <a role="menuitem" lang="ar" >العربيّة</a> </li> <li role="presentation"> <a role="menuitem" lang="fa" >فارسی</a> </li> <li role="presentation"> <a role="menuitem" lang="hi" >हिंदी</a> </li> <li role="presentation"> <a role="menuitem" lang="bn" >বাংলা</a> </li> <li role="presentation"> <a role="menuitem" lang="th" >ภาษาไทย</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_cn" >中文 – 简体</a> </li> <li role="presentation"> <a role="menuitem" lang="zh_tw" >中文 – 繁體</a> </li> <li role="presentation"> <a role="menuitem" lang="ja" >日本語</a> </li> <li role="presentation"> <a role="menuitem" lang="ko" >한국어</a> </li> </ul> </devsite-language-selector> </nav> </div> </devsite-footer-utility> <devsite-panel></devsite-panel> <devsite-concierge data-info-panel data-ai-panel data-api-explorer-panel > </devsite-concierge> </section></section> <devsite-sitemask></devsite-sitemask> <devsite-snackbar></devsite-snackbar> <devsite-tooltip ></devsite-tooltip> <devsite-heading-link></devsite-heading-link> <devsite-analytics> <script type="application/json" analytics>[{&#34;dimensions&#34;: {&#34;dimension1&#34;: &#34;Signed out&#34;, &#34;dimension6&#34;: &#34;en&#34;, &#34;dimension5&#34;: &#34;en&#34;, &#34;dimension3&#34;: false, &#34;dimension11&#34;: false, &#34;dimension4&#34;: &#34;Privacy Sandbox&#34;}, &#34;gaid&#34;: &#34;UA-24532603-1&#34;, &#34;metrics&#34;: {&#34;ratings_count&#34;: &#34;metric2&#34;, &#34;ratings_value&#34;: &#34;metric1&#34;}, &#34;purpose&#34;: 1}]</script> <script type="application/json" tag-management>{&#34;at&#34;: &#34;True&#34;, &#34;ga4&#34;: [{&#34;id&#34;: &#34;G-272J68FCRF&#34;, &#34;purpose&#34;: 1}], &#34;ga4p&#34;: [{&#34;id&#34;: &#34;G-272J68FCRF&#34;, &#34;purpose&#34;: 1}], &#34;gtm&#34;: [{&#34;id&#34;: &#34;GTM-WPJH8HP6&#34;, &#34;purpose&#34;: 0}], &#34;parameters&#34;: {&#34;internalUser&#34;: &#34;False&#34;, &#34;language&#34;: {&#34;machineTranslated&#34;: &#34;False&#34;, &#34;requested&#34;: &#34;en&#34;, &#34;served&#34;: &#34;en&#34;}, &#34;pageType&#34;: &#34;article&#34;, &#34;projectName&#34;: &#34;Privacy Sandbox&#34;, &#34;signedIn&#34;: &#34;False&#34;, &#34;tenant&#34;: &#34;developers&#34;, &#34;recommendations&#34;: {&#34;sourcePage&#34;: &#34;&#34;, &#34;sourceType&#34;: 0, &#34;sourceRank&#34;: 0, &#34;sourceIdenticalDescriptions&#34;: 0, &#34;sourceTitleWords&#34;: 0, &#34;sourceDescriptionWords&#34;: 0, &#34;experiment&#34;: &#34;&#34;}, &#34;experiment&#34;: {&#34;ids&#34;: &#34;&#34;}}}</script> </devsite-analytics> <devsite-badger></devsite-badger> <script nonce="jikTMJBYCo0FU2+YMhq+T+c52rjGWR"> (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i; t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0]; E.parentNode.insertBefore(t,E);})(window, document, 'script', 'https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/developers/js/app_loader.js', '[1,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/developers","https://developers-dot-devsite-v2-prod.appspot.com",null,null,["/_pwa/developers/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v870e399c64f7c43c99a3043db4b3a74327bb93d0914e84a0c3dba90bbfd67625/developers/images/favicon-new.png","https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyAP-jjEJBzmIyKR4F-3XITp8yM9T1gEEI8","AIzaSyB6xiKGDR5O3Ak2okS4rLkauxGUG7XP0hg","developers.google.com","AIzaSyAQk0fBONSGUqCNznf6Krs82Ap1-NV6J4o","AIzaSyCCxcqdrZ_7QMeLCRY20bh_SXdAYqy70KY",null,null,null,["Profiles__enable_profile_collections","Profiles__require_profile_eligibility_for_signin","TpcFeatures__enable_mirror_tenant_redirects","MiscFeatureFlags__enable_variable_operator","Search__enable_dynamic_content_confidential_banner","Concierge__enable_pushui","Profiles__enable_completecodelab_endpoint","Profiles__enable_developer_profiles_callout","CloudShell__cloud_shell_button","MiscFeatureFlags__developers_footer_image","Profiles__enable_awarding_url","Profiles__enable_release_notes_notifications","Search__enable_page_map","MiscFeatureFlags__developers_footer_dark_image","CloudShell__cloud_code_overflow_menu","Search__enable_ai_search_summaries","MiscFeatureFlags__enable_firebase_utm","Cloud__enable_cloudx_experiment_ids","DevPro__enable_developer_subscriptions","Cloud__enable_cloud_shell","Cloud__enable_llm_concierge_chat","MiscFeatureFlags__emergency_css","Profiles__enable_page_saving","BookNav__enable_tenant_cache_key","Cloud__enable_cloud_shell_fte_user_flow","Search__enable_ai_search_summaries_restricted","EngEduTelemetry__enable_engedu_telemetry","Profiles__enable_recognition_badges","Analytics__enable_clearcut_logging","Experiments__reqs_query_experiments","Search__enable_ai_eligibility_checks","Cloud__enable_cloudx_ping","Concierge__enable_concierge_restricted","DevPro__enable_cloud_innovators_plus","Cloud__enable_cloud_dlp_service","Cloud__enable_cloud_facet_chat","Cloud__enable_legacy_calculator_redirect","Cloud__enable_free_trial_server_call","MiscFeatureFlags__enable_explain_this_code","Profiles__enable_dashboard_curated_recommendations","Concierge__enable_concierge","Search__enable_suggestions_from_borg","Profiles__enable_complete_playlist_endpoint","Profiles__enable_public_developer_profiles","MiscFeatureFlags__enable_project_variables","MiscFeatureFlags__enable_view_transitions","TpcFeatures__enable_required_headers","Significatio__enable_by_tenant"],null,null,"AIzaSyBLEMok-5suZ67qRPzx0qUtbnLmyT_kCVE","https://developerscontentserving-pa.clients6.google.com","AIzaSyCM4QpTRSqP5qI4Dvjt4OAScIN8sOUlO-k","https://developerscontentsearch-pa.clients6.google.com",1,4,null,"https://developerprofiles-pa.clients6.google.com",[1,"developers","Google for Developers","developers.google.com",null,"developers-dot-devsite-v2-prod.appspot.com",null,null,[1,1,[1],null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,[1],[1,null,null,[1,20],"/recommendations/information"],null,null,null,[1,1,1],[1,1,null,1,1]],null,[null,null,null,null,null,null,"/images/lockup-new.svg","/images/touchicon-180-new.png",null,null,null,null,1,null,null,null,null,null,null,null,null,1,null,null,null,"/images/lockup-dark-theme-new.svg",[]],[],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[6,1,14,15,20,22,23,29,32,36],null,[[null,null,null,[3,7,10,2,39,17,4,32,24,11,12,13,34,15,25],null,null,[1,[["docType","Choose a content type",[["Tutorial",null,null,null,null,null,null,null,null,"Tutorial"],["Guide",null,null,null,null,null,null,null,null,"Guide"],["Sample",null,null,null,null,null,null,null,null,"Sample"]]],["product","Choose a product",[["Android",null,null,null,null,null,null,null,null,"Android"],["ARCore",null,null,null,null,null,null,null,null,"ARCore"],["ChromeOS",null,null,null,null,null,null,null,null,"ChromeOS"],["Firebase",null,null,null,null,null,null,null,null,"Firebase"],["Flutter",null,null,null,null,null,null,null,null,"Flutter"],["Assistant",null,null,null,null,null,null,null,null,"Google Assistant"],["GoogleCloud",null,null,null,null,null,null,null,null,"Google Cloud"],["GoogleMapsPlatform",null,null,null,null,null,null,null,null,"Google Maps Platform"],["GooglePay",null,null,null,null,null,null,null,null,"Google Pay & Google Wallet"],["GooglePlay",null,null,null,null,null,null,null,null,"Google Play"],["Tensorflow",null,null,null,null,null,null,null,null,"TensorFlow"]]],["category","Choose a topic",[["AiAndMachineLearning",null,null,null,null,null,null,null,null,"AI and Machine Learning"],["Data",null,null,null,null,null,null,null,null,"Data"],["Enterprise",null,null,null,null,null,null,null,null,"Enterprise"],["Gaming",null,null,null,null,null,null,null,null,"Gaming"],["Mobile",null,null,null,null,null,null,null,null,"Mobile"],["Web",null,null,null,null,null,null,null,null,"Web"]]]]]],[1,1],null,1],[[["UA-24532603-1"],["UA-22084204-5"],null,null,["UA-24532603-5"],null,null,[["G-272J68FCRF"],null,null,[["G-272J68FCRF",2]]],[["UA-24532603-1",2]],null,[["UA-24532603-5",2]],null,1],[[12,9],[13,10],[16,13],[4,3],[5,4],[1,1],[14,11],[11,8],[15,12],[6,5],[3,2]],[[2,2],[1,1]]],null,4,null,null,null,null,null,null,null,null,null,null,null,null,null,"developers.devsite.google"],null,"pk_live_5170syrHvgGVmSx9sBrnWtA5luvk9BwnVcvIi7HizpwauFG96WedXsuXh790rtij9AmGllqPtMLfhe2RSwD6Pn38V00uBCydV4m"]') </script> <devsite-a11y-announce></devsite-a11y-announce> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10