<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://web.dev/</id>
  <title>Eiji Kitamura on web.dev</title>
  <updated>2026-04-15T23:21:06Z</updated>
  <author>
    <name>Eiji Kitamura</name>
  </author>
  <link href="https://web.dev/authors/agektmr/feed.xml" rel="self"/>
  <link href="https://web.dev/"/>
  <icon>https://web-dev.imgix.net/image/admin/Mh9DRmQhjlroJM9JDqsu.jpg?auto=format</icon>
  <logo>https://web.dev/images/shared/rss-banner.png</logo>
  <subtitle>Developer Advocate in Tokyo</subtitle>
  
  
  <entry>
    <title>Sign in with a passkey through form autofill</title>
    <link href="https://web.dev/passkey-form-autofill/"/>
    <updated>2022-10-12T00:00:00Z</updated>
    <id>https://web.dev/passkey-form-autofill/</id>
    <content type="html" mode="escaped">&lt;p&gt;&lt;a href=&quot;https://developers.google.com/identity/passkeys&quot; rel=&quot;noopener&quot;&gt;Passkeys&lt;/a&gt; replace passwords
and make user accounts on the web safer, simpler, easier to use. However, the
transition from password-based to passkey-based authentication can complicate
the user experience. Using form autofill to suggest passkeys can help
create a unified experience.&lt;/p&gt;
&lt;h2 id=&quot;why-use-form-autofill-to-sign-in-with-a-passkey&quot;&gt;Why use form autofill to sign-in with a passkey? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#why-use-form-autofill-to-sign-in-with-a-passkey&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With a passkey, a user can sign in to a website just by using fingerprint, face,
or device PIN.&lt;/p&gt;
&lt;p&gt;Ideally, there would be no password users and the authentication flow
could be as simple as a single sign-in button. When the user taps the button, an
account selector dialog pops up, the user can pick an account, unlock the screen
to verify and sign in.&lt;/p&gt;
&lt;p&gt;However, the transition from password to passkey-based authentication can be
challenging. As users switch to passkeys, there will still be those who use
passwords and websites will need to accommodate both types of users. Users
themselves should not be expected to remember on which sites they&#39;ve switched to
passkeys, so asking users to select which method to use up front would be poor
UX.&lt;/p&gt;
&lt;p&gt;Passkeys are also a new technology. Explaining them and making sure users are
comfortable using them can be a challenge for websites. We can rely on familiar
user experiences for autofilling passwords to solve both problems.&lt;/p&gt;
&lt;h2 id=&quot;conditional-ui&quot;&gt;Conditional UI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#conditional-ui&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To build an efficient user experience for both passkey and password users, you
can include passkeys in autofill suggestions. This is called &lt;a href=&quot;https://github.com/w3c/webauthn/wiki/Explainer:-WebAuthn-Conditional-UI&quot; rel=&quot;noopener&quot;&gt;conditional
UI&lt;/a&gt; and
it&#39;s a part of &lt;a href=&quot;https://w3c.github.io/webauthn/&quot; rel=&quot;noopener&quot;&gt;the WebAuthn standard&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/ZaxgMtkOh5CX2B1ZT9gd.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
&lt;/figure&gt;
&lt;p&gt;As soon as the user taps on the username input field, an autofill suggestion
dialog pops up which highlights the stored passkeys along with password autofill
suggestions. The user can then choose an account and use the device screen lock
to sign in.&lt;/p&gt;
&lt;p&gt;This way, users can sign in to your website with the existing form as if nothing
has changed, but with &lt;a href=&quot;https://developers.google.com/identity/passkeys#security-considerations&quot; rel=&quot;noopener&quot;&gt;the added security benefit of
passkeys&lt;/a&gt;
if they have one.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-good-bg color-state-good-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 24 24&quot; height=&quot;24&quot; width=&quot;24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Check&quot;&gt;   &lt;path d=&quot;M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Success&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  When a user signs in with a password, consider using that opportunity to offer them to &lt;a href=&quot;https://web.dev/passkey-registration&quot;&gt;create a passkey&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#how-it-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To authenticate with a passkey, you use &lt;a href=&quot;https://w3c.github.io/webauthn/&quot; rel=&quot;noopener&quot;&gt;the WebAuthn
API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The four components in a passkey authentication flow are:
the user:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;: Your backend server that holds the accounts database storing the
public key and other metadata about the passkey.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: Your frontend which communicates with the browser and sends
fetch requests to the backend.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser&lt;/strong&gt;: The user&#39;s browser which is running your Javascript.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authenticator&lt;/strong&gt;: The user&#39;s authenticator which creates and stores the
passkey. This may be on the same device as the browser (e.g. when using
Windows Hello) or on another device, like a phone.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;screenshot&quot;&gt;
  &lt;img alt=&quot;Passkey authentication diagram&quot; decoding=&quot;async&quot; height=&quot;254&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vAwnMiLi7U1spDopYg2Q.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;As soon as a user lands on the frontend, it requests a challenge from the
backend to authenticate with a passkey and calls
&lt;code&gt;navigator.credentials.get()&lt;/code&gt; to initiate authenticating with a passkey.
This returns a &lt;code&gt;Promise&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When the user puts the cursor in the sign-in field, the browser displays a
password autofill dialog including passkeys. An authentication dialog appears
if the user selects a passkey.&lt;/li&gt;
&lt;li&gt;After the user verifies their identity using the device&#39;s screen lock, the
promise is resolved and a public key credential is returned to the frontend.&lt;/li&gt;
&lt;li&gt;The frontend sends the public key credential to the backend. The backend
verifies the signature against the matched account&#39;s public key in the
database. If it succeeds, the user is signed in.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#prerequisites&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Conditional WebAuthn UI is publicly supported in Safari on iOS 16, iPadOS 16 and
macOS Ventura. It&#39;s also available on Chrome on Android, macOS and Windows 11
22H2.&lt;/p&gt;
&lt;h2 id=&quot;authenticate-with-a-passkey-through-form-autofill&quot;&gt;Authenticate with a passkey through form autofill &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#authenticate-with-a-passkey-through-form-autofill&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a user wants to sign in, you can make a conditional WebAuthn &lt;code&gt;get&lt;/code&gt; call
to indicate that passkeys may be included in autofill suggestions. A conditional
call to &lt;a href=&quot;https://w3c.github.io/webauthn/&quot; rel=&quot;noopener&quot;&gt;WebAuthn&lt;/a&gt;&#39;s
&lt;code&gt;navigator.credentials.get()&lt;/code&gt; API does not show UI and remains pending until
the user picks an account to sign-in with from the autofill suggestions. If the
user picks a passkey the browser will resolve the promise with a credential
rather than filling in the sign-in form. It&#39;s then the page&#39;s responsibility to
sign the user in.&lt;/p&gt;
&lt;h3 id=&quot;annotate-form-input-field&quot;&gt;Annotate form input field &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#annotate-form-input-field&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Add an &lt;code&gt;autocomplete&lt;/code&gt; attribute to the username &lt;code&gt;input&lt;/code&gt; field, if needed.
Append &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;webauthn&lt;/code&gt; as its tokens to let it suggest passkeys.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;username&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;username webauthn&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;feature-detection&quot;&gt;Feature detection &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#feature-detection&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Before invoking a conditional WebAuthn API call, check if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The browser supports WebAuthn.&lt;/li&gt;
&lt;li&gt;The browser supports WebAuthn conditional UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Availability of `window.PublicKeyCredential` means WebAuthn is usable.  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PublicKeyCredential &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;  &lt;br /&gt;    PublicKeyCredential&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;​​isConditionalMediationAvailable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Check if conditional mediation is available.  &lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; isCMA &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; PublicKeyCredential&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;​​isConditionalMediationAvailable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isCMA&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Call WebAuthn authentication  &lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;fetch-a-challenge-from-the-rp-server&quot;&gt;Fetch a challenge from the RP server &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#fetch-a-challenge-from-the-rp-server&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Fetch a challenge from the RP server that is required to call
&lt;code&gt;navigator.credentials.get()&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-challenge&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;challenge&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
A server-generated challenge in an ArrayBuffer. This is required to prevent
replay attacks. Make sure to generate a new challenge on every sign-in attempt
and disregard it after a certain duration or after a sign-in attempt fails to
validate. Consider it like a CSRF token.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialrequestoptions-allowcredentials&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;allowCredentials&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An array of acceptable credentials for this authentication. Pass an empty
array to let the user select an available passkey from a list shown by the
browser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialrequestoptions-userverification&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;userVerification&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
Indicates whether user verification using the device screen lock is
&lt;code&gt;&amp;quot;required&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;discouraged&amp;quot;&lt;/code&gt;. The default is &lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt;,
which means the authenticator may skip user verification. Set this to
&lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt; or omit the property.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  For requests with &lt;code&gt;userVerification&lt;/code&gt; set to &lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt;, authenticators may skip the user verification check, for example if the device doesn&#39;t have any biometric sensors, the user hasn&#39;t set it up (no enrolled fingerprints), or if the sensor is temporarily unavailable (a laptop running with a closed display lid). The &lt;a href=&quot;https://w3c.github.io/webauthn/#authdata-flags-uv&quot;&gt;UV bit in the authenticator data of the response&lt;/a&gt; always indicates whether user verification was performed.  If you&#39;d like to always require a user verification, set &lt;code&gt;userVerification&lt;/code&gt; to &lt;code&gt;&amp;quot;required&amp;quot;&lt;/code&gt;. Don&#39;t forget to check that the UV flag is &lt;code&gt;true&lt;/code&gt; on the server as well.  &lt;/div&gt;&lt;/aside&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  ArrayBuffer values transferred from the server such as &lt;code&gt;challenge&lt;/code&gt;, &lt;code&gt;user.id&lt;/code&gt; and credential &lt;code&gt;id&lt;/code&gt; for &lt;code&gt;excludeCredentials&lt;/code&gt; need to be encoded on transmission. Make sure to decode them on the RP frontend before passing the values to the WebAuthn API call. We recommend using Base64URL encode.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;call-webauthn-api-with-the-conditional-flag-to-authenticate-the-user&quot;&gt;Call WebAuthn API with the &lt;code&gt;conditional&lt;/code&gt; flag to authenticate the user &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#call-webauthn-api-with-the-conditional-flag-to-authenticate-the-user&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Call &lt;code&gt;navigator.credentials.get()&lt;/code&gt; to start waiting for the user authentication.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// To abort a WebAuthn call, instantiate an `AbortController`.  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; abortController &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AbortController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; publicKeyCredentialRequestOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Server generated challenge  &lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;challenge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// The same RP ID as used during registration  &lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;rpId&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;example.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; credential &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;publicKey&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; publicKeyCredentialRequestOptions&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; abortController&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Specify &#39;conditional&#39; to activate conditional UI  &lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;mediation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;conditional&#39;&lt;/span&gt;  &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialrequestoptions-rpid&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;rpId&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An RP ID is a domain and a website can specify either its domain or a
registrable suffix. This value must match the rp.id used when the passkey was
created.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember to specify &lt;code&gt;mediation: &#39;conditional&#39;&lt;/code&gt; to make the request conditional.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  The WebAuthn call here will be pending and the promise won&#39;t be resolved until the user interacts with the autofill input element and completes the authentication flow. The RP frontend can use &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/AbortController&quot;&gt;&lt;code&gt;AbortController&lt;/code&gt;&lt;/a&gt; to abort the WebAuthn call.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;send-the-returned-public-key-credential-to-the-rp-server&quot;&gt;Send the returned public key credential to the RP server &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#send-the-returned-public-key-credential-to-the-rp-server&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After the user selects an account and consents using the device&#39;s screen lock,
the promise is resolved returning a
&lt;a href=&quot;https://w3c.github.io/webauthn/#authenticatorassertionresponse&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PublicKeyCredential&lt;/code&gt;&lt;/a&gt;
object to the RP frontend.&lt;/p&gt;
&lt;p&gt;A promise can be rejected due to several different reasons. You need to handle the errors accordingly,
depending on the &lt;code&gt;Error&lt;/code&gt; object&#39;s &lt;code&gt;name&lt;/code&gt; property:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;NotAllowedError&lt;/code&gt;&lt;/strong&gt;: The user has canceled the operation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Other exceptions&lt;/strong&gt;: Something unexpected happened. The browser shows an
error dialog to the user.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The public key credential object contains the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#credential-id&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;id&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: The
base64url encoded ID of the authenticated passkey credential.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#credential-id&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;rawId&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: An
ArrayBuffer version of the credential ID.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#client-data&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;response.clientDataJSON&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An ArrayBuffer of client data. This field contains information such as the challenge
and the origin that the RP server will need to verify.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorassertionresponse-authenticatordata&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;response.authenticatorData&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An ArrayBuffer of authenticator data. This field contains information such as the RP
ID.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorassertionresponse-signature&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;response.signature&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An ArrayBuffer of the signature. This value is the core of the credential and needs
to be verified on the server.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorassertionresponse-userhandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;response.userHandle&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An ArrayBuffer that contained the user ID that was set at creation time. This
value can be used, instead of the credential ID, if the server needs to pick
the ID values that it uses, or if the backend wishes to avoid creating an
index on credential IDs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#enumdef-authenticatorattachment&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;authenticatorAttachment&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
Returns &lt;code&gt;platform&lt;/code&gt; when this credential came from the local device.
Otherwise &lt;code&gt;cross-platform&lt;/code&gt;, notably when &lt;a href=&quot;https://developers.google.com/identity/passkeys/use-cases#sign-in-with-a-phone&quot; rel=&quot;noopener&quot;&gt;the user used a phone to sign
in&lt;/a&gt;.
If the user needed to use a phone to sign-in, consider prompting them to
&lt;a href=&quot;https://web.dev/passkey-registration&quot;&gt;create a passkey&lt;/a&gt; on the local device.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;type&lt;/code&gt;&lt;/strong&gt;: This field is always set to &lt;code&gt;&amp;quot;public-key&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you use a library to handle the public-key credential object on the RP
server, we recommend that you send the entire object to the server after encoding it
partially with base64url.&lt;/p&gt;
&lt;h3 id=&quot;verify-the-signature&quot;&gt;Verify the signature &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#verify-the-signature&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you receive the public key credential on the server, pass it to the FIDO
library to process the object.&lt;/p&gt;
&lt;p&gt;Look up the matching credential ID with the
&lt;a href=&quot;https://w3c.github.io/webauthn/#credential-id&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;id&lt;/code&gt;&lt;/a&gt; property (If you need to
determine the user account, use the
&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorassertionresponse-userhandle&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;userHandle&lt;/code&gt;&lt;/a&gt;
property which is the &lt;code&gt;user.id&lt;/code&gt; you specified when creating the credential). See
if the credential&#39;s
&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorassertionresponse-signature&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;signature&lt;/code&gt;&lt;/a&gt;
can be verified with the stored public key. To do so, we recommend using a
server side library or a solution instead of writing your own code. &lt;a href=&quot;https://github.com/herrjemand/awesome-webauthn&quot; rel=&quot;noopener&quot;&gt;You can
find open source libraries in the awesome-webauth GitHub
repo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once the credential is verified with a matching public key, sign the user in.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-form-autofill/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/passkey-registration/&quot;&gt;Create a passkey for passwordless logins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.imperialviolet.org/2022/09/22/passkeys.html&quot; rel=&quot;noopener&quot;&gt;Passkeys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service&quot; rel=&quot;noopener&quot;&gt;Apple document: Authenticating a User Through a Web
Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/identity/passkeys/&quot; rel=&quot;noopener&quot;&gt;Google document: Passwordless login with
passkeys&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Create a passkey for passwordless logins</title>
    <link href="https://web.dev/passkey-registration/"/>
    <updated>2022-10-12T00:00:00Z</updated>
    <id>https://web.dev/passkey-registration/</id>
    <content type="html" mode="escaped">&lt;p&gt;Using &lt;a href=&quot;https://developers.google.com/identity/passkeys&quot; rel=&quot;noopener&quot;&gt;passkeys&lt;/a&gt; instead of
passwords is a great way for websites to make their user accounts safer,
simpler, easier to use and passwordless. With a passkey, a user can sign in to a
website or an app just by using their fingerprint, face or device PIN.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  To learn basic concepts of passkeys, check out &lt;a href=&quot;https://developers.google.com/identity/passkeys&quot;&gt;Passwordless login with passkeys&lt;/a&gt; first.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;A passkey has to be created, associated with a user account and have its public key be stored on your server before a user can sign in with it.&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot;&gt;How it works &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#how-it-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A user can be asked to create a passkey in one of the following situations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When a user signs in using a password, or a passkey from another device (that is,
the
&lt;a href=&quot;https://web.dev/passkey-form-autofill/#:~:text=authenticationattachment&quot;&gt;&lt;code&gt;authenticatorAttachment&lt;/code&gt;&lt;/a&gt;
is &lt;code&gt;cross-platform&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;On a dedicated page where users can manage their passkeys.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/2gY9wppN8tivRRWDH8gV.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
&lt;/figure&gt;
&lt;p&gt;To create a passkey, you use &lt;a href=&quot;https://w3c.github.io/webauthn/&quot; rel=&quot;noopener&quot;&gt;the WebAuthn
API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The four components of the passkey registration flow are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;: Your backend server that holds the accounts database storing the
public key and other metadata about the passkey.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: Your frontend which communicates with the browser and sends
fetch requests to the backend.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Browser&lt;/strong&gt;: The user&#39;s browser which is running your Javascript.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Authenticator&lt;/strong&gt;: The user&#39;s authenticator which creates and stores the
passkey. This may be on the same device as the browser (for example, when using
Windows Hello) or on another device, like a phone.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;screenshot&quot;&gt;
  &lt;img alt=&quot;Passkey registration diagram&quot; decoding=&quot;async&quot; height=&quot;258&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/vmxdOrHbR2kW17Ipv6hk.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The journey to add a new passkey to an existing user account is as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A user signs in to the website.&lt;/li&gt;
&lt;li&gt;Once the user is signed in, they request to create a passkey on the
frontend, for example, by pressing a &amp;quot;Create a passkey&amp;quot; button.&lt;/li&gt;
&lt;li&gt;The frontend requests information from the
backend to create a passkey, such as user
information, a challenge, and the credential IDs to exclude.&lt;/li&gt;
&lt;li&gt;The frontend calls &lt;code&gt;navigator.credentials.create()&lt;/code&gt; to create a passkey.
This call returns a promise.&lt;/li&gt;
&lt;li&gt;A passkey is created after the user consents using the device&#39;s screen lock.
The promise is resolved and a public key credential is returned to the
frontend.&lt;/li&gt;
&lt;li&gt;The frontend sends the public key credential to the backend and stores the
credential ID and the public key associated with the user account for future
authentications.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;compatibilities&quot;&gt;Compatibilities &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#compatibilities&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;WebAuthn is supported by most browsers, but there are small gaps. Refer to
&lt;a href=&quot;https://passkeys.dev/device-support/&quot; rel=&quot;noopener&quot;&gt;Device Support - passkeys.dev&lt;/a&gt; to learn
what combination of browsers and an operating systems support creating a
passkey.&lt;/p&gt;
&lt;h2 id=&quot;create-a-new-passkey&quot;&gt;Create a new passkey &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#create-a-new-passkey&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here&#39;s how a frontend should operate upon a request to create a new passkey.&lt;/p&gt;
&lt;h3 id=&quot;feature-detection&quot;&gt;Feature detection &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#feature-detection&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Before displaying a &amp;quot;Create a new passkey&amp;quot; button, check if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The browser supports WebAuthn.&lt;/li&gt;
&lt;li&gt;The device supports a platform authenticator (can create a passkey and
authenticate with the passkey).&lt;/li&gt;
&lt;li&gt;The browser supports &lt;a href=&quot;https://web.dev/passkey-form-autofill/&quot;&gt;WebAuthn conditional UI&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Availability of `window.PublicKeyCredential` means WebAuthn is usable.  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// `​​isConditionalMediationAvailable` means the feature detection is usable.  &lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PublicKeyCredential &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;  &lt;br /&gt;    PublicKeyCredential&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isUserVerifyingPlatformAuthenticatorAvailable &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;  &lt;br /&gt;    PublicKeyCredential&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;​​isConditionalMediationAvailable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Check if user verifying platform authenticator is available.  &lt;/span&gt;&lt;br /&gt;  Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;  &lt;br /&gt;    PublicKeyCredential&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isUserVerifyingPlatformAuthenticatorAvailable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;    PublicKeyCredential&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;​​isConditionalMediationAvailable&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;results&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Display &quot;Create a new passkey&quot; button  &lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Until all the conditions have been met, passkeys will not be supported on this browser.
The &amp;quot;Create a new passkey&amp;quot; button shouldn&#39;t be displayed until then.&lt;/p&gt;
&lt;h3 id=&quot;fetch-important-information-from-the-backend&quot;&gt;Fetch important information from the backend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#fetch-important-information-from-the-backend&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When the user clicks the button, fetch important information to call
&lt;code&gt;navigator.credentials.create()&lt;/code&gt; from the backend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-challenge&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;challenge&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
A server-generated challenge in ArrayBuffer for this registration. This is
required but unused during registration unless doing
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Web_Authentication_API/Attestation_and_Assertion&quot; rel=&quot;noopener&quot;&gt;attestation&lt;/a&gt;—an
advanced topic not covered here.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-id&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;user.id&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
A user&#39;s unique ID. This value must be an ArrayBuffer which does not include
personally identifying information, for example, e-mail addresses or usernames. A
random, 16-byte value generated per account will work well.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialentity-name&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;user.name&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
This field should hold a unique identifier for the account that the user will
recognise, like their email address or username. This will be displayed in the
account selector. (If using a username, use the same value as in password
authentication.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-displayname&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;user.displayName&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
This field is an optional, more user-friendly name for the account. It need not be unique
and could be the user&#39;s chosen name. If your site does not have a suitable
value to include here, pass an empty string. This may be displayed on the
account selector depending on the browser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-excludecredentials&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;excludeCredentials&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
Prevents registering the same device by providing a list of already registered
credential IDs. The
&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialdescriptor-transports&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;transports&lt;/code&gt;&lt;/a&gt;
member, if provided, should contain the result of calling
&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-gettransports&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;getTransports()&lt;/code&gt;&lt;/a&gt;
during the registration of each credential.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  ArrayBuffer values transferred from the server such as &lt;code&gt;challenge&lt;/code&gt;, &lt;code&gt;user.id&lt;/code&gt; and credential &lt;code&gt;id&lt;/code&gt; for &lt;code&gt;excludeCredentials&lt;/code&gt; need to be encoded on transmission. Don&#39;t forget to decode them on the frontend before passing to the WebAuthn API call. We recommend using Base64URL encode.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;call-webauthn-api-to-create-a-passkey&quot;&gt;Call WebAuthn API to create a passkey &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#call-webauthn-api-to-create-a-passkey&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Call &lt;code&gt;navigator.credentials.create()&lt;/code&gt; to create a new passkey. The API returns
a promise, waiting for the user&#39;s interaction displaying a modal dialog.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; publicKeyCredentialCreationOptions &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;challenge&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;rp&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Example&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;example.com&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;john78&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;displayName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;pubKeyCredParams&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;alg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public-key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;alg&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;257&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;public-key&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;excludeCredentials&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;public-key&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;transports&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;internal&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;authenticatorSelection&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;authenticatorAttachment&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;platform&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;requireResidentKey&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; credential &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;publicKey&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; publicKeyCredentialCreationOptions  &lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Encode and send the credential to the server for verification.  &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The parameters not explained above are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialrpentity-id&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;rp.id&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An RP ID is a domain and a website can specify either its domain or a
registrable suffix. For example, if an RP&#39;s origin is
&lt;code&gt;https://login.example.com:1337&lt;/code&gt;, the RP ID can be either
&lt;code&gt;login.example.com&lt;/code&gt; or &lt;code&gt;example.com&lt;/code&gt;. If the RP ID is specified as
&lt;code&gt;example.com&lt;/code&gt;, the user can authenticate on &lt;code&gt;login.example.com&lt;/code&gt; or on any
subdomains on &lt;code&gt;example.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialentity-name&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;rp.name&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
The RP&#39;s name.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-publickeycredentialcreationoptions-pubkeycredparams&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;pubKeyCredParams&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
This field specifies the RP&#39;s supported public-key algorithms. We recommend setting
it to &lt;code&gt;[{alg: -7, type: &amp;quot;public-key&amp;quot;},{alg: -257, type: &amp;quot;public-key&amp;quot;}]&lt;/code&gt;.
This specifies support for ECDSA with P-256 and RSA PKCS#1 and supporting
these gives complete coverage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorselectioncriteria-authenticatorattachment&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;authenticatorSelection.authenticatorAttachment&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
Set it to &lt;code&gt;&amp;quot;platform&amp;quot;&lt;/code&gt;. This indicates that we want an authenticator that is
embedded into the platform device, and the user will not be prompted to insert
e.g. a USB security key.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorselectioncriteria-residentkey&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;authenticatorSelection.requireResidentKey&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
Set it to a boolean &amp;quot;true&amp;quot;. A discoverable credential (resident key)
stores user information to the passkey and lets users select the account upon
authentication.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorselectioncriteria-userverification&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;authenticatorSelection.userVerification&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
Indicates whether a user verification using the device screen lock is
&lt;code&gt;&amp;quot;required&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;discouraged&amp;quot;&lt;/code&gt;. The default is &lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt;,
which means the authenticator may skip user verification. Set this to
&lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt; or omit the property.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  For requests with &lt;code&gt;userVerification&lt;/code&gt; set to &lt;code&gt;&amp;quot;preferred&amp;quot;&lt;/code&gt;, authenticators may skip the user verification check, for example if the device doesn&#39;t have any biometric sensors, the user hasn&#39;t set it up (no enrolled fingerprints), or if the sensor is temporarily unavailable (laptop running with a closed display lid). The &lt;a href=&quot;https://w3c.github.io/webauthn/#authdata-flags-uv&quot;&gt;UV bit in the authenticator data of the response&lt;/a&gt; always indicates whether user verification was performed.  If you&#39;d like to always require a user verification, set &lt;code&gt;userVerification&lt;/code&gt; to &lt;code&gt;&amp;quot;required&amp;quot;&lt;/code&gt;. Don&#39;t forget to check that the UV flag is &lt;code&gt;true&lt;/code&gt; on the server as well.  &lt;/div&gt;&lt;/aside&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  Note: Some browsers don&#39;t require any parameters on &lt;code&gt;authenticatorSelection&lt;/code&gt; to create a passkey, but others may. We recommend specifying those parameters explicitly.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;send-the-returned-public-key-credential-to-the-backend&quot;&gt;Send the returned public key credential to the backend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#send-the-returned-public-key-credential-to-the-backend&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After the user consents using the device&#39;s screen lock, a passkey is created and
the promise is resolved returning a
&lt;a href=&quot;https://w3c.github.io/webauthn/#authenticatorattestationresponse&quot; rel=&quot;noopener&quot;&gt;PublicKeyCredential&lt;/a&gt;
object to the frontend.&lt;/p&gt;
&lt;p&gt;The promise can be rejected for different reasons. You can handle these errors by checking the &lt;code&gt;Error&lt;/code&gt; object&#39;s &lt;code&gt;name&lt;/code&gt; property:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;InvalidStateError&lt;/code&gt;&lt;/strong&gt;: A passkey already exists on the device. No error
dialog will be shown to the user and the site should not treat this as an
error—the user wanted the local device registered and it is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;NotAllowedError&lt;/code&gt;&lt;/strong&gt;: The user has canceled the operation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Other exceptions&lt;/strong&gt;: Something unexpected happened. The browser shows an
error dialog to the user.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The public key credential object contains the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#credential-id&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;id&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: A Base64URL encoded
ID of the created passkey. This ID helps the browser to determine whether a
matching passkey is in the device upon authentication. This value needs to be stored
in the database on the backend.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#credential-id&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;rawId&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;: An ArrayBuffer
version of the credential ID.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#client-data&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;response.clientDataJSON&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An ArrayBuffer encoded client data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#attestation-object&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;response.attestationObject&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
An ArrayBuffer encoded attestation object. This contains important information
such as an RP ID, flags and a public key.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#enumdef-authenticatorattachment&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;authenticatorAttachment&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;:
Returns &lt;code&gt;&amp;quot;platform&amp;quot;&lt;/code&gt; when this credential is created on a passkey capable
device.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;type&lt;/code&gt;&lt;/strong&gt;: This field is always set to &lt;code&gt;&amp;quot;public-key&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you use a library to handle the public key credential object on the backend,
we recommend sending the entire object to the backend after encoding it
partially with base64url.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  Optionally, the &lt;code&gt;response&lt;/code&gt; member of the credential - an &lt;a href=&quot;https://w3c.github.io/webauthn/#iface-authenticatorattestationresponse&quot;&gt;&lt;code&gt;AuthenticatorAttestationResponse&lt;/code&gt;&lt;/a&gt; — provides &lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-gettransports&quot;&gt;&lt;code&gt;getTransports()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-getpublickey&quot;&gt;&lt;code&gt;getPublicKey()&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-getauthenticatordata&quot;&gt;&lt;code&gt;getAuthenticatorData()&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;https://w3c.github.io/webauthn/#dom-authenticatorattestationresponse-getpublickey&quot;&gt;&lt;code&gt;getPublicKeyAlgorithm()&lt;/code&gt;&lt;/a&gt; functions to retrieve elements of the credential.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;save-the-credential&quot;&gt;Save the credential &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#save-the-credential&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Upon receiving the public key credential on the backend, pass it to the FIDO
library to process the object.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  We recommend using a server-side library or a solution instead of writing your own code to process a public-key credential. Check out &lt;a href=&quot;https://github.com/herrjemand/awesome-webauthn&quot;&gt;open-source libraries &lt;/a&gt; to process public-key credentials.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;You can then store the information retrieved from the credential to the database for
future use. The following list includes some typical properties to save:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Credential ID (Primary key)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User ID&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Public key&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The public-key credential also includes the following information
that you may want to save in the database:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#backup-eligibility&quot; rel=&quot;noopener&quot;&gt;Backup Eligibility
flag&lt;/a&gt;&lt;/strong&gt;: &lt;code&gt;true&lt;/code&gt; if the
device is eligible for passkey synchronization.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#backup-state&quot; rel=&quot;noopener&quot;&gt;Backup State flag&lt;/a&gt;&lt;/strong&gt;: &lt;code&gt;true&lt;/code&gt;
if the created passkey is actually set to be synchronized.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://w3c.github.io/webauthn/#enumdef-authenticatortransport&quot; rel=&quot;noopener&quot;&gt;Transports&lt;/a&gt;&lt;/strong&gt;:
A list of transports the device supports: &lt;code&gt;&amp;quot;internal&amp;quot;&lt;/code&gt; means the device
supports a passkey, &lt;code&gt;&amp;quot;hybrid&amp;quot;&lt;/code&gt; means it also supports &lt;a href=&quot;https://developers.google.com/identity/passkeys/use-cases#sign-in-with-a-phone&quot; rel=&quot;noopener&quot;&gt;authentication on
another
device&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To authenticate the user, read &lt;a href=&quot;https://web.dev/passkey-form-autofill&quot;&gt;Sign in with a passkey through form
autofill&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/passkey-registration/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/passkey-form-autofill&quot;&gt;Sign in with a passkey through form autofill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.imperialviolet.org/2022/09/22/passkeys.html&quot; rel=&quot;noopener&quot;&gt;Passkeys&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service&quot; rel=&quot;noopener&quot;&gt;Apple document: Authenticating a User Through a Web
Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/identity/passkeys/&quot; rel=&quot;noopener&quot;&gt;Google document: Passwordless login with
passkeys&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Yahoo! JAPAN&#39;s password-free authentication reduced inquiries by 25%, sped up sign-in time by 2.6x</title>
    <link href="https://web.dev/yahoo-japan-identity-case-study/"/>
    <updated>2022-05-10T00:00:00Z</updated>
    <id>https://web.dev/yahoo-japan-identity-case-study/</id>
    <content type="html" mode="escaped">&lt;p&gt;Yahoo! JAPAN is one of the largest media companies in Japan, providing
services such as search, news, e-commerce, and e-mail. Over 50 million users
log in to Yahoo! JAPAN services every month.&lt;/p&gt;
&lt;p&gt;Over the years, there were many attacks on user accounts and issues that led
to lost account access. Most of these issues were related to password usage
for authentication.&lt;/p&gt;
&lt;p&gt;With recent advances in authentication technology, Yahoo! JAPAN has decided to
move from password-based to passwordless authentication.&lt;/p&gt;
&lt;h2 id=&quot;why-passwordless&quot;&gt;Why passwordless? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#why-passwordless&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As Yahoo! JAPAN offers e-commerce and other money-related services, there&#39;s a
risk of significant damage to users in the event of unauthorized access or
account loss.&lt;/p&gt;
&lt;p&gt;The most common attacks related to passwords were password list attacks and
phishing scams. One of the reasons why password list attacks are common and
effective is many people&#39;s habit of using the same password for multiple
applications and websites.&lt;/p&gt;
&lt;p&gt;The following figures are the results of a survey conducted by Yahoo! JAPAN.&lt;/p&gt;
&lt;ul class=&quot;stats&quot;&gt;
&lt;div class=&quot;stats__item&quot;&gt;
&lt;p class=&quot;stats__figure&quot;&gt;
50
&lt;sub&gt;%&lt;/sub&gt;
&lt;/p&gt;
&lt;p&gt;use the same ID and password on six or more sites&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;stats__item&quot;&gt;
&lt;p class=&quot;stats__figure&quot;&gt;
60
&lt;sub&gt;%&lt;/sub&gt;
&lt;/p&gt;
&lt;p&gt;Use the same password across multiple sites&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;stats__item&quot;&gt;
&lt;p class=&quot;stats__figure&quot;&gt;
70
&lt;sub&gt;%&lt;/sub&gt;
&lt;/p&gt;
&lt;p&gt;use a password as the primary way to login&lt;/p&gt;
&lt;/div&gt;
&lt;/ul&gt;
&lt;p&gt;Users often forget their passwords, which accounted for the majority of
password-related inquiries. There were also inquiries from users who had
forgotten their login IDs in addition to their passwords. At their peak, these
inquiries accounted for more than a third of all account-related inquiries.&lt;/p&gt;
&lt;p&gt;By going passwordless, Yahoo! JAPAN aimed to improve not only security, but
also usability, without placing any extra burden on users.&lt;/p&gt;
&lt;p&gt;From a security perspective, eliminating passwords from the user
authentication process reduces the damage from list-based attacks, and from a
usability perspective, providing an authentication method that does not rely
on remembering passwords prevents situations where a user is unable to login
because they forgot their password.&lt;/p&gt;
&lt;h2 id=&quot;yahoo-japans-passwordless-initiatives&quot;&gt;Yahoo! JAPAN&#39;s passwordless initiatives &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#yahoo-japans-passwordless-initiatives&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Yahoo! JAPAN is taking a number of steps to promote passwordless
authentication, which can be broadly divided into three categories:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Provide an alternative means of authentication to passwords.&lt;/li&gt;
&lt;li&gt;Password deactivation.&lt;/li&gt;
&lt;li&gt;Passwordless account registration.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first two initiatives aimed at existing users, while passwordless
registration is aimed at new users.&lt;/p&gt;
&lt;h3 id=&quot;1-providing-an-alternative-means-of-authentication-to-passwords&quot;&gt;1. Providing an alternative means of authentication to passwords &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#1-providing-an-alternative-means-of-authentication-to-passwords&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Yahoo! JAPAN offers the following alternatives to passwords.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/sms-otp-form/&quot;&gt;SMS authentication&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/identity/fido&quot; rel=&quot;noopener&quot;&gt;FIDO with WebAuthn&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In addition, we also offer authentication methods such as e-mail
authentication, password combined with SMS OTP (one time password), and
password combined with email OTP.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Yahoo! JAPAN restricts their service to phone carriers operating inside Japan and prohibits VoIP SMS. &lt;/div&gt;&lt;/aside&gt;
&lt;h4 id=&quot;sms-authentication&quot;&gt;SMS authentication &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#sms-authentication&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;SMS authentication is a system which allows a registered user to receive a
six-digit authentication code through SMS. Once the user receives the SMS,
they can enter the authentication code in the app or website.&lt;/p&gt;
&lt;figure class=&quot;screenshot&quot;&gt;
&lt;img alt=&quot;&quot; decoding=&quot;async&quot; height=&quot;437&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 668px) 668px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/h08m9uzVJg9uNzM3LE5k.jpg?auto=format&amp;w=1336 1336w&quot; width=&quot;668&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Apple has long allowed iOS to read SMS messages and suggest authentication
codes from the text body. Recently, it&#39;s become possible to use suggestions by
specifying &amp;quot;one-time-code&amp;quot; in the &lt;code&gt;autocomplete&lt;/code&gt; attribute of the input
element. Chrome on Android, Windows, and Mac can provide the same experience
using the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WebOTP_API&quot; rel=&quot;noopener&quot;&gt;WebOTP API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;one-time-code&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;sign in&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;OTPCredential&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; input &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;code&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ac &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AbortController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;closest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;form&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;submit&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      ac&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;otp&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;transport&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sms&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ac&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;otp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; otp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Both approaches are designed to prevent phishing by including the domain in
the SMS body and providing suggestions only for the specified domain.&lt;/p&gt;
&lt;p&gt;For more information about the WebOTP API and &lt;code&gt;autocomplete=&amp;quot;one-time-code&amp;quot;&lt;/code&gt;,
check out &lt;a href=&quot;https://web.dev/sms-otp-form/&quot;&gt;SMS OTP form best practices&lt;/a&gt;.&lt;/p&gt;
&lt;figure class=&quot;screenshot&quot;&gt;
&lt;img alt=&quot;&quot; decoding=&quot;async&quot; height=&quot;523&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 387px) 387px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/Szaf3C0hfjLNkTWAVf9B.png?auto=format&amp;w=774 774w&quot; width=&quot;387&quot; /&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;fido-with-webauthn&quot;&gt;FIDO with WebAuthn &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#fido-with-webauthn&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;FIDO with WebAuthn uses a hardware authenticator to generate a public key
cipher pair and prove possession. When a smartphone is used as the
authenticator, it can be combined with biometric authentication (such as
fingerprint sensors or facial recognition) to perform one-step two-factor
authentication. In this case, only the signature and the success indication
from the biometric authentication are sent to the server, so there is no risk
of biometric data theft.&lt;/p&gt;
&lt;p&gt;The following diagram shows the server-client configuration for FIDO. The
client authenticator authenticates the user with biometrics and signs the
result using public key cryptography. The private key used to create the
signature is securely stored in a &lt;a href=&quot;https://en.wikipedia.org/wiki/Trusted_execution_environment&quot; rel=&quot;noopener&quot;&gt;TEE (Trusted Execution Environment)&lt;/a&gt;
or similar location. A service provider that uses FIDO is called an RP
(relying party).&lt;/p&gt;
&lt;figure&gt;
   &lt;img alt=&quot;&quot; decoding=&quot;async&quot; height=&quot;400&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/PkFYWnOZABjPu7Zc7rXN.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;figcaption style=&quot;text-align:left&quot;&gt;
&lt;p&gt;Once the user performs the authentication (commonly with a biometric scan or PIN), the authenticator uses a private key to send a signed verification signal to the browser. The browser then shares that signal with the RP&#39;s website.&lt;/p&gt;&lt;p&gt;The RP website then sends the signed verification signal to the RP&#39;s server, which verifies the signature against the public key to complete the authentication.&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;For more information, read
&lt;a href=&quot;https://fidoalliance.org/fido-authentication/&quot; rel=&quot;noopener&quot;&gt;authentication guidelines from the FIDO Alliance&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Yahoo! JAPAN supports FIDO on Android (mobile app and web), iOS (mobile app
and web), Windows (Edge, Chrome, Firefox), and macOS (Safari, Chrome). As a
consumer service, FIDO can be used on almost any device, which makes it a good
option for promoting passwordless authentication.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
       &lt;tr&gt;
   &lt;td&gt;
    &lt;strong&gt;Operating System&lt;/strong&gt;
   &lt;/td&gt;
   &lt;td&gt;
    &lt;strong&gt;Support for FIDO&lt;/strong&gt;
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
  &lt;tr&gt;
   &lt;td&gt;
    Android
   &lt;/td&gt;
   &lt;td&gt;
    Apps, Browser (Chrome)
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
    iOS
   &lt;/td&gt;
   &lt;td&gt;
    Apps (iOS14 or later), Browser (Safari 14 or later)
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
    Windows
   &lt;/td&gt;
   &lt;td&gt;
    Browser (Edge, Chrome, Firefox)
   &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;
    Mac (Big Sur or later)
   &lt;/td&gt;
   &lt;td&gt;
    Browser (Safari, Chrome)
   &lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;figure class=&quot;alignright&quot;&gt;
  &lt;img alt=&quot;&quot; class=&quot;screenshot&quot; decoding=&quot;async&quot; height=&quot;497&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 520px) 520px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/iq0dODcbp3WcPUGTwHkl.png?auto=format&amp;w=1040 1040w&quot; width=&quot;520&quot; /&gt;
  &lt;figcaption&gt;Sample Yahoo! JAPAN prompt to authenticate with FIDO.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Yahoo! JAPAN recommends that users register for FIDO with WebAuthn, if they&#39;ve
not already authenticated through other means. When a user needs to log in
with the same device, they can quickly authenticate using a biometric sensor.&lt;/p&gt;
&lt;p&gt;Users must set up FIDO authentication with all devices they use to log in to
Yahoo! JAPAN.&lt;/p&gt;
&lt;p&gt;To promote passwordless authentication and be considerate of users who are
transitioning away from passwords, we provide multiple means of
authentication. This means that different users can have different
authentication method settings, and the authentication methods they can use
may differ from browser to browser. We believe it&#39;s a better experience if
users log in using the same authentication method each time.&lt;/p&gt;
&lt;p&gt;To meet these requirements, it&#39;s necessary to track previous authentication
methods and link this information to the client by storing it in the form of
cookies, etc. We can then analyze how different browsers and applications are
used for authentication. The user is asked to provide appropriate
authentication based on the user&#39;s settings, the previous authentication
methods used, and the minimum level of authentication required.&lt;/p&gt;
&lt;h3 id=&quot;2-password-deactivation&quot;&gt;2. Password deactivation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#2-password-deactivation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Yahoo! JAPAN asks users to set up an alternative authentication method and
then disable their password so that it cannot be used. In addition to setting
up alternative authentication, disabling password authentication (therefore
making it impossible to sign in with only a password) helps protect users from
list-based attacks.&lt;/p&gt;
&lt;p&gt;We&#39;ve taken the following steps to encourage users to disable their
passwords.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Promoting alternative authentication methods when users reset their passwords.&lt;/li&gt;
&lt;li&gt;Encouraging users to set up easy-to-use authentication methods (such as
FIDO) and disable passwords for situations that require frequent
authentication.&lt;/li&gt;
&lt;li&gt;Urging users to disable their passwords before using high-risk services,
such as e-commerce payments.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a user forgets their password, they can run an account recovery. Previously
this involved a password reset. Now, users can choose to set up a different
authentication method, and we encourage them to do so.&lt;/p&gt;
&lt;h3 id=&quot;3-passwordless-account-registration&quot;&gt;3. Passwordless account registration &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#3-passwordless-account-registration&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;New users can create password-free Yahoo! JAPAN accounts. Users are first
required to register with an SMS authentication. Once they&#39;ve logged in, we
encourage the user to set up FIDO authentication.&lt;/p&gt;
&lt;p&gt;Since FIDO is a per-device setting, it can be difficult to recover an account,
should the device become inoperable. Therefore, we require users to keep their
phone number registered, even after they&#39;ve set up additional authentication.&lt;/p&gt;
&lt;h3 id=&quot;key-challenges-for-passwordless-authentication&quot;&gt;Key challenges for passwordless authentication &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#key-challenges-for-passwordless-authentication&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Passwords rely on human memory and are device-independent. On the other hand,
the authentication methods introduced thus far in our passwordless initiative
are device-dependent. This poses several challenges.&lt;/p&gt;
&lt;p&gt;When multiple devices are used, there are some issues related to usability:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When using SMS authentication to log in from a PC, users must check their
mobile phone for incoming SMS messages. This may be inconvenient, as it
requires the user&#39;s phone to be available and easy to access at any time.&lt;/li&gt;
&lt;li&gt;With FIDO, especially with platform authenticators, a user with multiple
devices will be unable to authenticate on unregistered devices.
Registration must be completed for each device they intend to use.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FIDO authentication is tied to specific devices, which requires they remain in
the user&#39;s possession and active.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the service contract is canceled, it will no longer be possible to send
SMS messages to the registered phone number.&lt;/li&gt;
&lt;li&gt;FIDO stores private keys on a specific device. If the device is lost, those
keys are unusable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yahoo! JAPAN is taking various steps to address these problems.&lt;/p&gt;
&lt;p&gt;The most important solution is to encourage users to set up multiple
authentication methods. This provides alternative account access when devices
are lost. Since FIDO keys are device-dependent, it is also good practice to
register FIDO private keys on multiple devices.&lt;/p&gt;
&lt;p&gt;Alternatively, users can use the &lt;a href=&quot;https://web.dev/sms-otp-form/&quot;&gt;WebOTP API to pass SMS verification
codes&lt;/a&gt; from an Android phone to Chrome on a PC.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Apple recently announced the &lt;a href=&quot;https://developer.apple.com/documentation/authenticationservices/public-private_key_authentication/supporting_passkeys&quot;&gt;passkeys&lt;/a&gt; feature. Apple uses iCloud Keychain to share the private key (stored on the device) among devices that are signed in with the same Apple ID, which eliminates the need for registration for each device.  The FIDO Alliance recognizes the importance of account recovery issues and has published a &lt;a href=&quot;https://fidoalliance.org/white-paper-multiple-authenticators-for-reducing-account-recovery-needs-for-fido-enabled-consumer-accounts/&quot;&gt;white paper&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;We believe that addressing these issues will become even more important as
passwordless authentication spreads.&lt;/p&gt;
&lt;h3 id=&quot;promoting-passwordless-authentication&quot;&gt;Promoting passwordless authentication &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#promoting-passwordless-authentication&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Yahoo! JAPAN has been working on these passwordless initiatives since 2015.
This began with the acquisition of FIDO server certification in May 2015,
followed by the introduction of SMS authentication, a password deactivation
feature, and FIDO support for each device.&lt;/p&gt;
&lt;p&gt;Today, more than 30 million monthly active users have already disabled their
passwords and are using non-password authentication methods. Yahoo! JAPAN&#39;s
support for FIDO started with Chrome on Android, and now more than 10 million
users have set up FIDO authentication.&lt;/p&gt;
&lt;p&gt;As a result of Yahoo! JAPAN&#39;s initiatives, the percentage of inquiries
involving forgotten login IDs or passwords has decreased by 25% compared to the
period when the number of such inquiries was at its highest, and we have also
been able to confirm that unauthorized access has declined as a result of the
increase in the number of passwordless accounts.&lt;/p&gt;
&lt;p&gt;Since FIDO is so easy to set up, it has a particularly high conversion rate.
In fact, Yahoo! JAPAN has found that FIDO has a higher CVR than SMS
authentication.&lt;/p&gt;
&lt;ul class=&quot;stats&quot;&gt;
&lt;div class=&quot;stats__item&quot;&gt;
&lt;p class=&quot;stats__figure&quot;&gt;
25
&lt;sub&gt;%&lt;/sub&gt;
&lt;/p&gt;
&lt;p&gt;Decrease in requests for forgotten credentials&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;stats__item&quot;&gt;
&lt;p class=&quot;stats__figure&quot;&gt;
74
&lt;sub&gt;%&lt;/sub&gt;
&lt;/p&gt;
&lt;p&gt;Users succeed with FIDO authentication&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;stats__item&quot;&gt;
&lt;p class=&quot;stats__figure&quot;&gt;
65
&lt;sub&gt;%&lt;/sub&gt;
&lt;/p&gt;
&lt;p&gt;Succeed with SMS verification&lt;/p&gt;
&lt;/div&gt;
&lt;/ul&gt;
&lt;p&gt;FIDO has a higher success rate than SMS authentication, and faster average and
median authentication times. As for passwords, some groups have short
authentication times, and we suspect that this is due to the browser&#39;s
&lt;a href=&quot;https://web.dev/sign-in-form-best-practices/#current-password&quot;&gt;&lt;code&gt;autocomplete=&amp;quot;current-password&amp;quot;&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;figure class=&quot;screenshot&quot;&gt;
&lt;img alt=&quot;Graph comparison of authentication time for passwords, SMS, and FIDO.&quot; decoding=&quot;async&quot; height=&quot;478&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 799px) 799px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/VbsHyyQopiec0718rMq2kTE1hke2/KhkGTZgYgmUM9pJGrg5h.png?auto=format&amp;w=1598 1598w&quot; width=&quot;799&quot; /&gt;
&lt;figcaption&gt;On average, FIDO takes 8 seconds to authenticate, while passwords take 21 seconds, and SMS verification takes 27.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The greatest difficulty for offering passwordless accounts is not the addition
of authentication methods, but &lt;strong&gt;popularizing the use of authenticators&lt;/strong&gt;.
If the experience of using a passwordless service is not user-friendly, the
transition will not be easy.&lt;/p&gt;
&lt;p&gt;We believe that to achieve improved security we must first improve usability,
which will require unique innovations for each service.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/yahoo-japan-identity-case-study/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Password authentication is risky in terms of security, and it also poses
challenges in terms of usability. Now that technologies supporting
non-password authentication, such as WebOTP API and FIDO, are more widely
available, it&#39;s time to start working toward passwordless authentication.&lt;/p&gt;
&lt;p&gt;At Yahoo! JAPAN, taking this approach has had a definite effect on both
usability and security. However, many users are still using passwords, so we
will continue to encourage more users to switch to passwordless authentication
methods. We will also continue improving our products to optimize the user
experience for passwordless authentication methods.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by olieman.eth on &lt;a href=&quot;https://unsplash.com/&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content>
    <author>
      <name>Yuya Ito</name>
    </author><author>
      <name>Eiji Kitamura</name>
    </author><author>
      <name>Alexandra White</name>
    </author>
  </entry>
  
  <entry>
    <title>Save Credentials from Forms</title>
    <link href="https://web.dev/security-credential-management-save-forms/"/>
    <updated>2022-02-24T00:00:00Z</updated>
    <id>https://web.dev/security-credential-management-save-forms/</id>
    <content type="html" mode="escaped">&lt;figure&gt;
&lt;video&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/C47gYyWYVMMhDmtYSLOWazuyePF2/hglb1gObe5c9zqoF2VuX.mov&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
&lt;figcaption&gt;Save Credentials from sign-in forms&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Keep your registration and sign-in forms as simple as possible.&lt;/p&gt;
&lt;p&gt;Save credentials from sign-in forms
so users won&#39;t have to sign in again when they return.&lt;/p&gt;
&lt;p&gt;To store user credentials from forms:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Include &lt;code&gt;autocomplete&lt;/code&gt; in the form.&lt;/li&gt;
&lt;li&gt;Prevent the form from submitting.&lt;/li&gt;
&lt;li&gt;Authenticate by sending a request.&lt;/li&gt;
&lt;li&gt;Store the credential.&lt;/li&gt;
&lt;li&gt;Update the UI or proceed to the personalized page.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;include-autocomplete-in-the-form&quot;&gt;Include &lt;code&gt;autocomplete&lt;/code&gt; in the form &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#include-autocomplete-in-the-form&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before moving forward,
check if your form includes &lt;code&gt;autocomplete&lt;/code&gt; attributes.
This helps the Credential Management API find the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt;
from the form and construct a credential object.&lt;/p&gt;
&lt;p&gt;This also helps browsers not supporting the Credential Management API
to understand its semantics.
Learn more about autofill in
&lt;a href=&quot;https://cloudfour.com/thinks/autofill-what-web-devs-should-know-but-dont/&quot; rel=&quot;noopener&quot;&gt;this article&lt;/a&gt; by
&lt;a href=&quot;https://medium.com/@grigs&quot; rel=&quot;noopener&quot;&gt;Jason Grigsby&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;signup&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;post&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;email&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;username email&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;display-name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;password&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;new-password&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;submit&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Sign Up!&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;prevent-the-form-from-submitting&quot;&gt;Prevent the form from submitting &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#prevent-the-form-from-submitting&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the user presses the submit button, prevent the form from submitting, which would otherwise
result in a page transition:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#signup&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    f&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;submit&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;By preventing a page transition,
you can retain the credential information while verifying its authenticity.&lt;/p&gt;
&lt;h2 id=&quot;authenticate-by-sending-a-request&quot;&gt;Authenticate by sending a request &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#authenticate-by-sending-a-request&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To authenticate the user, deliver credential information to your server using AJAX.&lt;/p&gt;
&lt;p&gt;On the server side, create an endpoint (or simply alter an existing endpoint)
that responds with HTTP code 200 or 401, so that it’s clear to the browser
whether the sign-up/sign-in/change password is successful or not.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Try sign-in with AJAX&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;POST&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;include&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;store-the-credential&quot;&gt;Store the credential &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#store-the-credential&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To store a credential, first check if the API is available,
then instantiate a
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/PasswordCredential&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PasswordCredential&lt;/code&gt;&lt;/a&gt;
with the form element as an argument
either synchronously or asynchronously.
Call
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/store&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.store()&lt;/code&gt;&lt;/a&gt;.
If the API is not available,
you can simply forward the profile information to the next step.&lt;/p&gt;
&lt;p&gt;Synchronous example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PasswordCredential&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Asynchronous example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once the request succeeds, store the credential information.
(Don&#39;t store the credentials information if the request failed
as doing so confuses returning users.)&lt;/p&gt;
&lt;p&gt;When the Chrome browser obtains credential information,
a notification pops up asking to store a credential
(or federation provider).&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;store credential&quot; decoding=&quot;async&quot; height=&quot;202&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 385px) 385px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/gbo4Q6zSt7ryUzb8d3KB.png?auto=format&amp;w=770 770w&quot; width=&quot;385&quot; /&gt;
  &lt;figcaption&gt;Notification for an auto signed-in user&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;update-the-ui&quot;&gt;Update the UI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#update-the-ui&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If everything went well, update the UI using the profile information,
or proceed to the personalized page.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;profile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token function&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token function&quot;&gt;showError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Sign-in Failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;full-code-example&quot;&gt;Full code example &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#full-code-example&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Get form&#39;s DOM object&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; f &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#signup&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;f&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;submit&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Stop submitting form by itself&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Try sign-in with AJAX&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;POST&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FormData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;credentials&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;include&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Sign-in failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Instantiate PasswordCredential with the form&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PasswordCredential&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;target&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Successful sign-in&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Sign-in failed&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;showError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Sign-in Failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;browser-compatibility&quot;&gt;Browser compatibility &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#browser-compatibility&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;passwordcredential&quot;&gt;&lt;code&gt;PasswordCredential&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#passwordcredential&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 51, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      51
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 79, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
79
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/PasswordCredential#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;navigatorcredentialsstore&quot;&gt;&lt;code&gt;navigator.credentials.store()&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#navigatorcredentialsstore&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 51, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      51
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 60, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      60
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 79, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      79
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 13, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      13
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/store#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-save-forms/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author><author>
      <name>Meggin Kearney</name>
    </author>
  </entry>
  
  <entry>
    <title>Security headers quick reference</title>
    <link href="https://web.dev/security-headers/"/>
    <updated>2021-05-18T00:00:00Z</updated>
    <id>https://web.dev/security-headers/</id>
    <content type="html" mode="escaped">&lt;p&gt;This article lists the most important security headers you can use to protect
your website. Use it to understand web-based security features, learn how to
implement them on your website, and as a reference for when you need a reminder.&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Security headers recommended for websites that handle sensitive user data:&lt;/dt&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#csp&quot;&gt;Content Security Policy (CSP)&lt;/a&gt;&lt;/dd&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#tt&quot;&gt;Trusted Types&lt;/a&gt;&lt;/dd&gt;
&lt;dt&gt;Security headers recommended for all websites:&lt;/dt&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#xcto&quot;&gt;X-Content-Type-Options&lt;/a&gt;&lt;/dd&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#xfo&quot;&gt;X-Frame-Options&lt;/a&gt;&lt;/dd&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#corp&quot;&gt;Cross-Origin Resource Policy (CORP)&lt;/a&gt;&lt;/dd&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#coop&quot;&gt;Cross-Origin Opener Policy (COOP)&lt;/a&gt;&lt;/dd&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#hsts&quot;&gt;HTTP Strict Transport Security (HSTS)&lt;/a&gt;&lt;/dd&gt;
&lt;dt&gt;Security headers for websites with advanced capabilities:&lt;/dt&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#cors&quot;&gt;Cross-Origin Resource Sharing (CORS)&lt;/a&gt;&lt;/dd&gt;
&lt;dd&gt;&lt;a href=&quot;https://web.dev/security-headers/#coep&quot;&gt;Cross-Origin Embedder Policy (COEP)&lt;/a&gt;&lt;/dd&gt;
&lt;/dl&gt;
&lt;details&gt;
&lt;summary&gt;
  Known threats on the web
  &lt;p class=&quot;text-base color-core-text gap-top-base&quot;&gt; Before diving into security headers, learn about known threats on the web and why you&#39;d want to use these security headers.&lt;/p&gt;
&lt;/summary&gt;
&lt;p&gt;Before diving into security headers, learn about known threats on the web
and why you&#39;d want to use these security headers.&lt;/p&gt;
&lt;h3 id=&quot;protect-your-site-from-injection-vulnerabilities&quot;&gt;Protect your site from injection vulnerabilities &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#protect-your-site-from-injection-vulnerabilities&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Injection vulnerabilities arise when untrusted data processed by your
application can affect its behavior and, commonly, lead to the execution of
attacker-controlled scripts. The most common vulnerability caused by injection
bugs is &lt;a href=&quot;https://portswigger.net/web-security/cross-site-scripting&quot; rel=&quot;noopener&quot;&gt;cross-site
scripting&lt;/a&gt; (XSS) in
its various forms, including &lt;a href=&quot;https://portswigger.net/web-security/cross-site-scripting/reflected&quot; rel=&quot;noopener&quot;&gt;reflected
XSS&lt;/a&gt;,
&lt;a href=&quot;https://portswigger.net/web-security/cross-site-scripting/stored&quot; rel=&quot;noopener&quot;&gt;stored XSS&lt;/a&gt;,
&lt;a href=&quot;https://portswigger.net/web-security/cross-site-scripting/dom-based&quot; rel=&quot;noopener&quot;&gt;DOM-based
XSS&lt;/a&gt;, and
other variants.&lt;/p&gt;
&lt;p&gt;An XSS vulnerability can typically give an attacker complete access to user data
processed by the application and any other information hosted in the same &lt;a href=&quot;https://web.dev/same-site-same-origin/#origin&quot;&gt;web
origin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Traditional defenses against injections include consistent use of autoescaping
HTML template systems, avoiding the use of &lt;a href=&quot;https://domgo.at/cxss/sinks&quot; rel=&quot;noopener&quot;&gt;dangerous JavaScript
APIs&lt;/a&gt;, and properly processing user data by hosting
file uploads in a separate domain and sanitizing user-controlled HTML.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#csp&quot;&gt;Content Security Policy (CSP)&lt;/a&gt; to control which scripts can be
executed by your application to mitigate the risk of injections.&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#tt&quot;&gt;Trusted Types&lt;/a&gt; to enforce sanitization of data passed into dangerous
JavaScript APIs.&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#xcto&quot;&gt;X-Content-Type-Options&lt;/a&gt; to prevent the browser from
misinterpreting the MIME types of your website&#39;s resources, which can lead to
script execution.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;isolate-your-site-from-other-websites&quot;&gt;Isolate your site from other websites &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#isolate-your-site-from-other-websites&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The openness of the web allows websites to interact with each other in ways that
can violate an application&#39;s security expectations. This includes unexpectedly
making authenticated requests or embedding data from another application in the
attacker&#39;s document, allowing the attacker to modify or read application data.&lt;/p&gt;
&lt;p&gt;Common vulnerabilities that undermine web isolation include
&lt;a href=&quot;https://portswigger.net/web-security/clickjacking&quot; rel=&quot;noopener&quot;&gt;clickjacking&lt;/a&gt;, &lt;a href=&quot;https://portswigger.net/web-security/csrf&quot; rel=&quot;noopener&quot;&gt;cross-site
request forgery&lt;/a&gt; (CSRF), &lt;a href=&quot;https://www.scip.ch/en/?labs.20160414&quot; rel=&quot;noopener&quot;&gt;cross-site
script inclusion&lt;/a&gt; (XSSI), and various
&lt;a href=&quot;https://xsleaks.dev/&quot; rel=&quot;noopener&quot;&gt;cross-site leaks&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#xfo&quot;&gt;X-Frame-Options&lt;/a&gt; to prevent your documents from being embedded by a
malicious website.&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#corp&quot;&gt;Cross-Origin Resource Policy (CORP)&lt;/a&gt; to prevent your website&#39;s
resources from being included by a cross-origin website.&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#coop&quot;&gt;Cross-Origin Opener Policy (COOP)&lt;/a&gt; to protect your website&#39;s
windows from interactions by malicious websites.&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#cors&quot;&gt;Cross-Origin Resource Sharing (CORS)&lt;/a&gt; to control access to your
website&#39;s resources from cross-origin documents.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/post-spectre-webdev/&quot; rel=&quot;noopener&quot;&gt;Post-Spectre Web
Development&lt;/a&gt; is a great read
if you are interested in these headers.&lt;/p&gt;
&lt;h3 id=&quot;build-a-powerful-website-securely&quot;&gt;Build a powerful website securely &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#build-a-powerful-website-securely&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://ieeexplore.ieee.org/document/8835233&quot; rel=&quot;noopener&quot;&gt;Spectre&lt;/a&gt; puts any data loaded
into the same &lt;a href=&quot;https://web.dev/why-coop-coep/&quot;&gt;browsing context group&lt;/a&gt; potentially readable
despite &lt;a href=&quot;https://web.dev/same-origin-policy/&quot;&gt;same-origin policy&lt;/a&gt;. Browsers restrict features
that may possibly exploit the vulnerability behind a special environment called
&amp;quot;&lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;cross-origin isolation&lt;/a&gt;&amp;quot;. With cross-origin isolation, you can
use powerful features such as &lt;code&gt;SharedArrayBuffer&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#coep&quot;&gt;Cross-Origin Embedder Policy (COEP)&lt;/a&gt; along with &lt;a href=&quot;https://web.dev/security-headers/#coop&quot;&gt;COOP&lt;/a&gt; to
enable cross-origin isolation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;encrypt-traffic-to-your-site&quot;&gt;Encrypt traffic to your site &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#encrypt-traffic-to-your-site&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Encryption issues appear when an application does not fully encrypt data in
transit, allowing eavesdropping attackers to learn about the user&#39;s interactions
with the application.&lt;/p&gt;
&lt;p&gt;Insufficient encryption can arise in the following cases: not using HTTPS,
&lt;a href=&quot;https://web.dev/what-is-mixed-content/&quot;&gt;mixed content&lt;/a&gt;, setting cookies without the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Cookies#restrict_access_to_cookies&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Secure&lt;/code&gt;
attribute&lt;/a&gt;
(or &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Cookies#Cookie_prefixes&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;__Secure&lt;/code&gt;
prefix&lt;/a&gt;),
or &lt;a href=&quot;https://blog.detectify.com/2018/04/26/cors-misconfigurations-explained/&quot; rel=&quot;noopener&quot;&gt;lax CORS validation
logic&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;a href=&quot;https://web.dev/security-headers/#hsts&quot;&gt;HTTP Strict Transport Security (HSTS)&lt;/a&gt; to consisitently serve your
contents through HTTPS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;csp&quot;&gt;Content Security Policy (CSP) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#csp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.google.com/about/appsecurity/learning/xss/&quot; rel=&quot;noopener&quot;&gt;Cross-Site Scripting
(XSS)&lt;/a&gt; is an attack
where a vulnerability on a website allows a malicious script to be injected and
executed.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Content-Security-Policy&lt;/code&gt; provides an added layer to mitigate XSS attacks by
restricting which scripts can be executed by the page.&lt;/p&gt;
&lt;p&gt;It&#39;s recommended that you enable strict CSP using one of the following approaches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you render your HTML pages on the server, use &lt;strong&gt;a nonce-based strict CSP&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If your HTML has to be served statically or cached, for example if it&#39;s a
single-page application, use &lt;strong&gt;a hash-based strict CSP&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;label&quot;&gt;Example usage: A nonce-based CSP&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;Content-Security-Policy:&lt;br /&gt;  script-src &#39;nonce-{RANDOM1}&#39; &#39;strict-dynamic&#39; https: &#39;unsafe-inline&#39;;&lt;br /&gt;  object-src &#39;none&#39;;&lt;br /&gt;  base-uri &#39;none&#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use CSP
&lt;/summary&gt;
&lt;h3 id=&quot;recommended-usages&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  A CSP can be an &lt;em&gt;extra&lt;/em&gt; protection against XSS attacks; you should still make sure to escape (and sanitize) user input.  &lt;/div&gt;&lt;/aside&gt;
&lt;h4 id=&quot;nonce-based-csp&quot;&gt;1. Use a nonce-based strict CSP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#nonce-based-csp&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;If you render your HTML pages on the server, use &lt;strong&gt;a nonce-based strict CSP&lt;/strong&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  A nonce is a random number used only once. A nonce-based CSP is only secure if you can generate a different nonce for each response. If you can&#39;t do this, use &lt;a href=&quot;https://web.dev/security-headers/#hash-based-csp&quot;&gt;a hash-based CSP&lt;/a&gt; instead.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Generate a new script nonce value for every request on the server side and set
the following header:&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;server configuration file&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;Content-Security-Policy:&lt;br /&gt;  script-src &#39;nonce-{RANDOM1}&#39; &#39;strict-dynamic&#39; https: &#39;unsafe-inline&#39;;&lt;br /&gt;  object-src &#39;none&#39;;&lt;br /&gt;  base-uri &#39;none&#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In HTML, in order to load the scripts, set the &lt;code&gt;nonce&lt;/code&gt; attribute of all
&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags to the same &lt;code&gt;{RANDOM1}&lt;/code&gt; string.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;index.html&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{RANDOM1}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/script1.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;nonce&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;{RANDOM1}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Inline scripts can be used with the `nonce` attribute.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;a href=&quot;https://photos.google.com/&quot; rel=&quot;noopener&quot;&gt;Google Photos&lt;/a&gt; is a good nonce-based strict CSP
example. Use DevTools to see how it&#39;s used.&lt;/p&gt;
&lt;h4 id=&quot;hash-based-csp&quot;&gt;2. Use a hash-based strict CSP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#hash-based-csp&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;If your HTML has to be served statically or cached, for example if you&#39;re
building a single-page application, use &lt;strong&gt;a hash-based strict CSP&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;server configuration file&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;Content-Security-Policy:&lt;br /&gt;  script-src &#39;sha256-{HASH1}&#39; &#39;sha256-{HASH2}&#39; &#39;strict-dynamic&#39; https: &#39;unsafe-inline&#39;;&lt;br /&gt;  object-src &#39;none&#39;;&lt;br /&gt;  base-uri &#39;none&#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In HTML, you&#39;ll need to inline your scripts in order to apply a hash-based
policy, because &lt;a href=&quot;https://wpt.fyi/results/content-security-policy/script-src/script-src-sri_hash.sub.html?label=master&amp;amp;label=experimental&amp;amp;aligned&quot; rel=&quot;noopener&quot;&gt;most browsers don&#39;t support hashing external
scripts&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;index.html&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// your script1, inlined&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// your script2, inlined&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;To load external scripts, read &amp;quot;Load sourced scripts dynamically&amp;quot; under
&lt;a href=&quot;https://web.dev/strict-csp/#hash-based-csp&quot;&gt;Option B: Hash-based CSP Response Header&lt;/a&gt; section.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://csp-evaluator.withgoogle.com/&quot; rel=&quot;noopener&quot;&gt;CSP Evaluator&lt;/a&gt; is a good tool to
evaluate your CSP, but at the same time a good nonce-based strict CSP example.
Use DevTools to see how it&#39;s used.&lt;/p&gt;
&lt;h3 id=&quot;supported-browsers&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  * &lt;code&gt;https:&lt;/code&gt; is a fallback for Safari and &lt;code&gt;unsafe-inline&lt;/code&gt; is a fallback for very old browser versions. &lt;code&gt;https:&lt;/code&gt; and &lt;code&gt;unsafe-inline&lt;/code&gt; don&#39;t make your policy less safe because they will be ignored by browsers who support &lt;code&gt;strict-dynamic&lt;/code&gt;. Read more in &lt;a href=&quot;https://web.dev/strict-csp/#step-4-add-fallbacks-to-support-safari-and-older-browsers&quot;&gt;Add fallbacks to support Safari and older browsers&lt;/a&gt;. * Safari does &lt;em&gt;not&lt;/em&gt; support &lt;code&gt;strict-dynamic&lt;/code&gt; yet. But a strict CSP like in the examples above is safer than an allowlist CSP (and much safer than no CSP at all) for all of your users. Even in Safari, a strict CSP protects your site from some types of XSS attacks, because the presence of the CSP disallows certain unsafe patterns.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;other-things-to-note-about-csp&quot;&gt;Other things to note about CSP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#other-things-to-note-about-csp&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;frame-ancestors&lt;/code&gt;&lt;/a&gt;
directive protects your site from clickjacking—a risk that arises if you allow
untrusted sites to embed yours. If you prefer simpler solution, you can use
&lt;a href=&quot;https://web.dev/security-headers/#xfo&quot;&gt;&lt;code&gt;X-Frame-Options&lt;/code&gt;&lt;/a&gt; to block being loaded, but &lt;code&gt;frame-ancestors&lt;/code&gt; gives
you an advanced configuration to only allow specific origins as embedders.&lt;/li&gt;
&lt;li&gt;You may have used &lt;a href=&quot;https://web.dev/fixing-mixed-content/#content-security-policy&quot;&gt;a CSP to ensure that all of your site&#39;s resources are
loaded over HTTPS&lt;/a&gt;. This has
become less relevant: nowadays, most browsers block
&lt;a href=&quot;https://web.dev/what-is-mixed-content/&quot;&gt;mixed-content&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You can also set a CSP in &lt;a href=&quot;https://web.dev/strict-csp/#step-2-set-a-strict-csp-and-prepare-your-scripts&quot;&gt;report-only
mode&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If you can&#39;t set a CSP as a header server-side, you can also set it as a meta
tag. Note that you can&#39;t use &lt;strong&gt;report-only&lt;/strong&gt; mode for meta tags (though
&lt;a href=&quot;https://github.com/w3c/webappsec-csp/issues/277&quot; rel=&quot;noopener&quot;&gt;this may change&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;learn-more&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/strict-csp&quot;&gt;Mitigate XSS with a Strict Content Security Policy (CSP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html&quot; rel=&quot;noopener&quot;&gt;Content Security Policy Cheat
Sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;tt&quot;&gt;Trusted Types &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#tt&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://portswigger.net/web-security/cross-site-scripting/dom-based&quot; rel=&quot;noopener&quot;&gt;DOM-based
XSS&lt;/a&gt; is an
attack where a malicious data is passed into a sink that supports dynamic code
execution such as &lt;code&gt;eval()&lt;/code&gt; or &lt;code&gt;.innerHTML&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Trusted Types provide the tools to write, security review, and maintain
applications free of DOM XSS. They can be enabled via &lt;a href=&quot;https://web.dev/security-headers/#csp&quot;&gt;CSP&lt;/a&gt; and make
JavaScript code secure by default by limiting dangerous web APIs to only accept
a special object—a Trusted Type.&lt;/p&gt;
&lt;p&gt;To create these objects you can define security policies in which you can ensure
that security rules (such as escaping or sanitization) are consistently applied
before the data is written to the DOM. These policies are then the only places
in code that could potentially introduce DOM XSS.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example usages&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Content-Security-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value csp languages-csp&quot;&gt;require-trusted-types-for &#39;script&#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Feature detection&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;trustedTypes &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; trustedTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createPolicy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Name and create a policy&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; policy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; trustedTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;escapePolicy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function-variable function&quot;&gt;createHTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&lt;span class=&quot;token escape&quot;&gt;\&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&amp;amp;lt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&amp;amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Assignment of raw strings is blocked by Trusted Types.&lt;/span&gt;&lt;br /&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;some string&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This throws an exception.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Assignment of Trusted Types is accepted safely.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; escaped &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; policy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&amp;lt;img src=x onerror=alert(1)&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; escaped&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// &#39;&amp;amp;lt;img src=x onerror=alert(1)&amp;amp;gt;&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use Trusted Types
&lt;/summary&gt;
&lt;h3 id=&quot;recommended-usages-2&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Enforce Trusted Types for dangerous DOM sinks&lt;/p&gt;
 &lt;p class=&quot;label&quot;&gt;CSP and Trusted Types header:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Content-Security-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value csp languages-csp&quot;&gt;require-trusted-types-for &#39;script&#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Currently &lt;code&gt;&#39;script&#39;&lt;/code&gt; is the only acceptable value for
&lt;code&gt;require-trusted-types-for&lt;/code&gt; directive.&lt;/p&gt;
&lt;p&gt;Of course, you can combine Trusted Types with other CSP directives:&lt;/p&gt;
 &lt;p class=&quot;label&quot;&gt; Merging a nonce-based CSP from above with Trusted Types: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;Content-Security-Policy:&lt;br /&gt;  script-src &#39;nonce-{RANDOM1}&#39; &#39;strict-dynamic&#39; https: &#39;unsafe-inline&#39;;&lt;br /&gt;  object-src &#39;none&#39;;&lt;br /&gt;  base-uri &#39;none&#39;;&lt;br /&gt;  require-trusted-types-for &#39;script&#39;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt; &lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  You may limit allowed Trusted Types policy names by setting an additional &lt;code&gt;trusted-types&lt;/code&gt; directive (for example, &lt;code&gt;trusted-types myPolicy&lt;/code&gt;). However, this is not a requirement.  &lt;/div&gt;&lt;/aside&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Define a policy&lt;/p&gt;
 &lt;p class=&quot;label&quot;&gt;Policy:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Feature detection&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;trustedTypes &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; trustedTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;createPolicy&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Name and create a policy&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; policy &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; trustedTypes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;escapePolicy&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function-variable function&quot;&gt;createHTML&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; str&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&lt;span class=&quot;token escape&quot;&gt;\&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&amp;amp;lt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&amp;amp;gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt; &lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  You can define policies with arbitrary names unless you limit the names of allowed Trusted Types policies by setting the &lt;code&gt;trusted-types&lt;/code&gt; directive.  &lt;/div&gt;&lt;/aside&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Apply the policy&lt;/p&gt;
 &lt;p class=&quot;label&quot;&gt;Use the policy when writing data to the DOM:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Assignment of raw strings are blocked by Trusted Types.&lt;/span&gt;&lt;br /&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;some string&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// This throws an exception.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Assignment of Trusted Types is accepted safely.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; escaped &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; policy&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&amp;lt;img src=x onerror=alert(1)&gt;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;el&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;innerHTML &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; escaped&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// &#39;&amp;amp;lt;img src=x onerror=alert(1)&amp;amp;gt;&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;With &lt;code&gt;require-trusted-types-for &#39;script&#39;&lt;/code&gt;, using a trusted type is a
requirement. Using any dangerous DOM API with a string will result in an
error.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;supported-browsers-2&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-2&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/trusted-types/&quot;&gt;Prevent DOM-based cross-site scripting vulnerabilities with Trusted
Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy/require-trusted-types-for&quot; rel=&quot;noopener&quot;&gt;CSP: require-trusted-types-for - HTTP |
MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types&quot; rel=&quot;noopener&quot;&gt;CSP: trusted-types - HTTP |
MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.compass-demo.com/trusted-types/&quot; rel=&quot;noopener&quot;&gt;Trusted Types demo&lt;/a&gt;—open DevTools Inspector and see
what is happening&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;xcto&quot;&gt;X-Content-Type-Options &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#xcto&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a malicious HTML document is served from your domain (for example, if an
image uploaded to a photo service contains valid HTML markup), some browsers
will treat it as an active document and allow it to execute scripts in the
context of the application, leading to a &lt;a href=&quot;https://www.google.com/about/appsecurity/learning/xss/&quot; rel=&quot;noopener&quot;&gt;cross-site scripting
bug&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt; prevents it by instructing the browser that
the &lt;a href=&quot;https://mimesniff.spec.whatwg.org/#introduction&quot; rel=&quot;noopener&quot;&gt;MIME type&lt;/a&gt; set in the
&lt;code&gt;Content-Type&lt;/code&gt; header for a given response is correct. This header is
recommended for &lt;strong&gt;all of your resources&lt;/strong&gt;.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example usage&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;nosniff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use X-Content-Type-Options
&lt;/summary&gt;
&lt;h3 id=&quot;recommended-usages-3&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages-3&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt; is recommended for all resources served from
your server along with the correct &lt;code&gt;Content-Type&lt;/code&gt; header.&lt;/p&gt;
&lt;img alt=&quot;X-Content-Type-Options: nosniff&quot; decoding=&quot;async&quot; height=&quot;237&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/IWqRWe9R1mOJImmMbLoM.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p class=&quot;label&quot;&gt;Example headers sent with a document HTML&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;nosniff&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Content-Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;text/html; charset=utf-8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;supported-browsers-3&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-3&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 64, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      64
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 50, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      50
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 11, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      11
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Content-Type-Options#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-3&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-3&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Content-Type-Options&quot; rel=&quot;noopener&quot;&gt;X-Content-Type-Options - HTTP MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;xfo&quot;&gt;X-Frame-Options &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#xfo&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If a malicious website can embed your site as an iframe, this may allow
attackers to invoke unintended actions by the user with
&lt;a href=&quot;https://portswigger.net/web-security/clickjacking&quot; rel=&quot;noopener&quot;&gt;clickjacking&lt;/a&gt;. Also, in some
cases &lt;a href=&quot;https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)&quot; rel=&quot;noopener&quot;&gt;Spectre-type
attacks&lt;/a&gt; give
malicious websites a chance to learn about the contents of an embedded document.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;X-Frame-Options&lt;/code&gt; indicates whether or not a browser should be allowed to render
a page in a &lt;code&gt;&amp;lt;frame&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;embed&amp;gt;&lt;/code&gt;, or &lt;code&gt;&amp;lt;object&amp;gt;&lt;/code&gt;. &lt;strong&gt;All documents&lt;/strong&gt;
are recommended to send this header to indicate whether they allow being
embedded by other documents.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  If you need more granular control such as allowing only a specific origin to embed the document, use the &lt;a href=&quot;https://web.dev/security-headers/#csp&quot;&gt;CSP&lt;/a&gt; &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors&quot;&gt;&lt;code&gt;frame-ancestors&lt;/code&gt;&lt;/a&gt; directive.  &lt;/div&gt;&lt;/aside&gt;
&lt;p class=&quot;label&quot;&gt;Example usage&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;X-Frame-Options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;DENY&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use X-Frame-Options
&lt;/summary&gt;
&lt;h3 id=&quot;recommended-usages-4&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages-4&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;All documents that are not designed to be embedded should use &lt;code&gt;X-Frame-Options&lt;/code&gt; header.&lt;/p&gt;
&lt;p&gt;You can try how the following configurations affect loading an iframe on &lt;a href=&quot;https://cross-origin-isolation.glitch.me/&quot; rel=&quot;noopener&quot;&gt;this
demo&lt;/a&gt;. Change the &lt;code&gt;X-Frame-Options&lt;/code&gt;
dropdown menu and click the &lt;strong&gt;Reload the iframe&lt;/strong&gt; button.&lt;/p&gt;
&lt;h4 id=&quot;protects-your-website-from-being-embedded-by-any-other-websites&quot;&gt;Protects your website from being embedded by any other websites &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#protects-your-website-from-being-embedded-by-any-other-websites&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Deny being embedded by any other documents.&lt;/p&gt;
&lt;img alt=&quot;X-Frame-Options: DENY&quot; decoding=&quot;async&quot; height=&quot;237&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2ZM5obgGK38CMcZ75PkH.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;X-Frame-Options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;DENY&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;protects-your-website-from-being-embedded-by-any-cross-origin-websites&quot;&gt;Protects your website from being embedded by any cross-origin websites &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#protects-your-website-from-being-embedded-by-any-cross-origin-websites&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Allow being embedded only by same-origin documents.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;X-Frame-Options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;SAMEORIGIN&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  Documents being embeddable by default means the web developers need to explicitly send &lt;code&gt;DENY&lt;/code&gt; or &lt;code&gt;SAMEORIGIN&lt;/code&gt; to stop being embedded and protect themselves from side-channel attacks. The Chrome team is considering switching to block document embeds by default so that websites will be secure even if they don&#39;t explicitly set the header. In that new world, documents would need to explicitly opt-in to be embedded.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;supported-browsers-4&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-4&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Frame-Options#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-4&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-4&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Frame-Options&quot; rel=&quot;noopener&quot;&gt;X-Frame-Options - HTTP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;corp&quot;&gt;Cross-Origin Resource Policy (CORP) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#corp&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An attacker can embed resources from another origin, for example from your site,
to learn information about them by exploiting web-based &lt;a href=&quot;https://xsleaks.dev/&quot; rel=&quot;noopener&quot;&gt;cross-site
leaks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Cross-Origin-Resource-Policy&lt;/code&gt; mitigates this risk by indicating the set of
websites it can be loaded by. The header takes one of three values:
&lt;code&gt;same-origin&lt;/code&gt;, &lt;code&gt;same-site&lt;/code&gt;, and &lt;code&gt;cross-origin&lt;/code&gt;. &lt;strong&gt;All resources&lt;/strong&gt; are
recommended to send this header to indicate whether they allow being loaded by
other websites.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example usage&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Resource-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use CORP
&lt;/summary&gt;
&lt;h3 id=&quot;recommended-usages-5&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages-5&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It is recommended that &lt;strong&gt;all&lt;/strong&gt; resources are served with one of the following
three headers.&lt;/p&gt;
&lt;p&gt;You can try how the following configurations affect loading resources under a
&lt;a href=&quot;https://web.dev/security-headers/#coep&quot;&gt;&lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; environment&lt;/a&gt; on &lt;a href=&quot;https://cross-origin-isolation.glitch.me/?coep=require-corp&amp;amp;&quot; rel=&quot;noopener&quot;&gt;this
demo&lt;/a&gt;. Change the
&lt;strong&gt;Cross-Origin-Resource-Policy&lt;/strong&gt; dropdown menu and click the &lt;strong&gt;Reload the
iframe&lt;/strong&gt; or &lt;strong&gt;Reload the image&lt;/strong&gt; button to see the effect.&lt;/p&gt;
&lt;h4 id=&quot;allow-resources-to-be-loaded-cross-origin&quot;&gt;Allow resources to be loaded &lt;code&gt;cross-origin&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#allow-resources-to-be-loaded-cross-origin&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;It&#39;s recommended that CDN-like services apply &lt;code&gt;cross-origin&lt;/code&gt; to resources
(since they are usually loaded by cross-origin pages), unless they are already served
through &lt;a href=&quot;https://web.dev/security-headers/#cors&quot;&gt;CORS&lt;/a&gt; which has a similar effect.&lt;/p&gt;
&lt;img alt=&quot;Cross-Origin-Resource-Policy: cross-origin&quot; decoding=&quot;async&quot; height=&quot;234&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/qP2mspVMC6RazxDjWUrL.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Resource-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;cross-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;limit-resources-to-be-loaded-from-the-same-origin&quot;&gt;Limit resources to be loaded from the &lt;code&gt;same-origin&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#limit-resources-to-be-loaded-from-the-same-origin&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;same-origin&lt;/code&gt; should be applied to resources that are intended to be loaded only
by same-origin pages. You should apply this to resources that include sensitive
information about the user, or responses of an API that is intended to be called
only from the same origin.&lt;/p&gt;
&lt;p&gt;Keep in mind that resources with this header can still be loaded directly, for
example by navigating to the URL in a new browser window. Cross-Origin Resource
Policy only protects the resource from being embedded by other websites.&lt;/p&gt;
&lt;img alt=&quot;Cross-Origin-Resource-Policy: same-origin&quot; decoding=&quot;async&quot; height=&quot;238&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7UzYMWsbKkh89m5ZImvj.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Resource-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;limit-resources-to-be-loaded-from-the-same-site&quot;&gt;Limit resources to be loaded from the &lt;code&gt;same-site&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#limit-resources-to-be-loaded-from-the-same-site&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;same-site&lt;/code&gt; is recommended to be applied to resources that are similar to above
but are intended to be loaded by other subdomains of your site.&lt;/p&gt;
&lt;img alt=&quot;Cross-Origin-Resource-Policy: same-site&quot; decoding=&quot;async&quot; height=&quot;233&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/R9yNRGSJ4xABc560WRJI.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Resource-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-site&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  To learn more about the difference between same-origin and same-site, check out &lt;a href=&quot;https://web.dev/same-site-same-origin/&quot;&gt;Understanding &amp;quot;same-site&amp;quot; and &amp;quot;same-origin&amp;quot;&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;supported-browsers-5&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-5&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 73, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      73
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 74, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      74
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 79, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      79
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-5&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-5&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://resourcepolicy.fyi/&quot; rel=&quot;noopener&quot;&gt;Consider deploying cross-origin resource policy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;Making your website &amp;quot;cross-origin isolated&amp;quot; using COOP and COEP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/why-coop-coep/&quot;&gt;Why you need &amp;quot;cross-origin isolated&amp;quot; for powerful features&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;coop&quot;&gt;Cross-Origin Opener Policy (COOP) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#coop&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An attacker&#39;s website can open another site in a popup window to learn
information about it by exploiting web-based &lt;a href=&quot;https://xsleaks.dev/&quot; rel=&quot;noopener&quot;&gt;cross-site
leaks&lt;/a&gt;. In some cases, this may also allow the
exploitation of side-channel attacks based on
&lt;a href=&quot;https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)&quot; rel=&quot;noopener&quot;&gt;Spectre&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Cross-Origin-Opener-Policy&lt;/code&gt; header provides a way for a document to isolate
itself from cross-origin windows opened through &lt;code&gt;window.open()&lt;/code&gt; or a link with
&lt;code&gt;target=&amp;quot;_blank&amp;quot;&lt;/code&gt; without &lt;code&gt;rel=&amp;quot;noopener&amp;quot;&lt;/code&gt;. As a result, any cross-origin opener
of the document will have no reference to it and will not be able to interact
with it.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example usage&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin-allow-popups&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use COOP
&lt;/summary&gt;
&lt;h3 id=&quot;recommended-usages-6&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages-6&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can try how the following configurations affect communication with a
cross-origin popup window on &lt;a href=&quot;https://cross-origin-isolation.glitch.me/&quot; rel=&quot;noopener&quot;&gt;this demo&lt;/a&gt;.
Change the &lt;strong&gt;Cross-Origin-Opener-Policy&lt;/strong&gt; dropdown menu for both the document
and the popup window, click the &lt;strong&gt;Open a popup&lt;/strong&gt; button then click &lt;strong&gt;Send a
postMessage&lt;/strong&gt; to see if the message is actually delivered.&lt;/p&gt;
&lt;h4 id=&quot;isolate-a-document-from-cross-origin-windows&quot;&gt;Isolate a document from cross-origin windows &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#isolate-a-document-from-cross-origin-windows&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Setting &lt;code&gt;same-origin&lt;/code&gt; puts the document to be isolated from cross-origin
document windows.&lt;/p&gt;
&lt;img alt=&quot;Cross-Origin-Opener-Policy: same-origin&quot; decoding=&quot;async&quot; height=&quot;235&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/mSDG9auD7r5asxGJvJjg.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;isolate-a-document-from-cross-origin-windows-but-allow-popups&quot;&gt;Isolate a document from cross-origin windows but allow popups &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#isolate-a-document-from-cross-origin-windows-but-allow-popups&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Setting &lt;code&gt;same-origin-allow-popups&lt;/code&gt; allows a document to retain a reference to
its popup windows unless they set COOP with &lt;code&gt;same-origin&lt;/code&gt; or
&lt;code&gt;same-origin-allow-popups&lt;/code&gt;. This means &lt;code&gt;same-origin-allow-popups&lt;/code&gt; can still
protect the document from being referenced when opened as a popup window, but
allow it to communicate with its own popups.&lt;/p&gt;
&lt;img alt=&quot;Cross-Origin-Opener-Policy: same-origin-allow-popups&quot; decoding=&quot;async&quot; height=&quot;233&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/2uJZ0s2VnjxJUcBI2Ol9.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin-allow-popups&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;allow-a-document-to-be-referenced-by-cross-origin-windows&quot;&gt;Allow a document to be referenced by cross-origin windows &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#allow-a-document-to-be-referenced-by-cross-origin-windows&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;unsafe-none&lt;/code&gt; is the default value but you can explicitly indicate that this
document can be opened by a cross-origin window and retain mutual access.&lt;/p&gt;
&lt;img alt=&quot;Cross-Origin-Opener-Policy: unsafe-none&quot; decoding=&quot;async&quot; height=&quot;233&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/oSco89ZT3RP7gZzNKDjY.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  &lt;code&gt;unsafe-none&lt;/code&gt; being the default means the web developers need to send &lt;code&gt;same-origin&lt;/code&gt; or &lt;code&gt;same-origin-allow-popups&lt;/code&gt; explicitly to protect their website from side-channel attacks.  &lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;unsafe-none&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  Features such as &lt;code&gt;SharedArrayBuffer&lt;/code&gt; or &lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt; are disabled by default. Some browsers allow you to use them in &amp;quot;cross-origin isolated&amp;quot; contexts, which require you to set &lt;a href=&quot;https://web.dev/security-headers/#coop&quot;&gt;COOP&lt;/a&gt; and &lt;a href=&quot;https://web.dev/security-headers/#coep&quot;&gt;COEP&lt;/a&gt; headers.  To learn more, read &lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;Making your website &amp;quot;cross-origin isolated&amp;quot; using COOP and COEP&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h4 id=&quot;report-patterns-incompatible-with-coop&quot;&gt;Report patterns incompatible with COOP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#report-patterns-incompatible-with-coop&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;You can receive reports when COOP prevents cross-window interactions with the
Reporting API.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin; report-to=&quot;coop&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;COOP also supports a report-only mode so you can receive reports without
actually blocking communication between cross-origin documents.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy-Report-Only&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin; report-to=&quot;coop&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;supported-browsers-6&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-6&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 83, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      83
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 79, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      79
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 83, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      83
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 15.2, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      15.2
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-6&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-6&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/why-coop-coep/&quot;&gt;Why you need &amp;quot;cross-origin isolated&amp;quot; for powerful features&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;cors&quot;&gt;Cross-Origin Resource Sharing (CORS) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#cors&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Unlike other items in this article, Cross-Origin Resource Sharing (CORS) is not
a header, but a browser mechanism that requests and permits access to
cross-origin resources.&lt;/p&gt;
&lt;p&gt;By default, browsers enforce &lt;a href=&quot;https://web.dev/same-origin-policy/&quot;&gt;the same-origin policy&lt;/a&gt; to
prevent a web page from accessing cross-origin resources. For example, when a
cross-origin image is loaded, even though it&#39;s displayed on the web page
visually, the JavaScript on the page doesn&#39;t have access to the image&#39;s data.
The resource provider can relax restrictions and allow other websites to read
the resource by opting-in with CORS.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example usage&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;https://example.com&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use CORS
&lt;/summary&gt;
&lt;p&gt;Before looking into how to configure CORS, it&#39;s helpful to understand the
distinction between request types. Depending on request details, a request will
be classified as a &lt;strong&gt;simple request&lt;/strong&gt; or a &lt;strong&gt;preflighted request&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Criteria for a simple request:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The method is &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;HEAD&lt;/code&gt;, or &lt;code&gt;POST&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The custom headers only include &lt;code&gt;Accept&lt;/code&gt;, &lt;code&gt;Accept-Language&lt;/code&gt;,
&lt;code&gt;Content-Language&lt;/code&gt;, and &lt;code&gt;Content-Type&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Content-Type&lt;/code&gt; is &lt;code&gt;application/x-www-form-urlencoded&lt;/code&gt;,
&lt;code&gt;multipart/form-data&lt;/code&gt;, or &lt;code&gt;text/plain&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything else is classified as a preflighted request. For more details,
check out &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/CORS#simple_requests&quot; rel=&quot;noopener&quot;&gt;Cross-Origin Resource Sharing (CORS) - HTTP |
MDN&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;recommended-usages-7&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages-7&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;simple-request&quot;&gt;Simple request &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#simple-request&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;When a request meets the simple request criteria, the browser sends a
cross-origin request with an &lt;code&gt;Origin&lt;/code&gt; header that indicates the requesting
origin.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example request header&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;Get / HTTP/1.1&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;https://example.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;label&quot;&gt;Example response header&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;https://example.com&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Origin: https://example.com&lt;/code&gt; indicates that the
&lt;code&gt;https://example.com&lt;/code&gt; can access the contents of the response. Resources meant
to be readable by any site can set this header to &lt;code&gt;*&lt;/code&gt;, in which case the
browser will only require the request to be made &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Request/credentials#value&quot; rel=&quot;noopener&quot;&gt;without
credentials&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Credentials: true&lt;/code&gt; indicates that requests which carry
credentials (cookies) are allowed to load the resource. Otherwise,
authenticated requests will be rejected even if the requesting origin is
present in the &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can try how the simple request affect loading resources under a
&lt;a href=&quot;https://web.dev/security-headers/#coep&quot;&gt;&lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; environment&lt;/a&gt; on &lt;a href=&quot;https://cross-origin-isolation.glitch.me/?coep=require-corp&amp;amp;&quot; rel=&quot;noopener&quot;&gt;this
demo&lt;/a&gt;. Click the
&lt;strong&gt;Cross-Origin Resource Sharing&lt;/strong&gt; checkbox and click the &lt;strong&gt;Reload the image&lt;/strong&gt;
button to see the effect.&lt;/p&gt;
&lt;h4 id=&quot;preflighted-requests&quot;&gt;Preflighted requests &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#preflighted-requests&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A preflighted request is preceded with an &lt;code&gt;OPTIONS&lt;/code&gt; request to check if the
subsequent request is allowed to be sent.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example request header&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token request-line&quot;&gt;&lt;span class=&quot;token method property&quot;&gt;OPTIONS&lt;/span&gt; &lt;span class=&quot;token request-target url&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token http-version property&quot;&gt;HTTP/1.1&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;https://example.com&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Request-Method&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;POST&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Request-Headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;X-PINGOTHER, Content-Type&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Request-Method: POST&lt;/code&gt; allows the following request to be made
with the  &lt;code&gt;POST&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Request-Headers: X-PINGOTHER, Content-Type&lt;/code&gt; allows the
requester to set the &lt;code&gt;X-PINGOTHER&lt;/code&gt; and &lt;code&gt;Content-Type&lt;/code&gt; HTTP headers in the
subsequent request.&lt;/li&gt;
&lt;/ul&gt;
&lt;p class=&quot;label&quot;&gt;Example response headers&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;https://example.com&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Credentials&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Methods&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;POST, GET, OPTIONS&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Allow-Headers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;X-PINGOTHER, Content-Type&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Access-Control-Max-Age&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;86400&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Methods: POST, GET, OPTIONS&lt;/code&gt; indicates that subsequent
requests can be made with the  &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;OPTIONS&lt;/code&gt; methods.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Headers: X-PINGOTHER, Content-Type&lt;/code&gt; indicates subsequent
requests can include the &lt;code&gt;X-PINGOTHER&lt;/code&gt; and &lt;code&gt;Content-Type&lt;/code&gt; headers.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Max-Age: 86400&lt;/code&gt;  indicates that the result of the preflighted
request can be cached for 86400 seconds.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;supported-browsers-7&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-7&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 3.5, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      3.5
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-7&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-7&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/cross-origin-resource-sharing/&quot;&gt;Cross-Origin Resource Sharing (CORS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/CORS&quot; rel=&quot;noopener&quot;&gt;Cross-Origin Resource Sharing (CORS) - HTTP |
MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;coep&quot;&gt;Cross-Origin Embedder Policy (COEP) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#coep&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To reduce the ability of &lt;a href=&quot;https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)&quot; rel=&quot;noopener&quot;&gt;Spectre-based
attacks&lt;/a&gt; to
steal cross-origin resources, features such as &lt;code&gt;SharedArrayBuffer&lt;/code&gt; or
&lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt; are disabled by default.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; prevents documents and workers from
loading cross-origin resources such as images, scripts, stylesheets, iframes and
others unless these resources explicitly opt into being loaded via &lt;a href=&quot;https://web.dev/security-headers/#cors&quot;&gt;CORS&lt;/a&gt;
or &lt;a href=&quot;https://web.dev/security-headers/#corp&quot;&gt;CORP&lt;/a&gt; headers. COEP can be combined with&lt;code&gt;Cross-Origin-Opener-Policy&lt;/code&gt;
to opt a document into &lt;a href=&quot;https://web.dev/cross-origin-isolation-guide/&quot;&gt;cross-origin isolation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Use &lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; when you want to enable
&lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;cross-origin isolation&lt;/a&gt; for your document.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example usage&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Embedder-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;require-corp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use COEP
&lt;/summary&gt;
&lt;h3 id=&quot;example-usages&quot;&gt;Example usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#example-usages&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;COEP takes a single value of &lt;code&gt;require-corp&lt;/code&gt;. By sending this header, you can
instruct the browser to block loading resources that do not opt-in via
&lt;a href=&quot;https://web.dev/security-headers/#cors&quot;&gt;CORS&lt;/a&gt; or &lt;a href=&quot;https://web.dev/security-headers/#corp&quot;&gt;CORP&lt;/a&gt;.&lt;/p&gt;
&lt;img alt=&quot;How COEP works&quot; decoding=&quot;async&quot; height=&quot;410&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;You can try how the following configurations affect loading resources on &lt;a href=&quot;https://cross-origin-isolation.glitch.me/&quot; rel=&quot;noopener&quot;&gt;this
demo&lt;/a&gt;. Change the
&lt;strong&gt;Cross-Origin-Embedder-Policy&lt;/strong&gt; dropdown menu, the
&lt;strong&gt;Cross-Origin-Resource-Policy&lt;/strong&gt; dropdown menu, the &lt;strong&gt;Report Only&lt;/strong&gt; checkbox etc
to see how they affect loading resources. Also, open &lt;a href=&quot;https://reporting-endpoint.glitch.me/&quot; rel=&quot;noopener&quot;&gt;the reporting endpoint
demo&lt;/a&gt; to see if the blocked resources are
reported.&lt;/p&gt;
&lt;h4 id=&quot;enable-cross-origin-isolation&quot;&gt;Enable cross-origin isolation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#enable-cross-origin-isolation&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Enable &lt;a href=&quot;https://web.dev/coop-coep&quot;&gt;cross-origin isolation&lt;/a&gt; by sending
&lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; along with
&lt;code&gt;Cross-Origin-Opener-Policy: same-origin&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Embedder-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;require-corp&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;report-resources-incompatible-withn-coep&quot;&gt;Report resources incompatible withn COEP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#report-resources-incompatible-withn-coep&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;You can receive reports of blocked resources caused by COEP with the Reporting
API.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Embedder-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;require-corp; report-to=&quot;coep&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;COEP also supports report-only mode so you can receive reports without actually
blocking loading resources.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Embedder-Policy-Report-Only&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;require-corp; report-to=&quot;coep&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;supported-browsers-8&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-8&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 83, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      83
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 79, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      79
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 83, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      83
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 15.2, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      15.2
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-8&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-8&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;Making your website &amp;quot;cross-origin isolated&amp;quot; using COOP and COEP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/why-coop-coep/&quot;&gt;Why you need &amp;quot;cross-origin isolated&amp;quot; for powerful features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/cross-origin-isolation-guide/&quot;&gt;A guide to enable cross-origin isolation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;hsts&quot;&gt;HTTP Strict Transport Security (HSTS) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#hsts&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Communication over a plain HTTP connection is not encrypted, making the
transferred data accessible to network-level eavesdroppers.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Strict-Transport-Security&lt;/code&gt; header informs the browser that it should never load
the site using HTTP and use HTTPS instead. Once it&#39;s set, the browser will use
HTTPS instead of HTTP to access the domain without a redirect for a duration
defined in the header.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;Example usage&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Strict-Transport-Security&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value hsts languages-hsts&quot;&gt;max-age=31536000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  How to use HSTS
&lt;/summary&gt;
&lt;h3 id=&quot;recommended-usages-8&quot;&gt;Recommended usages &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#recommended-usages-8&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;All websites that transition from HTTP to HTTPS should respond with a
&lt;code&gt;Strict-Transport-Security&lt;/code&gt; header when a request with HTTP is received.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Strict-Transport-Security&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value hsts languages-hsts&quot;&gt;max-age=31536000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;supported-browsers-9&quot;&gt;Supported browsers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#supported-browsers-9&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 4, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      4
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 12, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      12
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 7, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      7
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Strict-Transport-Security#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;h3 id=&quot;learn-more-9&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#learn-more-9&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Strict-Transport-Security&quot; rel=&quot;noopener&quot;&gt;Strict-Transport-Security -
HTTP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-headers/#further-reading&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/post-spectre-webdev/&quot; rel=&quot;noopener&quot;&gt;Post-Spectre Web Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author><author>
      <name>Maud Nalpas</name>
    </author><author>
      <name>Artur Janc</name>
    </author>
  </entry>
  
  <entry>
    <title>Fill OTP forms within cross-origin iframes with WebOTP API</title>
    <link href="https://web.dev/web-otp-iframe/"/>
    <updated>2021-04-21T00:00:00Z</updated>
    <id>https://web.dev/web-otp-iframe/</id>
    <content type="html" mode="escaped">&lt;p&gt;SMS OTPs (one-time passwords) are commonly used to verify phone numbers, for
example as a second step in authentication, or to verify payments on the web.
However, switching between the browser and the SMS app, to copy-paste or manually
enter the OTP makes it easy to make mistakes and adds friction to the user experience.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://web.dev/web-otp&quot;&gt;WebOTP API&lt;/a&gt; gives websites the ability to programmatically
obtain the one-time password from a SMS message and enter it
automatically in the form for the users with just one tap without switching the
app. The SMS is specially-formatted and bound to the origin, so it mitigates
chances for phishing websites to steal the OTP as well.&lt;/p&gt;
&lt;p&gt;One use case that has yet to be supported in WebOTP was targeting an origin
inside an iframe. This is typically used for payment confirmation, especially
with &lt;a href=&quot;https://en.wikipedia.org/wiki/3-D_Secure&quot; rel=&quot;noopener&quot;&gt;3D Secure&lt;/a&gt;. Having &lt;a href=&quot;https://wicg.github.io/sms-one-time-codes/&quot; rel=&quot;noopener&quot;&gt;the common
format to support cross-origin
iframes&lt;/a&gt;, WebOTP API now delivers
OTPs bound to nested origins starting in Chrome 91.&lt;/p&gt;
&lt;h2 id=&quot;how-webotp-api-works&quot;&gt;How WebOTP API works &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#how-webotp-api-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;WebOTP API itself is simple enough:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; otp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;otp&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;transport&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sms&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The SMS message must be &lt;a href=&quot;https://web.dev/web-otp/#format&quot;&gt;formatted with the origin-bound one-time
codes&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Your OTP is: 123456.&lt;br /&gt;&lt;br /&gt;@web-otp.glitch.me #12345&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Notice that at the last line it contains the origin to be bound to preceded with
a &lt;code&gt;@&lt;/code&gt; followed by the OTP preceded with a &lt;code&gt;#&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When the text message arrives, an info bar pops up and prompts the user to
verify their phone number. After the user clicks the &lt;code&gt;Verify&lt;/code&gt; button, the
browser automatically forwards the OTP to the site and resolves the
&lt;code&gt;navigator.credentials.get()&lt;/code&gt;. The website can then extract the OTP and complete
the verification process.&lt;/p&gt;
&lt;p&gt;Learn the basics of using WebOTP at &lt;a href=&quot;https://web.dev/web-otp/&quot;&gt;Verify phone numbers on the web with the
WebOTP API&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;cross-origin-iframes-use-cases&quot;&gt;Cross-origin iframes use cases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#cross-origin-iframes-use-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Entering an OTP in a form within a cross-origin iframe is common in payment
scenarios. Some credit card issuers require an additional verification step to
check the payer&#39;s authenticity. This is called 3D Secure and the form is
typically exposed within an iframe on the same page as if it&#39;s a part of the
payment flow.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A user visits &lt;code&gt;shop.example&lt;/code&gt; to purchase a pair of shoes with a credit card.&lt;/li&gt;
&lt;li&gt;After entering the credit card number, the integrated payment provider shows a
form from &lt;code&gt;bank.example&lt;/code&gt; within an iframe asking the user to verify their
phone number for fast checkout.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bank.example&lt;/code&gt; sends an SMS that contains an OTP to the user so that they can
enter it to verify their identity.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-to-use-webotp-api-from-a-cross-origin-iframe&quot;&gt;How to use WebOTP API from a cross-origin iframe &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#how-to-use-webotp-api-from-a-cross-origin-iframe&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To use WebOTP API from within a cross-origin iframe, you need to do two
things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Annotate both the top-frame origin and the iframe origin in the SMS text
message.&lt;/li&gt;
&lt;li&gt;Configure permissions policy to allow the cross-origin iframe to receive OTP
from the user directly.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;video autoplay=&quot;&quot; controls=&quot;&quot; height=&quot;600&quot; loop=&quot;&quot; muted=&quot;&quot; preload=&quot;auto&quot; width=&quot;300&quot; style=&quot;--vid-width: 300; --vid-height: 600&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/Ba3OSkSsB4NwFkHGOuvc.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    WebOTP API within an iframe in action.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You can try the demo yourself at
&lt;a href=&quot;https://web-otp-iframe-demo.stackblitz.io/&quot; rel=&quot;noopener&quot;&gt;https://web-otp-iframe-demo.stackblitz.io&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;annotate-bound-origins-to-the-sms-text-message&quot;&gt;Annotate bound-origins to the SMS text message &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#annotate-bound-origins-to-the-sms-text-message&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When WebOTP API is called from within an iframe, the SMS text message must
include the top-frame origin preceded by &lt;code&gt;@&lt;/code&gt; followed by the OTP preceded by &lt;code&gt;#&lt;/code&gt;
followed by the iframe origin preceded by &lt;code&gt;@&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;@shop.example #123456 @bank.exmple&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;configure-permissions-policy&quot;&gt;Configure Permissions Policy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#configure-permissions-policy&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To use WebOTP in a cross-origin iframe, the embedder must grant access to this
API via otp-credentials &lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/permissions-policy/&quot; rel=&quot;noopener&quot;&gt;permissions policy&lt;/a&gt; to avoid unintended
behavior. In general there are two ways to achieve this goal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;via HTTP Header:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Permissions-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;otp-credentials=(self &quot;https://bank.example&quot;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;via iframe &lt;code&gt;allow&lt;/code&gt; attribute:&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;iframe&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://bank.example/…&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;allow&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;otp-credentials&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;iframe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;See &lt;a href=&quot;https://developer.chrome.com/docs/privacy-sandbox/permissions-policy/#example-permissions-policy-setups/&quot; rel=&quot;noopener&quot;&gt;more examples on how to specify a permission policy
&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;caveats&quot;&gt;Caveats &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#caveats&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;nesting-levels&quot;&gt;Nesting levels &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#nesting-levels&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;At the moment Chrome only supports WebOTP API calls from cross-origin iframes
that have &lt;strong&gt;no more than one&lt;/strong&gt; unique origin in its ancestor chain. In the
following scenarios:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a.com -&amp;gt; b.com&lt;/li&gt;
&lt;li&gt;a.com -&amp;gt; b.com -&amp;gt; b.com&lt;/li&gt;
&lt;li&gt;a.com -&amp;gt; a.com -&amp;gt; b.com&lt;/li&gt;
&lt;li&gt;a.com -&amp;gt; b.com -&amp;gt; c.com&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;using WebOTP in b.com is supported but using it in c.com is not.&lt;/p&gt;
&lt;p&gt;Note that the following scenario is also not supported because of lack of demand
and UX complexities.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a.com -&amp;gt; b.com -&amp;gt; a.com (calls WebOTP API)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;interoperability&quot;&gt;Interoperability &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#interoperability&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While browser engines other than Chromium do not implement the WebOTP API,
Safari shares the same &lt;a href=&quot;https://wicg.github.io/sms-one-time-codes/&quot; rel=&quot;noopener&quot;&gt;SMS format&lt;/a&gt;
with its &lt;code&gt;input[autocomplete=&amp;quot;one-time-code&amp;quot;]&lt;/code&gt; support. In Safari, as soon as an
SMS that contains an origin-bound one-time code format arrives with the matched
origin, the keyboard suggests to enter the OTP to the input field.&lt;/p&gt;
&lt;p&gt;As of April 2021, Safari supports iframe with &lt;a href=&quot;https://github.com/WICG/sms-one-time-codes/issues/4#issuecomment-709557866&quot; rel=&quot;noopener&quot;&gt;a unique SMS format using
&lt;code&gt;%&lt;/code&gt;&lt;/a&gt;.
However, as the spec discussion concluded to go with &lt;code&gt;@&lt;/code&gt; instead, we hope the
implementation of supported SMS format will converge.&lt;/p&gt;
&lt;h2 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your feedback is invaluable in making WebOTP API better, so go on and try it out
and &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=1136506&quot; rel=&quot;noopener&quot;&gt;let us know&lt;/a&gt;
what you think.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-otp-iframe/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/web-otp/&quot;&gt;Verify phone numbers on the web with the Web OTP
API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/sms-otp-form/&quot;&gt;SMS OTP form best practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wicg.github.io/web-otp/&quot; rel=&quot;noopener&quot;&gt;WebOTP API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wicg.github.io/sms-one-time-codes/&quot; rel=&quot;noopener&quot;&gt;Origin-bound one-time codes delivered via
SMS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rupixen?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;rupixen.com&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/s/photos/online-payment?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
    <author>
      <name>Yi Gu</name>
    </author><author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>A guide to enable cross-origin isolation</title>
    <link href="https://web.dev/cross-origin-isolation-guide/"/>
    <updated>2021-02-09T00:00:00Z</updated>
    <id>https://web.dev/cross-origin-isolation-guide/</id>
    <content type="html" mode="escaped">&lt;p&gt;This guide shows you how to enable cross-origin isolation. Cross-origin
isolation is required if you want to use
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;SharedArrayBuffer&lt;/code&gt;&lt;/a&gt;,
&lt;a href=&quot;https://web.dev/monitor-total-page-memory-usage/&quot;&gt;&lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt;&lt;/a&gt;
or &lt;a href=&quot;https://developer.chrome.com/blog/cross-origin-isolated-hr-timers/&quot; rel=&quot;noopener&quot;&gt;high resolution timer with better
precision&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you intend to enable cross-origin isolation, evaluate the impact this will
have on other cross-origin resources on your website, such as ad placements.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
  Determine where in your website &lt;code&gt;SharedArrayBuffer&lt;/code&gt; is used
  &lt;p class=&quot;text-base color-core-text gap-top-base&quot;&gt; Starting in Chrome 92, functionalities that use &lt;code&gt;SharedArrayBuffer&lt;/code&gt; will no longer work without cross-origin isolation. If you landed on this page due to a &lt;code&gt;SharedArrayBuffer&lt;/code&gt; deprecation message, it&#39;s likely either your website or one of the resources embedded on it is using &lt;code&gt;SharedArrayBuffer&lt;/code&gt;. To ensure nothing breaks on your website due to deprecation, start by identifying where it&#39;s used.&lt;/p&gt;
&lt;/summary&gt;
&lt;aside class=&quot;aside flow bg-state-good-bg color-state-good-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 24 24&quot; height=&quot;24&quot; width=&quot;24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Check&quot;&gt;   &lt;path d=&quot;M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Objective&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; * Turn on cross-origin isolation to keep using &lt;code&gt;SharedArrayBuffer&lt;/code&gt;. * If you rely on third-party code that uses &lt;code&gt;SharedArrayBuffer&lt;/code&gt;, notify the third-party provider to take action. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;If you are not sure where in your site a &lt;code&gt;SharedArrayBuffer&lt;/code&gt; is used, there are
two ways find out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using Chrome DevTools&lt;/li&gt;
&lt;li&gt;(Advanced) Using Deprecation Reporting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you already know where you are using &lt;code&gt;SharedArrayBuffer&lt;/code&gt;, skip to
&lt;a href=&quot;https://web.dev/cross-origin-isolation-guide/#analysis&quot;&gt;Analyze the impact of cross-origin isolation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;using-chrome-devtools&quot;&gt;Using Chrome DevTools &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/cross-origin-isolation-guide/#using-chrome-devtools&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/devtools/open/&quot; rel=&quot;noopener&quot;&gt;Chrome DevTools&lt;/a&gt;
allows developers to inspect websites.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/docs/devtools/open/&quot; rel=&quot;noopener&quot;&gt;Open the Chrome
DevTools&lt;/a&gt; on
the page you suspect might be using &lt;code&gt;SharedArrayBuffer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;Console&lt;/strong&gt; panel.&lt;/li&gt;
&lt;li&gt;If the page is using &lt;code&gt;SharedArrayBuffer&lt;/code&gt;, the following message will show up:&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[Deprecation] SharedArrayBuffer will require cross-origin isolation as of M92, around May 2021. See https://developer.chrome.com/blog/enabling-shared-array-buffer/ for more details. common-bundle.js:535&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;The filename and the line number at the end of the message (for example, &lt;code&gt;common-bundle.js:535&lt;/code&gt;)
indicate where the &lt;code&gt;SharedArrayBuffer&lt;/code&gt; is coming from. If it&#39;s a third-party library,
contact the developer to fix the issue. If it&#39;s implemented as part of your website, follow
the guide below to enable cross-origin isolation.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;
&lt;img alt=&quot;DevToools Console warning when SharedArrayBuffer is used without cross-origin isolation&quot; decoding=&quot;async&quot; height=&quot;163&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GOgkyjAabePTc8AG22F7.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
   &lt;figcaption&gt;
      DevToools Console warning when SharedArrayBuffer is used without cross-origin isolation.
   &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;advanced-using-deprecation-reporting&quot;&gt;(Advanced) Using Deprecation Reporting &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/cross-origin-isolation-guide/#advanced-using-deprecation-reporting&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some browsers have &lt;a href=&quot;https://wicg.github.io/deprecation-reporting/&quot; rel=&quot;noopener&quot;&gt;a reporting functionality of deprecating
APIs&lt;/a&gt; to a specified endpoint.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/coop-coep/#set-up-reporting-endpoint&quot;&gt;Set up a deprecation report server and get the reporting
URL&lt;/a&gt;. You can achieve this by either
using a public service or building one yourself.&lt;/li&gt;
&lt;li&gt;Using the URL, set the following HTTP header to pages that are potentially
serving &lt;code&gt;SharedArrayBuffer&lt;/code&gt;.&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Report-To&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;{&quot;group&quot;:&quot;default&quot;,&quot;max_age&quot;:86400,&quot;endpoints&quot;:[{&quot;url&quot;:&quot;THE_DEPRECATION_ENDPOINT_URL&quot;}]}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Once the header starts to propagate, the endpoint you registered to should
start collecting deprecation reports.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;See an example implementation here:
&lt;a href=&quot;https://cross-origin-isolation.glitch.me/&quot; rel=&quot;noopener&quot;&gt;https://cross-origin-isolation.glitch.me&lt;/a&gt;.&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id=&quot;analysis&quot;&gt;Analyze the impact of cross-origin isolation  &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/cross-origin-isolation-guide/#analysis&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Wouldn&#39;t it be great if you could assess the impact that enabling cross-origin
isolation would have on your site without actually breaking anything? The
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Cross-Origin-Opener-Policy-Report-Only&lt;/code&gt;&lt;/a&gt; and
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Cross-Origin-Embedder-Policy-Report-Only&lt;/code&gt;&lt;/a&gt;
HTTP headers allow you to do just that.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set &lt;a href=&quot;https://web.dev/coop-coep/#1.-set-the-cross-origin-opener-policy:-same-origin-header-on-the-top-level-document&quot;&gt;&lt;code&gt;Cross-Origin-Opener-Policy-Report-Only: same-origin&lt;/code&gt;&lt;/a&gt;
on your top-level document. As the name indicates, this header only sends
reports about the impact that &lt;code&gt;COOP: same-origin&lt;/code&gt; &lt;strong&gt;would&lt;/strong&gt; have on your
site—it won&#39;t actually disable communication with popup windows.&lt;/li&gt;
&lt;li&gt;Set up reporting and configure a web server to receive and save the reports.&lt;/li&gt;
&lt;li&gt;Set &lt;a href=&quot;https://web.dev/coop-coep/#3.-use-the-coep-report-only-http-header-to-assess-embedded-resources&quot;&gt;&lt;code&gt;Cross-Origin-Embedder-Policy-Report-Only: require-corp&lt;/code&gt;&lt;/a&gt;
on your top-level document. Again, this header lets you see the impact of
enabling &lt;code&gt;COEP: require-corp&lt;/code&gt; without actually affecting your site&#39;s
functioning yet. You can configure this header to send reports to the same
reporting server that you set up in the previous step.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; You can also &lt;a href=&quot;https://developer.chrome.com/docs/devtools/network/#information&quot;&gt;enable the &lt;strong&gt;Domain&lt;/strong&gt; column&lt;/a&gt; in Chrome DevTools &lt;strong&gt;Network&lt;/strong&gt; panel to get a general view of which resources would be impacted. &lt;/div&gt;&lt;/aside&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  Enabling cross-origin isolation will block the loading of cross-origin resources that you don&#39;t explicitly opt-in, and it will prevent your top-level document from being able to communicate with popup windows.  We&#39;ve been exploring ways to deploy &lt;code&gt;Cross-Origin-Resource-Policy&lt;/code&gt; at scale, as cross-origin isolation requires all subresources to explicitly opt-in. And we have come up with the idea of going in the opposite direction: &lt;a href=&quot;https://developer.chrome.com/blog/coep-credentialless-origin-trial/&quot;&gt;a new COEP &amp;quot;credentialless&amp;quot; mode&lt;/a&gt; that allows loading resources without the CORP header by stripping all their credentials. We hope this will lighten your burden of making sure the subresources are sending the &lt;code&gt;Cross-Origin-Resource-Policy&lt;/code&gt; header.  Though &lt;code&gt;credentialless&lt;/code&gt; mode is available on Chrome from version 96, it&#39;s not supported by any other browsers yet, this may cause some developers find it challenging to deploy COOP or COEP at this stage.  Also, it&#39;s known that the &lt;code&gt;Cross-Origin-Opener-Policy: same-origin&lt;/code&gt; header will break integrations that require cross-origin window interactions such as OAuth and payments. To mitigate this problem, we are exploring &lt;a href=&quot;https://github.com/whatwg/html/issues/6364&quot;&gt;relaxing the condition&lt;/a&gt; to enable cross-origin isolation to &lt;code&gt;Cross-Origin-Opener-Policy: same-origin-allow-popups&lt;/code&gt;. This way the communication with the window opened by itself will be possible.  If you want to enable cross-origin isolation but are blocked by these challenges, we recommend &lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/#origin-trial&quot;&gt;registering for an origin trial&lt;/a&gt; and waiting until the new modes are available. We are not planning to terminate the origin trial until these new modes are available.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;mitigate-the-impact-of-cross-origin-isolation&quot;&gt;Mitigate the impact of cross-origin isolation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/cross-origin-isolation-guide/#mitigate-the-impact-of-cross-origin-isolation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After you have determined which resources will be affected by cross-origin
isolation, here are general guidelines for how you actually opt-in those
cross-origin resources:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;On cross-origin resources such as images, scripts, stylesheets, iframes, and
others, set the &lt;a href=&quot;https://resourcepolicy.fyi/#cross-origin&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Cross-Origin-Resource-Policy: cross-origin&lt;/code&gt;&lt;/a&gt; header. On same-site
resources, set &lt;a href=&quot;https://resourcepolicy.fyi/#same-origin&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Cross-Origin-Resource-Policy: same-site&lt;/code&gt;&lt;/a&gt; header.&lt;/li&gt;
&lt;li&gt;For resources loadable using &lt;a href=&quot;https://web.dev/cross-origin-resource-sharing/&quot;&gt;CORS&lt;/a&gt;, make
sure it is enabled, by setting the &lt;code&gt;crossorigin&lt;/code&gt; attribute in its HTML tag
(for example, &lt;code&gt;&amp;lt;img src=&amp;quot;example.jpg&amp;quot; crossorigin&amp;gt;&lt;/code&gt;). For JavaScript fetch
request, make sure &lt;code&gt;request.mode&lt;/code&gt; is set to &lt;code&gt;cors&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you want to use powerful features such as &lt;code&gt;SharedArrayBuffer&lt;/code&gt; inside a
loaded iframe, append &lt;code&gt;allow=&amp;quot;cross-origin-isolated&amp;quot;&lt;/code&gt; to the &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If cross-origin resources loaded into iframes or worker scripts involve
another layer of iframes or worker scripts, recursively apply steps described
in this section before moving forward.&lt;/li&gt;
&lt;li&gt;Once you confirm that all cross-origin resources are opted-in, set the
&lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; header on iframes and worker
scripts (This is required regardless of same-origin or cross-origin).&lt;/li&gt;
&lt;li&gt;Make sure there are no cross-origin popup windows that require communication
through &lt;code&gt;postMessage()&lt;/code&gt;. There&#39;s no way to keep them working when
cross-origin isolation is enabled. You can move the communication to another
document that isn&#39;t cross-origin isolated, or use a different communication
method (for example, HTTP requests).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;enable-cross-origin-isolation&quot;&gt;Enable cross-origin isolation &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/cross-origin-isolation-guide/#enable-cross-origin-isolation&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After you have mitigated the impact by cross-origin isolation, here are general
guidelines to enable cross-origin isolation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set the &lt;code&gt;Cross-Origin-Opener-Policy: same-origin&lt;/code&gt; header on your top-level
document. If you had set &lt;code&gt;Cross-Origin-Opener-Policy-Report-Only: same-origin&lt;/code&gt;, replace it. This blocks communication between your top-level
document and its popup windows.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;Cross-Origin-Embedder-Policy: require-corp&lt;/code&gt; header on your top-level
document. If you had set &lt;code&gt;Cross-Origin-Embedder-Policy-Report-Only: require-corp&lt;/code&gt;, replace it. This will block the loading of cross-origin
resources that are not opted-in.&lt;/li&gt;
&lt;li&gt;Check that &lt;code&gt;self.crossOriginIsolated&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; in console to verify
that your page is cross-origin isolated.&lt;/li&gt;
&lt;/ol&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  Enabling cross-origin isolation on a local server might be a pain as simple servers do not support sending headers. You can launch Chrome with a command line flag &lt;code&gt;--enable-features=SharedArrayBuffer&lt;/code&gt; to enable &lt;code&gt;SharedArrayBuffer&lt;/code&gt; without enabling cross-origin isolation. Learn &lt;a href=&quot;https://www.chromium.org/developers/how-tos/run-chromium-with-flags&quot;&gt;how to run Chrome with a command line flag on respective platforms&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/cross-origin-isolation-guide/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;Making your website &amp;quot;cross-origin isolated&amp;quot; using COOP and COEP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/&quot; rel=&quot;noopener&quot;&gt;SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome
92&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>SMS OTP form best practices</title>
    <link href="https://web.dev/sms-otp-form/"/>
    <updated>2020-12-09T00:00:00Z</updated>
    <id>https://web.dev/sms-otp-form/</id>
    <content type="html" mode="escaped">&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;sU4MpWYrGSI&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;p&gt;Asking a user to provide the OTP (one time password) delivered via SMS is a common
way to confirm a user&#39;s phone number. There are a few use cases for SMS OTP:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Two-factor authentication.&lt;/strong&gt; In addition to username and password, SMS OTP can be
used as a strong signal that the account is owned by the person who received the
SMS OTP.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Phone number verification.&lt;/strong&gt; Some services use a phone number as the user&#39;s
primary identifier. In such services, users can enter their phone number and the
OTP received via SMS to prove their identity. Sometimes it&#39;s combined with a PIN
to constitute a two-factor authentication.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Account recovery.&lt;/strong&gt; When a user loses access to their account, there needs
to be a way to recover it. Sending an email to their registered email address or
an SMS OTP to their phone number are common account recovery methods.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Payment confirmation&lt;/strong&gt; In payment systems, some banks or credit card
issuers request additional authentication from the payer for security reasons.
SMS OTP is commonly used for that purpose.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This post explains best practices to build an SMS OTP form for the above use
cases.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; While this post discusses SMS OTP form best practices, be aware that SMS OTP is not the most secure method of authentication by itself because phone numbers can be recycled and sometimes hijacked. And &lt;a href=&quot;https://youtu.be/kGGMgEfSzMw?t=1133&quot;&gt;the concept of OTP itself is not phishing resistant&lt;/a&gt;.  If you are looking for better security, consider using &lt;a href=&quot;https://www.w3.org/TR/webauthn-2/&quot;&gt;WebAuthn&lt;/a&gt;. Learn more about it from the talk &amp;quot;&lt;a href=&quot;https://goo.gle/webauthn-video&quot;&gt;What&#39;s new in sign-up &amp;amp; sign-in&lt;/a&gt;&amp;quot; at the Chrome Dev Summit 2019 and build a reauthentication experience using a biometric sensor with &amp;quot;&lt;a href=&quot;https://goo.gle/WebAuthnReauthCodelab&quot;&gt;Build your first WebAuthn app&lt;/a&gt;&amp;quot; codelab. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;checklist&quot;&gt;Checklist &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/sms-otp-form/#checklist&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To provide the best user experience with the SMS OTP, follow these steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element with:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;type=&amp;quot;text&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inputmode=&amp;quot;numeric&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;autocomplete=&amp;quot;one-time-code&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;@BOUND_DOMAIN #OTP_CODE&lt;/code&gt; as the last line of the OTP SMS message.&lt;/li&gt;
&lt;li&gt;Use the &lt;a href=&quot;https://web.dev/web-otp/&quot;&gt;WebOTP API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;use-the-lessinputgreater-element&quot;&gt;Use the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/sms-otp-form/#use-the-lessinputgreater-element&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using a form with an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; element is the most important best practice you
can follow because it works in all browsers. Even if other suggestions from
this post don&#39;t work in some browser, the user will still be able to enter and submit the OTP
manually.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;form&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/verify-otp&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;POST&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;input&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token attr-name&quot;&gt;inputmode&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;numeric&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token attr-name&quot;&gt;autocomplete&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;one-time-code&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token attr-name&quot;&gt;pattern&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;\d{6}&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token attr-name&quot;&gt;required&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The following are a few ideas to ensure an input field gets the best out of
browser functionality.&lt;/p&gt;
&lt;h3 id=&quot;type=text&quot;&gt;&lt;code&gt;type=&amp;quot;text&amp;quot;&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/sms-otp-form/#type=text&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Since OTPs are usually five or six digit numbers, using
&lt;code&gt;type=&amp;quot;number&amp;quot;&lt;/code&gt; for an input field might seem intuitive because it changes the mobile
keyboard to numbers only. This is not recommended because the browser expects an
input field to be a countable number rather than a sequence of multiple numbers,
which can cause unexpected behavior. Using &lt;code&gt;type=&amp;quot;number&amp;quot;&lt;/code&gt; causes up and down
buttons to be displayed beside the input field; pressing these buttons
increments or decrements the number and may remove preceding zeros.&lt;/p&gt;
&lt;p&gt;Use &lt;code&gt;type=&amp;quot;text&amp;quot;&lt;/code&gt; instead. This won&#39;t turn the mobile keyboard into numbers
only, but that is fine because the next tip for using &lt;code&gt;inputmode=&amp;quot;numeric&amp;quot;&lt;/code&gt; does
that job.&lt;/p&gt;
&lt;h3 id=&quot;inputmode=numeric&quot;&gt;&lt;code&gt;inputmode=&amp;quot;numeric&amp;quot;&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/sms-otp-form/#inputmode=numeric&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Use &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Global_attributes/inputmode&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;inputmode=&amp;quot;numeric&amp;quot;&lt;/code&gt;&lt;/a&gt;
to change the mobile keyboard to numbers only.&lt;/p&gt;
&lt;p&gt;Some websites use &lt;code&gt;type=&amp;quot;tel&amp;quot;&lt;/code&gt; for OTP input fields since it also
turns the mobile keyboard to numbers only (including &lt;code&gt;*&lt;/code&gt; and &lt;code&gt;#&lt;/code&gt;) when
focused. This hack was used in the past when &lt;code&gt;inputmode=&amp;quot;numeric&amp;quot;&lt;/code&gt;
wasn&#39;t widely supported. Since &lt;a href=&quot;https://github.com/mdn/browser-compat-data/pull/6782&quot; rel=&quot;noopener&quot;&gt;Firefox started supporting
&lt;code&gt;inputmode=&amp;quot;numeric&amp;quot;&lt;/code&gt;&lt;/a&gt;,
there&#39;s no need to use the semantically incorrect &lt;code&gt;type=&amp;quot;tel&amp;quot;&lt;/code&gt; hack.&lt;/p&gt;
&lt;h3 id=&quot;autocomplete=one-time-code&quot;&gt;&lt;code&gt;autocomplete=&amp;quot;one-time-code&amp;quot;&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/sms-otp-form/#autocomplete=one-time-code&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Attributes/autocomplete&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;autocomplete&lt;/code&gt;&lt;/a&gt;
attribute lets developers specify what permission the browser
has to provide autocomplete assistance and informs the browser about the
type of information expected in the field.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;autocomplete=&amp;quot;one-time-code&amp;quot;&lt;/code&gt; whenever a user receives an SMS message while a
form is open, the operating system will parse the OTP in the SMS heuristically and
the keyboard will suggest the OTP for the user to enter. It works only on Safari 12 and
later on iOS, iPadOS, and macOS, but we strongly recommend using it, because it is an
easy way to improve the SMS OTP experience on those platforms.&lt;/p&gt;
&lt;figure style=&quot;width:300px; margin:auto;&quot;&gt;
  &lt;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/sms-otp-form/ios-safari.webm&quot; type=&quot;video/webm&quot; /&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/sms-otp-form/ios-safari.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    `autocomplete=&quot;one-time-code&quot;` in action.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;autocomplete=&amp;quot;one-time-code&amp;quot;&lt;/code&gt; improves the user experience, but there&#39;s more you
can do by &lt;a href=&quot;https://web.dev/sms-otp-form/#format&quot;&gt;ensuring that the SMS message complies with the origin-bound message
format&lt;/a&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Optional attributes:  * &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Attributes/pattern&quot;&gt;&lt;code&gt;pattern&lt;/code&gt;&lt;/a&gt; specifies the format that the entered OTP must match. Use regular expressions to specify the matching pattern, for example, &lt;code&gt;\d{6}&lt;/code&gt; constrains the OTP to a six digit string. Learn more about the &lt;code&gt;pattern&lt;/code&gt; attribute in &lt;a href=&quot;https://web.dev/learn/forms/javascript/#ensure-users-are-notified-about-errors-in-real-time&quot;&gt;Use JavaScript for more complex real-time validation&lt;/a&gt;  * &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Attributes/required&quot;&gt;&lt;code&gt;required&lt;/code&gt;&lt;/a&gt; indicates that a field is required.  For more general form best practices, &lt;a href=&quot;https://web.dev/authors/samdutton/&quot;&gt;Sam Dutton&lt;/a&gt;&#39;s &lt;a href=&quot;https://web.dev/sign-in-form-best-practices/&quot;&gt;Sign-in form best practices&lt;/a&gt; is a great starting point. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;format&quot;&gt;Format the SMS text &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/sms-otp-form/#format&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Enhance the user experience of entering an OTP by aligning with
&lt;a href=&quot;https://wicg.github.io/sms-one-time-codes/&quot; rel=&quot;noopener&quot;&gt;the origin-bound one-time codes delivered via SMS&lt;/a&gt;
specification.&lt;/p&gt;
&lt;p&gt;The format rule is simple: Finish the SMS message with the receiver domain
preceded with &lt;code&gt;@&lt;/code&gt; and the OTP preceded with &lt;code&gt;#&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Your OTP is 123456&lt;br /&gt;&lt;br /&gt;@web-otp.glitch.me #123456&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Using a standard format for OTP messages makes extraction
of codes from them easier and more reliable. Associating OTP codes with
websites makes it harder to trick users into providing a code to malicious sites.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The precise rules are: * The message begins with (optional) human-readable text that contains a four to ten character alphanumeric string with at least one number, leaving the last line for the URL and the OTP. * The domain part of the URL of the website that invoked the API must be preceded by &lt;code&gt;@&lt;/code&gt;. * The URL must contain a pound sign (&amp;quot;&lt;code&gt;#&lt;/code&gt;&amp;quot;) followed by the OTP.  Make sure the number of characters doesn&#39;t exceed 140 in total.  To learn more about Chrome specific rules, read &lt;a href=&quot;https://web.dev/web-otp/#format&quot;&gt;Format the SMS message section of WebOTP API post&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Using this format provides a couple of benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The OTP will be bound to the domain. If the user is on domains other than
the one specified in the SMS message, the OTP suggestion won&#39;t appear.
This also mitigates the risk of phishing attacks and potential account hijacks.&lt;/li&gt;
&lt;li&gt;Browser will now be able to reliably extract the OTP without depending on
mysterious and flaky heuristics.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a website uses &lt;code&gt;autocomplete=&amp;quot;one-time-code&amp;quot;&lt;/code&gt;, Safari with iOS 14 or later
will suggest the OTP following the above rules.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; If the user is on a desktop with macOS Big Sur with the same iCloud account set up as on iOS, the OTP received on the iOS device will be available on the desktop Safari as well.  To learn more about other benefits and nuances of the availability on Apple platforms, read &lt;a href=&quot;https://developer.apple.com/news/?id=z0i801mg&quot;&gt;Enhance SMS-delivered code security with domain-bound codes&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;This SMS message format also benefits browsers other than Safari. Chrome, Opera,
and Vivaldi on Android also support the origin-bound one-time codes rule with
the WebOTP API, though not through &lt;code&gt;autocomplete=&amp;quot;one-time-code&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;use-the-webotp-api&quot;&gt;Use the WebOTP API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/sms-otp-form/#use-the-webotp-api&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://wicg.github.io/web-otp/&quot; rel=&quot;noopener&quot;&gt;The WebOTP API&lt;/a&gt; provides access to the OTP
received in an SMS message. By calling
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.get()&lt;/code&gt;&lt;/a&gt;
with &lt;code&gt;otp&lt;/code&gt; type (&lt;code&gt;OTPCredential&lt;/code&gt;) where &lt;code&gt;transport&lt;/code&gt; includes &lt;code&gt;sms&lt;/code&gt;, the website
will wait for an SMS that complies with the origin-bound one-time codes to be
delivered and granted access by the user. Once the OTP is passed to JavaScript,
the website can use it in a form or POST it directly to the server.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; The WebOTP API requires a secure origin (HTTPS). &lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;otp&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;transport&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sms&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;otp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; otp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;figure style=&quot;width:300px; margin:auto;&quot;&gt;
  &lt;video controls=&quot;&quot; autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/sms-otp-form/android-chrome.webm&quot; type=&quot;video/webm&quot; /&gt;
    &lt;source src=&quot;https://storage.googleapis.com/web-dev-assets/sms-otp-form/android-chrome.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
  &lt;figcaption&gt;
    WebOTP API in action.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Learn how to use the WebOTP API in detail in &lt;a href=&quot;https://web.dev/web-otp/&quot;&gt;Verify phone numbers on the web
with the WebOTP API&lt;/a&gt; or copy and paste the following snippet. (Make
sure the &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; element has an &lt;code&gt;action&lt;/code&gt; and &lt;code&gt;method&lt;/code&gt; attribute properly set.)&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Feature detection&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;OTPCredential&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;DOMContentLoaded&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; input &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;input[autocomplete=&quot;one-time-code&quot;]&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Cancel the WebOTP API if the form is submitted manually.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ac &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AbortController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; form &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;closest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;form&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;submit&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Cancel the WebOTP API.&lt;/span&gt;&lt;br /&gt;        ac&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;abort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Invoke the WebOTP API&lt;/span&gt;&lt;br /&gt;    navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;otp&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;transport&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;sms&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ac&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signal&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;otp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      input&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; otp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;code&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Automatically submit the form when an OTP is obtained.&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;form&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; form&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;submit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;err&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/mZNRsYE9Qi4&quot; rel=&quot;noopener&quot;&gt;Jason Leung&lt;/a&gt; on
&lt;a href=&quot;https://unsplash.com/&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Help users change passwords easily by adding a well-known URL for changing passwords</title>
    <link href="https://web.dev/change-password-url/"/>
    <updated>2020-09-01T00:00:00Z</updated>
    <id>https://web.dev/change-password-url/</id>
    <content type="html" mode="escaped">&lt;p&gt;Set a redirect from &lt;code&gt;/.well-known/change-password&lt;/code&gt; to the change password page
of your website. This will enable password managers to navigate your users
directly to that page.&lt;/p&gt;
&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As you may know, &lt;a href=&quot;https://security.googleblog.com/2017/11/new-research-understanding-root-cause.html&quot; rel=&quot;noopener&quot;&gt;passwords are not the best way to manage
accounts&lt;/a&gt;.
Luckily, there are emerging technologies such as
&lt;a href=&quot;https://webauthn.io/&quot; rel=&quot;noopener&quot;&gt;WebAuthn&lt;/a&gt; and techniques such as one-time passwords that
are helping us get closer to a world without passwords. However, these
technologies are still being developed and things won&#39;t change rapidly. Many
developers will still need to deal with passwords for at least the next few
years. While we wait for the emerging technologies and techniques to become
commonplace, we can at least make passwords easier to use.&lt;/p&gt;
&lt;p&gt;A good way to do this is to provide better support for password managers.&lt;/p&gt;
&lt;h3 id=&quot;how-password-managers-help&quot;&gt;How password managers help &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#how-password-managers-help&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Password managers can be built into browsers or provided as third-party apps.
They can help users in various ways:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Autofill the password for the correct input field&lt;/strong&gt;: Some browsers can find
the correct input heuristically even if the website is not optimized for this
purpose. Web developers can help password managers by correctly &lt;a href=&quot;https://web.dev/sign-in-form-best-practices/#new-password&quot;&gt;annotating HTML
input tags&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prevent phishing&lt;/strong&gt;: Because password managers remember where the password was
recorded, the password can be autofilled only at appropriate URLs, and not at
phishing websites.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generate strong and unique passwords&lt;/strong&gt;: Because strong and unique passwords
are directly generated and stored by the password manager, users don&#39;t have to
remember a single character of the password.&lt;/p&gt;
&lt;p&gt;Generating and autofilling passwords using a password manager have already
served the web well, but considering their lifecycle, updating the passwords
whenever it&#39;s required is as important as generating and autofilling. To
properly leverage that, password managers are adding a new feature:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Detect vulnerable passwords and suggest updating them&lt;/strong&gt;: Password managers can
detect passwords that are reused, analyze the entropy and weakness of them, and
even detect potentially leaked passwords or ones that are known to be unsafe
from sources such as &lt;a href=&quot;https://haveibeenpwned.com/&quot; rel=&quot;noopener&quot;&gt;Have I Been Pwned&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A password manager can warn users about problematic passwords, but there&#39;s a lot
of friction in asking users to navigate from the homepage to a change password
page, on top of going through the actual process of changing the password (which
varies from site to site). It would be much easier if password managers could
navigate the user directly to the change-password URL. This is where &lt;a href=&quot;https://w3c.github.io/webappsec-change-password-url/&quot; rel=&quot;noopener&quot;&gt;a
well-known URL for changing
passwords&lt;/a&gt; becomes useful.&lt;/p&gt;
&lt;p&gt;By reserving a well-known URL path that redirects the user to the change
password page, the website can easily redirect users to the right place to
change their passwords.&lt;/p&gt;
&lt;h2 id=&quot;set-up-a-well-known-url-for-changing-passwords&quot;&gt;Set up &amp;quot;a well-known URL for changing passwords&amp;quot; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#set-up-a-well-known-url-for-changing-passwords&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;.well-known/change-password&lt;/code&gt; is proposed as &lt;a href=&quot;https://wicg.github.io/change-password-url/&quot; rel=&quot;noopener&quot;&gt;a well-known URL for changing
passwords&lt;/a&gt;. All you have to do is
to configure your server to redirect requests for &lt;code&gt;.well-known/change-password&lt;/code&gt;
to the change password URL of your website.&lt;/p&gt;
&lt;p&gt;For example, let&#39;s say your website is &lt;code&gt;https://example.com&lt;/code&gt; and the change
password URL is &lt;code&gt;https://example.com/settings/password&lt;/code&gt;. You&#39;ll just need to set
your server to redirect a request for
&lt;code&gt;https://example.com/.well-known/change-password&lt;/code&gt; to
&lt;code&gt;https://example.com/settings/password&lt;/code&gt;. That&#39;s it. For the redirection, &lt;a href=&quot;https://wicg.github.io/change-password-url/#semantics&quot; rel=&quot;noopener&quot;&gt;use
the HTTP status code&lt;/a&gt;
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Status/302&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;302 Found&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Status/303&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;303 See Other&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Status/307&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;307 Temporary Redirect&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Alternatively you can serve HTML at your &lt;code&gt;.well-known/change-password&lt;/code&gt; URL with
a &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt; tag using an
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Element/meta#attr-http-equiv&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;http-equiv=&amp;quot;refresh&amp;quot;&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;refresh&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;0;url=https://example.com/settings/password&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;revisit-your-change-password-page-html&quot;&gt;Revisit your change password page HTML &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#revisit-your-change-password-page-html&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The goal of this feature is to help the user&#39;s password lifecycle be more fluid.
You can do two things to empower the user to update their password without
friction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If your change-password form needs the current password, add
&lt;code&gt;autocomplete=&amp;quot;current-password&amp;quot;&lt;/code&gt; to the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; tag to help the password
manager autofill it.&lt;/li&gt;
&lt;li&gt;For the new password field (in many cases it&#39;s two fields to ensure that the
user has entered the new password correctly), add
&lt;code&gt;autocomplete=&amp;quot;new-password&amp;quot;&lt;/code&gt; to the &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; tag to help the password
manager suggest a generated password.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Learn more at &lt;a href=&quot;https://web.dev/sign-in-form-best-practices/#new-password&quot;&gt;Sign-in form best
practices&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-it-is-used-in-real-world&quot;&gt;How it is used in real world &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#how-it-is-used-in-real-world&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;examples&quot;&gt;Examples &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#examples&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Thanks to Apple Safari&#39;s
&lt;a href=&quot;https://developer.apple.com/documentation/safari-release-notes/safari-13-release-notes&quot; rel=&quot;noopener&quot;&gt;implementation&lt;/a&gt;,
&lt;code&gt;/.well-known/change-password&lt;/code&gt;, has already been available on some major
websites for a while:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://accounts.google.com/.well-known/change-password&quot; rel=&quot;noopener&quot;&gt;Google&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/.well-known/change-password&quot; rel=&quot;noopener&quot;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.facebook.com/.well-known/change-password&quot; rel=&quot;noopener&quot;&gt;Facebook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://twitter.com/.well-known/change-password&quot; rel=&quot;noopener&quot;&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wordpress.com/.well-known/change-password&quot; rel=&quot;noopener&quot;&gt;WordPress&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Try them yourself and do the same for yours!&lt;/p&gt;
&lt;h3 id=&quot;browser-compatibility&quot;&gt;Browser compatibility &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#browser-compatibility&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A well-known URL for changing passwords has been &lt;a href=&quot;https://webkit.org/blog/9170/safari-technology-preview-84-with-safari-13-features-is-now-available/&quot; rel=&quot;noopener&quot;&gt;supported in Safari since
2019&lt;/a&gt;.
Chrome&#39;s password manager is starting to support it from version 86 onwards
(which is scheduled for Stable release in late October 2020)
and other Chromium-based browsers may follow. &lt;a href=&quot;https://mozilla.github.io/standards-positions/#change-password-url&quot; rel=&quot;noopener&quot;&gt;Firefox considers it worth
implementing&lt;/a&gt;,
but has not signalled that it plans to do so as of August 2020.&lt;/p&gt;
&lt;h3 id=&quot;chromes-password-manager-behavior&quot;&gt;Chrome&#39;s password manager behavior &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#chromes-password-manager-behavior&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&#39;s have a look at how Chrome&#39;s password manager treats vulnerable passwords.&lt;/p&gt;
&lt;p&gt;Chrome&#39;s password manager is able to check for leaked passwords. By navigating
to &lt;code&gt;about://settings/passwords&lt;/code&gt; users can run &lt;strong&gt;Check passwords&lt;/strong&gt; against stored
passwords, and see a list of passwords that are recommended for update.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;&quot; decoding=&quot;async&quot; height=&quot;845&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/2qTEnaWJhxDcvX6hfgrY.png?auto=format&amp;w=1600 1600w&quot; width=&quot;1478&quot; /&gt;
  &lt;figcaption&gt;
    Chrome&#39;s &lt;b&gt;Check passwords&lt;/b&gt; functionality
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;By clicking the &lt;b&gt;Change password&lt;/b&gt; button next to a password that is recommended to
be updated, the browser will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open the website&#39;s change password page if &lt;code&gt;/.well-known/change-password&lt;/code&gt; is
set up correctly.&lt;/li&gt;
&lt;li&gt;Open the website&#39;s homepage if &lt;code&gt;/.well-known/change-password&lt;/code&gt; is not set up
and Google doesn&#39;t know the fallback.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;
&lt;summary&gt;
  What if the server returns &lt;code&gt;200 OK&lt;/code&gt; even &lt;code&gt;/.well-known/change-password&lt;/code&gt; doesn&#39;t exist?
&lt;/summary&gt;
&lt;p&gt;Password managers try to determine if a website supports a well-known URL for
changing passwords by sending a request to &lt;code&gt;/.well-known/change-password&lt;/code&gt; before
actually forwarding a user to this URL. If the request returns &lt;code&gt;404 Not Found&lt;/code&gt;
it is obvious that the URL is not available, but a &lt;code&gt;200 OK&lt;/code&gt; response doesn&#39;t
necessarily mean that the URL is available, because there are a few edge cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A server-side-rendering website displays &amp;quot;Not found&amp;quot; when there is no content
but with &lt;code&gt;200 OK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A server-side-rendering website responds with &lt;code&gt;200 OK&lt;/code&gt; when there is no
content after redirecting to the &amp;quot;Not found&amp;quot; page.&lt;/li&gt;
&lt;li&gt;A single page app responds with the shell with &lt;code&gt;200 OK&lt;/code&gt; and renders the &amp;quot;Not
found&amp;quot; page on the client side when there is no content.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For these edge cases users will be forwarded to a &amp;quot;Not Found&amp;quot; page and that will
be a source of confusion.&lt;/p&gt;
&lt;p&gt;That&#39;s why there&#39;s &lt;a href=&quot;https://wicg.github.io/change-password-url/response-code-reliability.html&quot; rel=&quot;noopener&quot;&gt;a proposed standard
mechanism&lt;/a&gt;
to determine whether the server is configured to respond with &lt;code&gt;404 Not Found&lt;/code&gt;
when there is genuinely no content, by requesting a random page. Actually, the
URL is also reserved:
&lt;code&gt;/.well-known/resource-that-should-not-exist-whose-status-code-should-not-be-200&lt;/code&gt;.
Chrome for example uses this URL path to determine whether it can expect a
proper change password URL from &lt;code&gt;/.well-known/change-password&lt;/code&gt; in advance.&lt;/p&gt;
&lt;p&gt;When you are deploying &lt;code&gt;/.well-known/change-password&lt;/code&gt;, make sure that your
server returns &lt;code&gt;404 Not Found&lt;/code&gt; for any non-existing contents.&lt;/p&gt;
&lt;/details&gt;
&lt;h2 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you have any feedback on the specification, please file an issue to &lt;a href=&quot;https://github.com/wicg/change-password-url/issues&quot; rel=&quot;noopener&quot;&gt;the spec
repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/change-password-url/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://wicg.github.io/change-password-url/&quot; rel=&quot;noopener&quot;&gt;A Well-Known URL for Changing
Passwords&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wicg.github.io/change-password-url/response-code-reliability.html&quot; rel=&quot;noopener&quot;&gt;Detecting the reliability of HTTP status
codes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/sign-in-form-best-practices/&quot;&gt;Sign-in form best practices&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Photo by &lt;a href=&quot;https://unsplash.com/photos/zEFyM4sulJ8&quot; rel=&quot;noopener&quot;&gt;Matthew Brodeur&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/&quot; rel=&quot;noopener&quot;&gt;Unsplash&lt;/a&gt;&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Handling optional payment information with a service worker</title>
    <link href="https://web.dev/handling-optional-payment-information/"/>
    <updated>2020-08-31T00:00:00Z</updated>
    <id>https://web.dev/handling-optional-payment-information/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  Shipping and address support in &lt;a href=&quot;https://github.com/w3c/payment-request/pull/955&quot;&gt;the Payment Request API was once removed from the specification&lt;/a&gt; and from Chrome, but is &lt;a href=&quot;https://github.com/w3c/payment-request/pull/996&quot;&gt;being reverted&lt;/a&gt; in the spec. Thus, we&#39;ve reverted the documentation about shipping and address as well.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Once &lt;a href=&quot;https://web.dev/orchestrating-payment-transactions&quot;&gt;a web-based payment app receives a payment request and initiates a payment
transaction&lt;/a&gt;, the service worker will act
as the hub for communication between the merchant and the payment app. This post
explains how a payment app can pass information about the payment method,
shipping address, or contact information to the merchant using a service worker.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Handling optional payment information with a service worker&quot; class=&quot;w-screenshot&quot; decoding=&quot;async&quot; height=&quot;2335&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kDteyNFNEVnJQyTPw5p8.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Handling optional payment information with a service worker
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;payment-method-changes&quot;&gt;Inform the merchant of a payment method change &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/handling-optional-payment-information/#payment-method-changes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Payment apps can support multiple payment instruments with different payment methods.&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Customer&lt;/th&gt;
        &lt;th&gt;Payment Method&lt;/th&gt;
        &lt;th&gt;Payment Instrument&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td rowspan=&quot;3&quot;&gt;A&lt;/td&gt;
        &lt;td&gt;Credit Card Issuer 1&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;****1234&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Credit Card Issuer 1&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;****4242&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Bank X&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;******123&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td rowspan=&quot;2&quot;&gt;B&lt;/td&gt;
        &lt;td&gt;Credit Card Issuer 2&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;****5678&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Bank X&lt;/td&gt;
        &lt;td&gt;&lt;code&gt;******456&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;For example, in the above table, Customer A&#39;s web-based wallet has two credit
cards and one bank account registered. In this case, the app is handling three
payment instruments (&lt;code&gt;****1234&lt;/code&gt;, &lt;code&gt;****4242&lt;/code&gt;, &lt;code&gt;******123&lt;/code&gt;) and two payment
methods (Credit Card Issuer 1 and Bank X). On a payment transaction, the payment
app can let the customer pick one of the payment instruments and use it to pay
for the merchant.&lt;/p&gt;
&lt;figure style=&quot;width:300px; margin:auto;&quot;&gt;
  &lt;img alt=&quot;Payment method picker UI&quot; decoding=&quot;async&quot; height=&quot;1600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/yZYmEL3y1e2cPaLNz34K.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Payment method picker UI
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The payment app can let the merchant know which payment method the customer
picked before sending the full payment response. This is useful when the
merchant wants to run a discount campaign for a specific payment method brand,
for example.&lt;/p&gt;
&lt;p&gt;With the Payment Handler API, the payment app can send a &amp;quot;payment method change&amp;quot;
event to the merchant via a service worker to notify the new payment method
identifier. The service worker should invoke
&lt;code&gt;PaymentRequestEvent.changePaymentMethod()&lt;/code&gt; with the new payment method
information.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Inform the merchant of a payment method change&quot; decoding=&quot;async&quot; height=&quot;659&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/ogXzkcdinU3RNC9cMzN0.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Inform the merchant of a payment method change
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Payment apps can pass a &lt;code&gt;methodDetails&lt;/code&gt; object as the optional second argument
for &lt;code&gt;PaymentRequestEvent.changePaymentMethod()&lt;/code&gt;. This object can contain
arbitrary payment method details required for the merchant to process the change
event.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Sharing detailed information about a customer with the merchant before the transaction is finalized is potentially a privacy risk. As a best practice, payment apps should omit unnecessary details as much as possible. &lt;/div&gt;&lt;/aside&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Received a message from the frontend&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      …&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;PAYMENT_METHOD_CHANGED&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;paymentMethod&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newDetails &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;methodDetails&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Redact or check that no sensitive information is passed in&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// `newDetails`.&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Notify the merchant of the payment method change&lt;/span&gt;&lt;br /&gt;        details &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changePaymentMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; newDetails&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      …&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the merchant receives a &lt;code&gt;paymentmethodchange&lt;/code&gt; event from the Payment
Request API, they can update the payment details and respond with a
&lt;a href=&quot;https://w3c.github.io/payment-request/#paymentdetailsupdate-dictionary&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentDetailsUpdate&lt;/code&gt;&lt;/a&gt;
object.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [merchant] &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;paymentmethodchange&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;methodName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;another-pay&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Apply $10 discount for example.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; discount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;special discount&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// The value being string complies the spec&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;-10.00&#39;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; total &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    details&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;displayItems&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;discount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;displayItems&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;     total &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Convert the number back to string&lt;/span&gt;&lt;br /&gt;    details&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;total&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;amount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; total&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Pass a promise to `updateWith()` and send updated payment details&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;details&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the merchant responds, the promise that
&lt;a href=&quot;https://w3c.github.io/payment-handler/#dom-paymentrequestevent-changepaymentmethod&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestEvent.changePaymentMethod()&lt;/code&gt;&lt;/a&gt;
returned will resolve with a
&lt;a href=&quot;https://w3c.github.io/payment-handler/#the-paymentrequestdetailsupdate&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestDetailsUpdate&lt;/code&gt;&lt;/a&gt;
object.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Notify the merchant of the payment method change&lt;/span&gt;&lt;br /&gt;        details &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changePaymentMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; newDetails&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Provided the new payment details,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// send a message back to the frontend to update the UI&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;UPDATE_REQUEST&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Use the object to update the UI on the frontend. See &lt;a href=&quot;https://web.dev/handling-optional-payment-information/#reflect-the-updated-payment-details&quot;&gt;Reflect the updated
payment details&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;shipping-address-changes&quot;&gt;Inform the merchant of a shipping address change &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/handling-optional-payment-information/#shipping-address-changes&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Payment apps can provide a customer&#39;s shipping address to the merchant as part
of a payment transaction.&lt;/p&gt;
&lt;p&gt;This is useful for merchants because they can delegate the address collection to
payment apps. And, because the address data will be provided in &lt;a href=&quot;https://w3c.github.io/payment-request/#dom-addressinit&quot; rel=&quot;noopener&quot;&gt;the standard
data format&lt;/a&gt;, the
merchant can expect to receive shipping addresses in consistent structure.&lt;/p&gt;
&lt;p&gt;Additionally, customers can register their address information with their
preferred payment app and reuse it for different merchants.&lt;/p&gt;
&lt;figure class=&quot;w-figure&quot; style=&quot;width:300px; margin:auto;&quot;&gt;
  &lt;img alt=&quot;Shipping address picker UI&quot; class=&quot;w-screenshot&quot; decoding=&quot;async&quot; height=&quot;1600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/0ytdyaEC7tkPkBTv5rIu.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption class=&quot;w-figcaption&quot;&gt;
    Shipping address picker UI
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Payment apps can provide a UI to edit a shipping address or to select
pre-registered address information for the customer on a payment transaction.
When a shipping address is determined temporarily, the payment app can let the
merchant know of the redacted address information. This provides merchants with
multiple benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A merchant can determine whether the customer meets the regional restriction
to ship the item (for example, domestic only).&lt;/li&gt;
&lt;li&gt;A merchant can change the list of shipping options based on the region of the
shipping address (For example, international regular or express).&lt;/li&gt;
&lt;li&gt;A merchant can apply the new shipping cost based on the address and update the
total price.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the Payment Handler API, the payment app can send a &amp;quot;shipping address
change&amp;quot; event to the merchant from the service worker to notify the new shipping
address. The service worker should invoke
&lt;a href=&quot;https://w3c.github.io/payment-handler/#dom-paymentrequestevent-changeshippingaddress&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestEvent.changeShippingAddress()&lt;/code&gt;&lt;/a&gt;
with the &lt;a href=&quot;https://www.w3.org/TR/payment-request/#dom-addressinit&quot; rel=&quot;noopener&quot;&gt;new address
object&lt;/a&gt;.&lt;/p&gt;
&lt;figure class=&quot;w-figure&quot;&gt;
  &lt;img alt=&quot;Inform the merchant of a shipping address change&quot; class=&quot;w-screenshot&quot; decoding=&quot;async&quot; height=&quot;675&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/aVv5d9OEcEjH1Z6nUQKb.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption class=&quot;w-figcaption&quot;&gt;
    Inform the merchant of a shipping address change
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Received a message from the frontend&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      …&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;SHIPPING_ADDRESS_CHANGED&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newAddress &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        details &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changeShippingAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      …&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; &lt;strong&gt;Redacted address&lt;/strong&gt;. Informing the full shipping address to the merchant in this case is not necessary and risks customers&#39; privacy. The merchant only receives the parts of the address that they need to determine the shipping cost. Specifically, the browser will clear the &lt;code&gt;organization&lt;/code&gt;, &lt;code&gt;phone&lt;/code&gt;, &lt;code&gt;recipient&lt;/code&gt;, &lt;code&gt;addressLine&lt;/code&gt; fields from the payment app provided address before raising the &lt;code&gt;shippingaddresschange&lt;/code&gt; event in the merchant&#39;s DOM. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The merchant will receive a &lt;code&gt;shippingaddresschange&lt;/code&gt; event from the Payment
Request API so they can respond with the updated &lt;a href=&quot;https://w3c.github.io/payment-request/#paymentdetailsupdate-dictionary&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentDetailsUpdate&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [merchant] &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;shippingaddresschange&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Read the updated shipping address and update the request.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; addr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shippingAddress&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; details &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPaymentDetailsFromShippingAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;addr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// `updateWith()` sends back updated payment details&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;details&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the merchant responds, the promise
&lt;a href=&quot;https://w3c.github.io/payment-handler/#dom-paymentrequestevent-changeshippingaddress&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestEvent.changeShippingAddress()&lt;/code&gt;&lt;/a&gt;
returned will resolve with a
&lt;a href=&quot;https://w3c.github.io/payment-handler/#the-paymentrequestdetailsupdate&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestDetailsUpdate&lt;/code&gt;&lt;/a&gt;
object.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Notify the merchant of the shipping address change&lt;/span&gt;&lt;br /&gt;        details &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changeShippingAddress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newAddress&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Provided the new payment details,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// send a message back to the frontend to update the UI&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;UPDATE_REQUEST&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Use the object to update the UI on the frontend. See &lt;a href=&quot;https://web.dev/handling-optional-payment-information/#reflect-the-updated-payment-details&quot;&gt;Reflect the updated
payment details&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;inform-the-merchant-of-a-shipping-option-change&quot;&gt;Inform the merchant of a shipping option change &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/handling-optional-payment-information/#inform-the-merchant-of-a-shipping-option-change&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Shipping options are delivery methods merchants use to ship purchased items to a customer. Typical shipping options include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Free shipping&lt;/li&gt;
&lt;li&gt;Express shipping&lt;/li&gt;
&lt;li&gt;International shipping&lt;/li&gt;
&lt;li&gt;Premium international shipping&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each comes with its own cost. Usually faster methods/options are more expensive.&lt;/p&gt;
&lt;p&gt;Merchants using the Payment Request API can delegate this selection to a payment
app. The payment app can use the information to construct a UI and let the
customer pick a shipping option.&lt;/p&gt;
&lt;figure class=&quot;w-figure&quot; style=&quot;width:300px; margin:auto;&quot;&gt;
  &lt;img alt=&quot;Shipping option picker UI&quot; class=&quot;w-screenshot&quot; decoding=&quot;async&quot; height=&quot;1600&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/VkHwTharTqX7oFK62RkA.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption class=&quot;w-figcaption&quot;&gt;
    Shipping option picker UI
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The list of shipping options specified in the merchant&#39;s Payment Request API is
propagated to the payment app&#39;s service worker as a property of
&lt;code&gt;PaymentRequestEvent&lt;/code&gt;.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [merchant] &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;supportedMethods&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://bobbucks.dev/pay&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;transactionId&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;****&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;displayItems&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Anvil L/S Crew Neck - Grey M x1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;22.15&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;shippingOptions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;standard&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Standard&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;0.00&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;selected&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;5.00&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Total due&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;22.15&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requestShipping&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The payment app can let the merchant know which shipping option the customer
picked. This is important for both the merchant and the customer because
changing the shipping option changes the total price as well. The merchant needs
to be informed of the latest price for the payment verification later and the
customer also needs to be aware of the change.&lt;/p&gt;
&lt;p&gt;With the Payment Handler API, the payment app can send a &amp;quot;shipping option
change&amp;quot; event to the merchant from the service worker. The service worker should
invoke
&lt;a href=&quot;https://w3c.github.io/payment-handler/#dom-paymentrequestevent-changeshippingoption&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestEvent.changeShippingOption()&lt;/code&gt;&lt;/a&gt;
with the new shipping option ID.&lt;/p&gt;
&lt;figure class=&quot;w-figure&quot;&gt;
  &lt;img alt=&quot;Inform the merchant of a shipping option change&quot; class=&quot;w-screenshot&quot; decoding=&quot;async&quot; height=&quot;667&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/mERzHqvPGrjKWu29m5q1.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption class=&quot;w-figcaption&quot;&gt;
    Inform the merchant of a shipping option change
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Received a message from the frontend&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      …&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;SHIPPING_OPTION_CHANGED&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newOption &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shippingOptionId&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        details &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changeShippingOption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newOption&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      …&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The merchant will receive a &lt;code&gt;shippingoptionchange&lt;/code&gt; event from the Payment
Request API. The merchant should use the information to update the total price
and then respond with the updated
&lt;a href=&quot;https://w3c.github.io/payment-request/#paymentdetailsupdate-dictionary&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentDetailsUpdate&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [merchant] &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;shippingoptionchange&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// selected shipping option&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; shippingOption &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shippingOption&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newTotal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Total due&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;calculateNewTotal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;shippingOption&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// `updateWith()` sends back updated payment details&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; newTotal &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the merchant responds, the promise that
&lt;a href=&quot;https://w3c.github.io/payment-handler/#dom-paymentrequestevent-changeshippingoption&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestEvent.changeShippingOption()&lt;/code&gt;&lt;/a&gt;
returned will resolve with a
&lt;a href=&quot;https://w3c.github.io/payment-handler/#the-paymentrequestdetailsupdate&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestDetailsUpdate&lt;/code&gt;&lt;/a&gt;
object.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Notify the merchant of the shipping option change&lt;/span&gt;&lt;br /&gt;        details &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changeShippingOption&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newOption&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Provided the new payment details,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// send a message back to the frontend to update the UI&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;UPDATE_REQUEST&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Use the object to update the UI on the frontend. See &lt;a href=&quot;https://web.dev/handling-optional-payment-information/#reflect-the-updated-payment-details&quot;&gt;Reflect the updated
payment details&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reflect-the-updated-payment-details&quot;&gt;Reflect the updated payment details &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/handling-optional-payment-information/#reflect-the-updated-payment-details&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once the merchant finishes updating the payment details, the promises returned
from &lt;code&gt;.changePaymentMethod()&lt;/code&gt;, &lt;code&gt;.changeShippingAddress()&lt;/code&gt; and
&lt;code&gt;.changeShippingOption()&lt;/code&gt; will resolve with a common
&lt;a href=&quot;https://w3c.github.io/payment-handler/#the-paymentrequestdetailsupdate&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestDetailsUpdate&lt;/code&gt;&lt;/a&gt;
object. The payment handler can use the result to reflect updated total price
and shipping options to the UI.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The &lt;code&gt;PaymentRequestDetailsUpdate&lt;/code&gt; object is passed from the merchant and it contains the exact information the merchant put in the &lt;code&gt;PaymentDetailsUpdate&lt;/code&gt; object via the Payment Request API. The best way to ensure that merchants give you the information you expect is to provide good developer documentation, or provide a JavaScript library to control the information, or both. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Merchants may return errors for a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The payment method is not acceptable.&lt;/li&gt;
&lt;li&gt;The shipping address is outside of their supported regions.&lt;/li&gt;
&lt;li&gt;The shipping address contains invalid information.&lt;/li&gt;
&lt;li&gt;The shipping option is not selectable for the provided shipping address or
some other reason.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use the following properties to reflect the error status:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;error&lt;/code&gt;&lt;/strong&gt;: Human readable error string. This is the best string to display
to customers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;shippingAddressErrors&lt;/code&gt;&lt;/strong&gt;:
&lt;a href=&quot;https://www.w3.org/TR/payment-request/#dom-addresserrors&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;AddressErrors&lt;/code&gt;&lt;/a&gt;
object that contains in-detail error string per address property. This is
useful if you want to open a form that lets the customer edit their address
and you need to point them directly to the invalid fields.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;paymentMethodErrors&lt;/code&gt;&lt;/strong&gt;: Payment-method-specific error object. You can ask
merchants to provide a structured error, but the Web Payments spec authors
recommend keeping it a simple string.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;sample-code&quot;&gt;Sample code &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/handling-optional-payment-information/#sample-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most of sample codes you saw in this document were excerpts from the following
working sample app:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://paymenthandler-demo.glitch.me/&quot; rel=&quot;noopener&quot;&gt;https://paymenthandler-demo.glitch.me&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service worker &lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 420px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi&quot; loading=&quot;lazy&quot; src=&quot;https://glitch.com/embed/#!/embed/paymenthandler-demo?attributionHidden=true&amp;sidebarCollapsed=true&amp;path=public%2Fservice-worker.js&amp;previewSize=0&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;paymenthandler-demo on Glitch&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] frontend &lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 420px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi&quot; loading=&quot;lazy&quot; src=&quot;https://glitch.com/embed/#!/embed/paymenthandler-demo?attributionHidden=true&amp;sidebarCollapsed=true&amp;path=public%2Fpay.js&amp;previewSize=0&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;paymenthandler-demo on Glitch&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;To try it out:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://paymentrequest-demo.glitch.me/&quot; rel=&quot;noopener&quot;&gt;https://paymentrequest-demo.glitch.me/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Go to the bottom of the page.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Add a payment button&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;https://paymenthandler-demo.glitch.me&lt;/code&gt; to the &lt;strong&gt;Payment Method Identifier&lt;/strong&gt; field.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Pay&lt;/strong&gt; button next to the field.&lt;/li&gt;
&lt;/ol&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Orchestrating payment transactions with a service worker</title>
    <link href="https://web.dev/orchestrating-payment-transactions/"/>
    <updated>2020-08-31T00:00:00Z</updated>
    <id>https://web.dev/orchestrating-payment-transactions/</id>
    <content type="html" mode="escaped">&lt;p&gt;Once &lt;a href=&quot;https://web.dev/registering-a-web-based-payment-app/&quot;&gt;the payment app is registered&lt;/a&gt;, you
are ready to accept payment requests from merchants. This post explains how to
orchestrate a payment transaction from a service worker during runtime (i.e.
when a window is displayed and the user is interacting with it).&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Orchestrating payment transactions with a service worker&quot; decoding=&quot;async&quot; height=&quot;945&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/b0Pz24lmWMepSM6tboa1.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Orchestrating payment transactions with a service worker
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&amp;quot;Runtime payment parameter changes&amp;quot; refer to a set of events that allows the
merchant and payment handler to exchange messages while the user is interacting
with the payment handler. Learn more in &lt;a href=&quot;https://web.dev/handling-optional-payment-information&quot;&gt;Handling optional payment information
with a service worker&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;receive-payment-request-event&quot;&gt;Receive a payment request event from the merchant &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#receive-payment-request-event&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a customer chooses to pay with your web-based payment app and &lt;a href=&quot;https://web.dev/life-of-a-payment-transaction/#&quot;&gt;the merchant
invokes
&lt;code&gt;PaymentRequest.show()&lt;/code&gt;&lt;/a&gt;,
your service worker will receive a &lt;code&gt;paymentrequest&lt;/code&gt; event. Add an event listener
to the service worker to capture the event and prepare for the next action.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; resolver&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// `self` is the global object in service worker&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;paymentrequest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// If there&#39;s an ongoing payment transaction, reject it.&lt;/span&gt;&lt;br /&gt;    resolver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Preserve the event for future use&lt;/span&gt;&lt;br /&gt;  payment_request_event &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Remember that a service worker is a single instance across different tabs and windows in the same browser. Global variables are shared across all tabs and windows. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The preserved &lt;code&gt;PaymentRequestEvent&lt;/code&gt; contains important information about this
transaction:&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Property name&lt;/th&gt;
        &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;topOrigin&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          A string that indicates the origin of the top-level web page (usually the payee merchant). Use this to identify the merchant origin.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;paymentRequestOrigin&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          A string that indicates the origin of the invoker. This can be the same as &lt;code&gt;topOrigin&lt;/code&gt; when the merchant invokes the Payment Request API directly, but may be different if the API is invoked from within an iframe by a third party such as a payment gateway.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;paymentRequestId&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          The &lt;code&gt;id&lt;/code&gt; property of the &lt;code&gt;&lt;a href=&quot;https://w3c.github.io/payment-request/#paymentdetailsinit-dictionary&quot;&gt;PaymentDetailsInit&lt;/a&gt;&lt;/code&gt; provided to the Payment Request API. If the merchant omits, the browser will provide an auto-generated ID.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;methodData&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          The payment-method-specific data provided by the merchant as part of &lt;code&gt;&lt;a href=&quot;https://w3c.github.io/payment-request/#dom-paymentmethoddata&quot;&gt;PaymentMethodData&lt;/a&gt;&lt;/code&gt;.
Use this to determine the payment transaction details.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;total&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          The total amount provided by the merchant as part of &lt;code&gt;&lt;a href=&quot;https://w3c.github.io/payment-request/#dom-paymentdetailsinit&quot;&gt;PaymentDetailsInit&lt;/a&gt;&lt;/code&gt;.
Use this to construct a UI to let the customer know the total amount to pay.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;instrumentKey&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          The instrument key selected by the user. This reflects the &lt;code&gt;&lt;a href=&quot;https://w3c.github.io/payment-handler/#paymentinstruments-interface&quot;&gt;instrumentKey&lt;/a&gt;&lt;/code&gt; you provided in advance. An empty string indicates that the user did not specify any instruments.
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;open-payment-handler-window&quot;&gt;Open the payment handler window to display the web-based payment app frontend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#open-payment-handler-window&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a &lt;code&gt;paymentrequest&lt;/code&gt; event is received, the payment app can open a payment
handler window by calling &lt;code&gt;PaymentRequestEvent.openWindow()&lt;/code&gt;. The payment
handler window will present the customers your payment app&#39;s interface where
they can authenticate, choose shipping address and options, and authorize the
payment. We&#39;ll cover how to write the frontend code in &lt;em&gt;Handling payments on the
payment frontend&lt;/em&gt; (coming soon).&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/kM6NP47k4Xzl4tHWISCm.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    Checkout flow with a web-based payment app.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Pass a preserved promise to &lt;code&gt;PaymentRequestEvent.respondWith()&lt;/code&gt; so that you can
resolve it with a payment result in the future.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;paymentrequest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;…&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Retain a promise for future resolution&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Polyfill for PromiseResolver is provided below.&lt;/span&gt;&lt;br /&gt;  resolver &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PromiseResolver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Pass a promise that resolves when payment is done.&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;respondWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;promise&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Open the checkout page.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Open the window and preserve the client&lt;/span&gt;&lt;br /&gt;    client &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;openWindow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;checkoutURL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Reject if the window fails to open&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Failed to open window&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Reject the promise on failure&lt;/span&gt;&lt;br /&gt;    resolver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You can use a convenient &lt;code&gt;PromiseResolver&lt;/code&gt; polyfill to resolve a promise at
arbitrary timing.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PromiseResolver&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;promise_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resolve_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; resolve&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reject_ &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; reject&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;promise_ &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;resolve_ &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reject_ &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  For security reasons, the frontend page opened in the payment handler window must have valid HTTPS certificates and no &lt;a href=&quot;https://web.dev/what-is-mixed-content/&quot;&gt;mixed content&lt;/a&gt;; otherwise the payment request will be cancelled by Chrome. Learn more at &lt;a href=&quot;https://web.dev/registering-a-web-based-payment-app/#debugging-a-web-based-payment-app&quot;&gt;Debugging a web-based payment app&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;exchange-information&quot;&gt;Exchange information with the frontend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#exchange-information&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The payment app&#39;s service worker can exchange messages with the payment app&#39;s
frontend through &lt;code&gt;ServiceWorkerController.postMessage()&lt;/code&gt;. To receive messages
from the frontend, listen to &lt;code&gt;message&lt;/code&gt; events.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Define a convenient `postMessage()` method&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;postMessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; contents &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;client&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;contents &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;receive-ready-signal&quot;&gt;Receive the ready signal from the frontend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#receive-ready-signal&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once the payment handler window is opened, the service worker should wait for a
ready-state signal from the payment app frontend. The service worker can pass
important information to the frontend when it is ready.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] frontend: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;serviceWorker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;controller&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;WINDOW_IS_READY&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Received a message from the frontend&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// `WINDOW_IS_READY` is a frontend&#39;s ready state signal&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;WINDOW_IS_READY&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; total &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; payment_request_event&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;pass-details&quot;&gt;Pass the transaction details to the frontend &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#pass-details&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now send the payment details back. In this case you&#39;re only sending the total of
the payment request, but you can pass more details if you like.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Pass the payment details to the frontend&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;PAYMENT_IS_READY&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; total &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;label&quot;&gt; [payment handler] frontend: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; total&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;serviceWorker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;PAYMENT_IS_READY&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; total &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Update the UI&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;renderHTML&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;total&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;…&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;return-credentials&quot;&gt;Return the customer&#39;s payment credentials &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#return-credentials&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the customer authorizes the payment, the frontend can send a post message
to the service worker to proceed. You can resolve the promise passed to
&lt;code&gt;PaymentRequestEvent.respondWith()&lt;/code&gt; to send the result back to the merchant.
Pass a
&lt;a href=&quot;https://w3c.github.io/payment-handler/#dom-paymenthandlerresponse&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentHandlerResponse&lt;/code&gt;&lt;/a&gt;
object.&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Property name&lt;/th&gt;
        &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
      &lt;td&gt;&lt;code&gt;methodName&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          The payment method identifier used to make payment.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;details&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
          The payment method specific data that provides necessary information for the merchant to process payment.
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] frontend: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paymentMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; …&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;PAYMENT_AUTHORIZED&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    paymentMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;              &lt;span class=&quot;token comment&quot;&gt;// Payment method identifier&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Received a message from the frontend&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      …&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;PAYMENT_AUTHORIZED&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Resolve the payment request event promise&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// with a payment response object&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token literal-property property&quot;&gt;methodName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;paymentMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token literal-property property&quot;&gt;details&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;put payment credential here&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        resolver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Don&#39;t forget to initialize.&lt;/span&gt;&lt;br /&gt;        payment_request_event &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      …&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;cancel-transaction&quot;&gt;Cancel the payment transaction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#cancel-transaction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To allow the customer to cancel the transaction, the frontend can send a post
message to the service worker to do so. The service worker can then resolve the
promise passed to &lt;code&gt;PaymentRequestEvent.respondWith()&lt;/code&gt; with &lt;code&gt;null&lt;/code&gt; to indicate to
the merchant that the transaction has been cancelled.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] frontend: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;  &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;CANCEL_PAYMENT&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;label&quot;&gt; [payment handler] service-worker.js: &lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;…&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Received a message from the frontend&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      …&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;CANCEL_PAYMENT&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Resolve the payment request event promise&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// with null&lt;/span&gt;&lt;br /&gt;        resolver&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Don&#39;t forget to initialize.&lt;/span&gt;&lt;br /&gt;        payment_request_event &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      …&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;sample-code&quot;&gt;Sample code &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#sample-code&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All sample codes you saw in this document were excerpts from the following
working sample app:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://paymenthandler-demo.glitch.me/&quot; rel=&quot;noopener&quot;&gt;https://paymenthandler-demo.glitch.me&lt;/a&gt;&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] service worker &lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 420px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi&quot; loading=&quot;lazy&quot; src=&quot;https://glitch.com/embed/#!/embed/paymenthandler-demo?attributionHidden=true&amp;sidebarCollapsed=true&amp;path=public%2Fservice-worker.js&amp;previewSize=0&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;paymenthandler-demo on Glitch&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p class=&quot;label&quot;&gt; [payment handler] frontend &lt;/p&gt;
&lt;div class=&quot;glitch-embed-wrap&quot; style=&quot;height: 420px; width: 100%;&quot;&gt;
  &lt;iframe allow=&quot;camera; clipboard-read; clipboard-write; encrypted-media; geolocation; microphone; midi&quot; loading=&quot;lazy&quot; src=&quot;https://glitch.com/embed/#!/embed/paymenthandler-demo?attributionHidden=true&amp;sidebarCollapsed=true&amp;path=public%2Fpay.js&amp;previewSize=0&quot; style=&quot;height: 100%; width: 100%; border: 0;&quot; title=&quot;paymenthandler-demo on Glitch&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;To try it out:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://paymentrequest-demo.glitch.me/&quot; rel=&quot;noopener&quot;&gt;https://paymentrequest-demo.glitch.me/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Go to the bottom of the page.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Add a payment button&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;https://paymenthandler-demo.glitch.me&lt;/code&gt; to the &lt;strong&gt;Payment Method Identifier&lt;/strong&gt; field.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Pay&lt;/strong&gt; button next to the field.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/orchestrating-payment-transactions/#next-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In this article, we learned how to orchestrate a payment transaction from a
service worker. The next step is to learn how to add some more advanced features
to the service worker.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/handling-optional-payment-information&quot;&gt;Handling optional payment information with a service worker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Registering a web-based payment app</title>
    <link href="https://web.dev/registering-a-web-based-payment-app/"/>
    <updated>2020-07-17T00:00:00Z</updated>
    <id>https://web.dev/registering-a-web-based-payment-app/</id>
    <content type="html" mode="escaped">&lt;p&gt;Web-based payment apps are &lt;a href=&quot;https://web.dev/progressive-web-apps/&quot;&gt;Progressive Web Apps
(PWA)&lt;/a&gt; and run on top of &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Service_Worker_API&quot; rel=&quot;noopener&quot;&gt;service
workers&lt;/a&gt;. The
service worker in a payment app plays an important role as it captures payment
requests from a merchant, launches the payment app, and mediates the
communication with the merchant.&lt;/p&gt;
&lt;p&gt;To configure a web-based payment app, you need to register available payment
methods, and a service worker. You can configure your web-based payment app
declaratively with a web app manifest.&lt;/p&gt;
&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web Payments consists of a few different pieces of technologies and the support
status depends on the browser.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Chromium&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Safari&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Firefox&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Android&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Mobile&lt;/td&gt;
      &lt;td&gt;Desktop/Mobile&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Request API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Handler API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;iOS/Android payment app&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; *Safari supports Apple Pay but no third party payment apps. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;configuring-a-payment-app-with-a-web-app-manifest&quot;&gt;Configuring a payment app with a web app manifest &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#configuring-a-payment-app-with-a-web-app-manifest&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To configure your web-based payment app declaratively, &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-3-serve-a-web-app-manifest&quot;&gt;serve a web app
manifest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following properties in the web app manifest are relevant for web-based payment apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;icons&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;serviceworker&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scope&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;use_cache&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Check out &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-3-serve-a-web-app-manifest&quot;&gt;Setting up a payment
method&lt;/a&gt;
to make sure your payment method manifest points to your web app manifest
properly.&lt;/p&gt;
&lt;h3 id=&quot;registering-a-service-worker-just-in-time-jit&quot;&gt;Registering a service worker just-in-time (JIT) &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#registering-a-service-worker-just-in-time-jit&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Service workers are usually registered using JavaScript, but they can also be automatically registered by the browser when the user chooses to pay with a web-based payment app on a merchant website. This is called &lt;em&gt;just-in-time (JIT) registration&lt;/em&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;The JIT registration requires only serving &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-3-serve-a-web-app-manifest&quot;&gt;the web app
manifest&lt;/a&gt;
and no additional coding. If you&#39;ve already configured your web app manifest and
are serving it properly, you should be all set. The browser will handle the
rest.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; While a single payment method identifier can support multiple payment apps, JIT registration happens only when the payment method manifest points to a single payment app. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;debugging-a-web-based-payment-app&quot;&gt;Debugging a web-based payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#debugging-a-web-based-payment-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When developing a web-based payment app frontend, you&#39;ll probably jump between
merchant context and payment app context. The following debugging tips will help
your developing experience on Chrome.&lt;/p&gt;
&lt;h3 id=&quot;developing-on-a-local-server&quot;&gt;Developing on a local server &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#developing-on-a-local-server&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Which server do you use for development? Many developers tend to use localhost
or a company-internal server environment which can be challenging because
powerful features in the browser tend to require a secure environment (HTTPS)
and a valid certificate. The Payment Request API and the Payment Handler API are
no exception and localhosts or company-internal servers usually don&#39;t come with
a valid certificate.&lt;/p&gt;
&lt;p&gt;The good news is some browsers, including Chrome, exempt certificates for
&lt;code&gt;http://localhost&lt;/code&gt; by default. Also in Chrome, you can exempt the certificate
requirement by launching a Chrome instance. For example, to exempt the
requirement from &lt;code&gt;http://*.corp.company.com&lt;/code&gt;, use the following flags:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://chromiumdash.appspot.com/commit/988b56b519836f3d3d94f145ba3554a0c0a7d0a8&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;--ignore-certificate-errors&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chromiumdash.appspot.com/commit/77a7e1a65d14072149ec4420a0ab523586011d8a&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;--unsafely-treat-insecure-origin-as-secure=http://*.corp.company.com&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;/Applications/Google&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt; Chrome.app/Contents/MacOS/Google&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt; Chrome --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;http://*.corp.company.com&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;chrome.exe --ignore-certificate-errors --unsafely-treat-insecure-origin-as-secure&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;http://*.corp.company.com&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Learn more about running Chrome with a runtime flag at &lt;a href=&quot;https://www.chromium.org/developers/how-tos/run-chromium-with-flags&quot; rel=&quot;noopener&quot;&gt;Run Chromium with
flags&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;port-forwarding-a-local-server&quot;&gt;Port forwarding a local server &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#port-forwarding-a-local-server&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can port forward the local web server to an Android device using Chrome&#39;s
DevTools and test how it works from a mobile browser. To learn how to do it,
check out &lt;a href=&quot;https://developer.chrome.com/docs/devtools/remote-debugging/local-server/&quot; rel=&quot;noopener&quot;&gt;Access Local
Servers&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;remote-debugging-a-website-on-android-chrome-from-desktop-devtools&quot;&gt;Remote debugging a website on Android Chrome from desktop DevTools &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#remote-debugging-a-website-on-android-chrome-from-desktop-devtools&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can also debug Android Chrome on desktop DevTools. To learn how to do it,
check out &lt;a href=&quot;https://developer.chrome.com/docs/devtools/remote-debugging/&quot; rel=&quot;noopener&quot;&gt;Get Started with Remote Debugging Android
Devices&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;payment-handler-event-logging&quot;&gt;Payment Handler event logging &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#payment-handler-event-logging&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developers.google.com/web/updates/2019/09/devtools#payments&quot; rel=&quot;noopener&quot;&gt;DevTools can display Payment Handler API
events&lt;/a&gt; for
easier local development. Open DevTools on the merchant context and go to the
&amp;quot;Payment Handler&amp;quot; section under the &lt;strong&gt;Application&lt;/strong&gt; pane. Check &amp;quot;Show events
from other domains&amp;quot; and click the &amp;quot;Record&amp;quot; button to start capturing events sent
to the service worker that handles payments.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;A screenshot of Payment Handler event logging.&quot; decoding=&quot;async&quot; height=&quot;585&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/FixX1Ld3y0Vgb4ZcSBGc.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Payment Handler event logging.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/registering-a-web-based-payment-app/#next-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The next step is to learn how the service worker can orchestrate a payment
transaction at runtime.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/orchestrating-payment-transactions&quot;&gt;Orchestrating payment transactions with a service
worker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Web-based payment apps overview</title>
    <link href="https://web.dev/web-based-payment-apps-overview/"/>
    <updated>2020-07-17T00:00:00Z</updated>
    <id>https://web.dev/web-based-payment-apps-overview/</id>
    <content type="html" mode="escaped">&lt;p&gt;&lt;a href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#what-is-web-payments&quot;&gt;Web Payments&lt;/a&gt;
brings to the web a browser&#39;s built-in interface that allows users to enter
required payment information easier than ever before. The APIs can invoke
web-based payment apps, as well as &lt;a href=&quot;https://web.dev/android-payment-apps-developers-guide/&quot;&gt;Android payment
apps&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web Payments consists of a few different pieces of technologies and the support
status depends on the browser.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Chromium&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Safari&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Firefox&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Android&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Mobile&lt;/td&gt;
      &lt;td&gt;Desktop/Mobile&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Request API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Handler API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;iOS/Android payment app&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; *Safari supports Apple Pay but no third party payment apps. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;benefits-of-web-based-payment-apps&quot;&gt;Benefits of web-based payment apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#benefits-of-web-based-payment-apps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/8T37CEyLisAjwW39dRwB.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    Checkout flow with a web-based payment app.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Payments are made in modals, in the context of the merchant website, which
provides better user experience than typical payment app techniques that use
redirects or pop-ups.&lt;/li&gt;
&lt;li&gt;Web Payments APIs can be integrated into established websites allowing you to
leverage the existing user base.&lt;/li&gt;
&lt;li&gt;Unlike platform-specific apps, web-based payment apps don&#39;t need to be installed in
advance.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-does-a-web-based-payment-app-work&quot;&gt;How does a web-based payment app work? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#how-does-a-web-based-payment-app-work&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web-based payment apps are built using the standard web technologies. Every
web-based payment app must include a service worker.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; A &lt;a href=&quot;https://developer.chrome.com/docs/workbox/service-worker-overview/&quot;&gt;Service worker&lt;/a&gt; is an event-driven script that runs in the background even if the registering website is not open in the browser. Service workers enable websites to work offline and send push notifications, because they can respond to requests with a cache that is stored locally in advance. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;In a web-based payment app, a service worker can act as a mediator for payment
requests by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Opening a modal window and displaying the payment app&#39;s interface.&lt;/li&gt;
&lt;li&gt;Bridging the communication between the payment app and the merchant.&lt;/li&gt;
&lt;li&gt;Getting an authorization from the customer and passing the payment credential
to the merchant.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Learn how a payment app works on a merchant in &lt;a href=&quot;https://web.dev/life-of-a-payment-transaction/&quot;&gt;Life of a payment
transaction&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-merchants-discover-your-payment-app&quot;&gt;How merchants discover your payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#how-merchants-discover-your-payment-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order for a merchant to use your payment app, they need to use the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Payment_Request_API&quot; rel=&quot;noopener&quot;&gt;Payment
Request API&lt;/a&gt; and
specify the payment method you support using the &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-1-provide-the-payment-method-identifier&quot;&gt;payment method
identifier&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have a payment method identifier that is unique to your payment app, you
can set up your own &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-2-serve-the-payment-method-manifest&quot;&gt;payment method
manifest&lt;/a&gt;
and let browsers discover your app.&lt;/p&gt;
&lt;p&gt;Learn how it works and how you can set up a new payment method in &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/&quot;&gt;Setting up a
payment method&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;apis-you-can-use-inside-the-payment-handler-window&quot;&gt;APIs you can use inside the payment handler window &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#apis-you-can-use-inside-the-payment-handler-window&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &amp;quot;payment handler window&amp;quot; is a window in which payment apps are launched. In
Chrome, since it&#39;s a regular Chrome browser window, most web APIs should work as
if used in a top-level document, with only a few exceptions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Resizing the viewport is disabled.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;window.open()&lt;/code&gt; is disabled.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Payment Handler API is only supported in Chrome as of January 2023. However, since Chromium based browsers already have the implementation, some of them may expose the API in the future. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;webauthn-support&quot;&gt;WebAuthn support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#webauthn-support&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/blog/webauthn/&quot; rel=&quot;noopener&quot;&gt;WebAuthn&lt;/a&gt; is an
authentication mechanism based on the public key cryptography. You can let users
sign-in through a biometric verification. WebAuthn is already supported in the
payment handler window on Chrome, and the standard body is looking into creating
an even-tighter connection between Web Payments and WebAuthn.&lt;/p&gt;
&lt;h3 id=&quot;credential-management-api-support&quot;&gt;Credential Management API support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#credential-management-api-support&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/security-credential-management/&quot;&gt;The Credential Management
API&lt;/a&gt;
provides a programmatic interface between the site and the browser for seamless
sign-in across devices. You can let users sign-in to your website automatically
based on the information stored to the browser&#39;s password manager. It&#39;s planned
to be enabled in Chrome, but still &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=1052383&quot; rel=&quot;noopener&quot;&gt;under
development&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;webotp-support&quot;&gt;WebOTP support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#webotp-support&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://web.dev/web-otp/&quot;&gt;The WebOTP API&lt;/a&gt; helps you programmatically obtain an
OTP from an SMS message and verify a phone number for the user more easily. It&#39;s
planned to be enabled in Chrome, but still &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=1051930&quot; rel=&quot;noopener&quot;&gt;under
development&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can check out the list of known issues and features planned to be added to
the payment handler window in the &lt;a href=&quot;https://bugs.chromium.org/u/maxlg@chromium.org/hotlists/Expandable-payment-handler&quot; rel=&quot;noopener&quot;&gt;Chromium bug
tracker&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-based-payment-apps-overview/#next-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To start building a web-based payment app, you have three distinct parts to implement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/registering-a-web-based-payment-app&quot;&gt;Registering a web-based payment app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/orchestrating-payment-transactions&quot;&gt;Orchestrating payment transactions with a service worker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/handling-optional-payment-information&quot;&gt;Handling optional payment information with a service worker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Setting up a payment method</title>
    <link href="https://web.dev/setting-up-a-payment-method/"/>
    <updated>2020-05-25T00:00:00Z</updated>
    <id>https://web.dev/setting-up-a-payment-method/</id>
    <content type="html" mode="escaped">&lt;p&gt;To be used with the Payment Request API, a payment app must be associated with a
payment method identifier. Merchants that want to integrate with a payment app
will use the payment method identifier to indicate that to the browser. This
article discusses how payment app discovery works,  and how to configure your
payment app to be properly discovered and invoked by a browser.&lt;/p&gt;
&lt;p&gt;If you are new to the concept of Web Payments or how a payment transaction works
through payment apps, read the following articles first:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/empowering-payment-apps-with-web-payments&quot;&gt;Empowering payment apps with Web Payments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/life-of-a-payment-transaction&quot;&gt;Life of a payment transaction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web Payments consists of a few different pieces of technologies and the support
status depends on the browser.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Chromium&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Safari&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Firefox&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Android&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Mobile&lt;/td&gt;
      &lt;td&gt;Desktop/Mobile&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Request API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Handler API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;iOS/Android payment app&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; *Safari supports Apple Pay but no third party payment apps. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;how-a-browser-discovers-a-payment-app&quot;&gt;How a browser discovers a payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#how-a-browser-discovers-a-payment-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every payment app needs to provide the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;URL-based payment method identifier&lt;/li&gt;
&lt;li&gt;Payment method manifest (except when the payment method identifier is
provided by a third party)&lt;/li&gt;
&lt;li&gt;Web app manifest&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Diagram: How a browser discovers the payment app from a URL-based payment method identifier&quot; decoding=&quot;async&quot; height=&quot;587&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/kvLIMUysDNEG3IfPxKz6.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The discovery process starts when a merchant initiates a transaction:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The browser sends a request to the &lt;a href=&quot;https://w3c.github.io/payment-method-manifest/&quot; rel=&quot;noopener&quot;&gt;payment method
identifier&lt;/a&gt; URL and fetches
the &lt;a href=&quot;https://w3c.github.io/payment-method-manifest/&quot; rel=&quot;noopener&quot;&gt;payment method
manifest&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The browser determines the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/Manifest&quot; rel=&quot;noopener&quot;&gt;web app
manifest&lt;/a&gt; URL from the
payment method manifest and fetches the web app manifest.&lt;/li&gt;
&lt;li&gt;The browser determines whether to launch the OS payment app or the
web-based payment app from the web app manifest.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The next sections explain in detail how to set up your own payment method so
that browsers can discover it.&lt;/p&gt;
&lt;h2 id=&quot;step-1-provide-the-payment-method-identifier&quot;&gt;Step 1: Provide the payment method identifier &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#step-1-provide-the-payment-method-identifier&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://w3c.github.io/payment-method-id/#dfn-payment-method-identifiers&quot; rel=&quot;noopener&quot;&gt;payment method
identifier&lt;/a&gt;
is a URL-based string. For example, Google Pay&#39;s identifier is
&lt;code&gt;https://google.com/pay&lt;/code&gt;. Payment app developers can pick any URL as a payment
method identifier as long as they have control over it and can serve arbitrary
content. In this article, we&#39;ll use
&lt;a href=&quot;https://bobbucks.dev/pay&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;https://bobbucks.dev/pay&lt;/code&gt;&lt;/a&gt; as the payment method
identifier.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Payment apps can support third party payment methods as well. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;how-merchants-use-the-payment-method-identifier&quot;&gt;How merchants use the payment method identifier &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#how-merchants-use-the-payment-method-identifier&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;PaymentRequest&lt;/code&gt; object is constructed with a list of &lt;a href=&quot;https://www.w3.org/TR/payment-method-id/&quot; rel=&quot;noopener&quot;&gt;payment method
identifiers&lt;/a&gt; that identifies payment
apps a merchant decides to accept. Payment method identifiers are set as a value
for the &lt;code&gt;supportedMethods&lt;/code&gt; property. For example:&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;[merchant] requests payment:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;supportedMethods&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://bobbucks.dev/pay&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;total&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;10&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Redirects are allowed up to three times within the same-site for a payment method identifier in Chrome. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;step-2-serve-the-payment-method-manifest&quot;&gt;Step 2: Serve the payment method manifest &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#step-2-serve-the-payment-method-manifest&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://w3c.github.io/payment-method-manifest/&quot; rel=&quot;noopener&quot;&gt;payment method manifest&lt;/a&gt; is a
JSON file that defines which payment app can use this payment method.&lt;/p&gt;
&lt;h3 id=&quot;provide-the-payment-method-manifest&quot;&gt;Provide the payment method manifest &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#provide-the-payment-method-manifest&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When a merchant initiates a payment transaction, &lt;a href=&quot;https://w3c.github.io/payment-method-manifest/#accessing&quot; rel=&quot;noopener&quot;&gt;the browser sends an HTTP
&lt;code&gt;GET&lt;/code&gt; request to the payment method identifier URL&lt;/a&gt;.
The server responds with the payment method
manifest body.&lt;/p&gt;
&lt;p&gt;A payment method manifest has two fields, &lt;code&gt;default_applications&lt;/code&gt; and
&lt;code&gt;supported_origins&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Property name&lt;/th&gt;
        &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;default_applications&lt;/code&gt; (required)&lt;/td&gt;
        &lt;td&gt;
        An array of URLs that points to web app manifests where the payment
        apps are hosted. (The URL can be a relative). This array is expected
        to reference the development manifest, production manifest, etc.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;supported_origins&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
        An array of URLs that points to origins that may host third-party
        payment apps implementing the same payment method. Note that a payment
        method can be implemented by multiple payment apps.
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
    &lt;caption&gt;Payment method manifest fields&lt;/caption&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;A payment method manifest file should look like this:&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;[payment handler] /payment-manifest.json:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;default_applications&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://bobbucks.dev/manifest.json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;supported_origins&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string&quot;&gt;&quot;https://alicepay.friendsofalice.example&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the browser reads the &lt;code&gt;default_applications&lt;/code&gt; field, it finds a list of
links to &lt;a href=&quot;https://w3c.github.io/manifest/&quot; rel=&quot;noopener&quot;&gt;web app manifests&lt;/a&gt; of supported
payment apps.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Chrome supports a single default payment app per single payment method as of Chrome 83. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;optionally-route-the-browser-to-find-the-payment-method-manifest-in-another-location&quot;&gt;Optionally route the browser to find the payment method manifest in another location &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#optionally-route-the-browser-to-find-the-payment-method-manifest-in-another-location&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The payment method identifier URL can optionally respond with a &lt;code&gt;Link&lt;/code&gt; header
that points to another URL where the browser can fetch the payment method
manifest. This is useful when a payment method manifest is hosted at a different
server or when the payment app is served by a third party.&lt;/p&gt;
&lt;img alt=&quot;How a browser discovers the payment app from a URL-based payment method identifier with redirects&quot; decoding=&quot;async&quot; height=&quot;698&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/5YDqz1ppLkjHd9HYgXYH.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Configure the payment method server to respond with a HTTP &lt;code&gt;Link&lt;/code&gt; header with
the &lt;code&gt;rel=&amp;quot;payment-method-manifest&amp;quot;&lt;/code&gt; attribute and the &lt;a href=&quot;https://w3c.github.io/payment-method-manifest/&quot; rel=&quot;noopener&quot;&gt;payment method
manifest&lt;/a&gt; URL.&lt;/p&gt;
&lt;p&gt;For example, if the manifest is at &lt;code&gt;https://bobbucks.dev/payment-manifest.json&lt;/code&gt;,
the response header would include:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Link&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;&amp;lt;https://bobbucks.dev/payment-manifest.json&gt;; rel=&quot;payment-method-manifest&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The URL can be a fully-qualified domain name or a relative path. Inspect
&lt;code&gt;https://bobbucks.dev/pay/&lt;/code&gt; for network traffic to see an example. You may use a
&lt;code&gt;curl&lt;/code&gt; command as well:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; --include https://bobbucks.dev/pay&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Learn more about &lt;a href=&quot;https://github.com/w3c/payment-request-info/wiki/PaymentMethodPractice&quot;&gt;payment method practices at W3C documentation&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;step-3-serve-a-web-app-manifest&quot;&gt;Step 3: Serve a web app manifest &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#step-3-serve-a-web-app-manifest&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://developer.mozilla.org/docs/Web/Manifest&quot; rel=&quot;noopener&quot;&gt;web app manifest&lt;/a&gt; is
used to define a web app as the name suggests. It&#39;s a widely used manifest file
to &lt;a href=&quot;https://web.dev/add-manifest/&quot;&gt;define a Progressive Web App (PWA)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Typical web app manifest would look like this:&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;[payment handler] /manifest.json:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Pay with Bobpay&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;short_name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Bobpay&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;This is an example of the Payment Handler API.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;icons&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;images/manifest/icon-192x192.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;192x192&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;images/manifest/icon-512x512.png&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;512x512&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;serviceworker&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;service-worker.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;scope&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;use_cache&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;start_url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;display&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;standalone&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;theme_color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#3f51b5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;background_color&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#3f51b5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;related_applications&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;platform&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;play&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;com.example.android.samplepay&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;min_version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token property&quot;&gt;&quot;fingerprints&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sha256_cert&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token property&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;4C:FC:14:C6:97:DE:66:4E:66:97:50:C0:24:CE:5F:27:00:92:EE:F3:7F:18:B3:DA:77:66:84:CD:9D:E9:D2:CB&quot;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The information described in a web app manifest is also used to define how a
payment app appears in the Payment Request UI.&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Property name&lt;/th&gt;
        &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;code&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/Manifest/name&quot;&gt;name&lt;/a&gt;&lt;/code&gt; (required)
        &lt;/td&gt;
        &lt;td&gt;
        Used as the payment app name.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;code&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/Manifest/icons&quot;&gt;icons&lt;/a&gt;&lt;/code&gt; (required)
        &lt;/td&gt;
        &lt;td&gt;
        Used as the payment app icon. Only Chrome uses these icons; other
        browsers may use them as fallback icons if you don&#39;t specify them as
        part of the payment instrument.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;code&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Service_Worker_API&quot;&gt;serviceworker&lt;/a&gt;&lt;/code&gt;
        &lt;/td&gt;
        &lt;td&gt;
        Used to detect the service worker that runs as the web-based payment
        app.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;serviceworker.src&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
        The URL to download the service worker script from.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;serviceworker.scope&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
        A string representing a URL that defines a service worker&#39;s
        registration scope.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;code&gt;serviceworker.use_cache&lt;/code&gt;&lt;/td&gt;
        &lt;td&gt;
        The URL to download the service worker script from.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;code&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/Manifest/related_applications&quot;&gt;related_applications&lt;/a&gt;&lt;/code&gt;
        &lt;/td&gt;
        &lt;td&gt;
        Used to detect the app that acts as the OS-provided payment app.
        Find more details at &lt;a href=&quot;https://web.dev/android-payment-apps-developers-guide/&quot;&gt;Android
        payment apps developer guide&lt;/a&gt;.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;code&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/Manifest/prefer_related_applications&quot;&gt;prefer_related_applications&lt;/a&gt;&lt;/code&gt;
        &lt;/td&gt;
        &lt;td&gt;
        Used to determine which payment app to launch when both an OS-provided payment app and a web-based payment app are available.
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
    &lt;caption&gt;Important web app manifest fields&lt;/caption&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Payment app with an icon.&quot; decoding=&quot;async&quot; height=&quot;237&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/lyP2t7T5R5bVzqh0LUTx.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;
    Payment app label and icon.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The web app manifest&#39;s &lt;code&gt;name&lt;/code&gt; property is used as the payment app name, &lt;code&gt;icons&lt;/code&gt;
property is used as the payment app icon.&lt;/p&gt;
&lt;h2 id=&quot;how-chrome-determines-which-payment-app-to-launch&quot;&gt;How Chrome determines which payment app to launch &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#how-chrome-determines-which-payment-app-to-launch&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;launching-the-platform-specific-payment-app&quot;&gt;Launching the platform-specific payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#launching-the-platform-specific-payment-app&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To launch the platform-specific payment app, the following conditions must be met:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;related_applications&lt;/code&gt; field is specified in the web app manifest and:
&lt;ul&gt;
&lt;li&gt;The installed app&#39;s package ID and signature match, while the minimum
version (&lt;code&gt;min_version&lt;/code&gt;) in the web app manifest is less than or equal to
the version of the installed application.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;prefer_related_applications&lt;/code&gt; field is &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The platform-specific payment app is installed and has:
&lt;ul&gt;
&lt;li&gt;An intent filter of &lt;code&gt;org.chromium.action.PAY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A payment method identifier specified as the value for the &lt;code&gt;org.chromium.default_payment_method_name&lt;/code&gt; property.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://web.dev/android-payment-apps-developers-guide/&quot;&gt;Android payment apps: developer&#39;s guide&lt;/a&gt;
for more details about how to set these up.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;[payment handler] /manifest.json&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;prefer_related_applications&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token property&quot;&gt;&quot;related_applications&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;platform&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;play&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;xyz.bobpay.app&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;min_version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;fingerprints&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sha256_cert&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;92:5A:39:05:C5:B9:EA:BC:71:48:5F:F2:05:0A:1E:57:5F:23:40:E9:E3:87:14:EC:6D:A2:04:21:E0:FD:3B:D1&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If the browser has determined that the platform-specific payment app is available, the
discovery flow is terminated here. Otherwise it continues to the next step --
launching the web-based payment app.&lt;/p&gt;
&lt;h3 id=&quot;launching-the-web-based-payment-app&quot;&gt;Launching the web-based payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#launching-the-web-based-payment-app&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The web-based payment app should be specified in the web app manifest&#39;s &lt;code&gt;serviceworker&lt;/code&gt; field.&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;[payment handler] /manifest.json:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;serviceworker&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;payment-handler.js&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The browser launches the web-based payment app by sending a &lt;code&gt;paymentrequest&lt;/code&gt;
event to the service worker. The service worker doesn&#39;t have to be registered in
advance. &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#jit-register&quot;&gt;It can be registered just-in-time&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;understanding-the-special-optimizations&quot;&gt;Understanding the special optimizations &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#understanding-the-special-optimizations&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;how-browsers-can-skip-the-payment-request-ui-and-launch-a-payment-app-directly&quot;&gt;How browsers can skip the Payment Request UI and launch a payment app directly &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#how-browsers-can-skip-the-payment-request-ui-and-launch-a-payment-app-directly&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In Chrome, when &lt;code&gt;show()&lt;/code&gt; method of &lt;code&gt;PaymentRequest&lt;/code&gt; is called, the Payment
Request API displays a browser-provided UI called the &amp;quot;Payment Request UI&amp;quot;. This
UI allows users to choose a payment app. After pressing the &lt;strong&gt;Continue&lt;/strong&gt; button
in the Payment Request UI, the selected payment app is launched.&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/VOKIj5Tqfi2bNPCjtkyi.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    Payment Request UI intervenes before launching the payment app.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Showing the Payment Request UI before launching a payment app increases the
number of steps needed for a user to fulfill a payment. To optimize the process,
the browser can delegate fulfillment of that information to payment apps and
launch a payment app directly without showing the Payment Request UI when
&lt;code&gt;show()&lt;/code&gt; is called.&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/8T37CEyLisAjwW39dRwB.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    Skip the Payment Request UI and launch the payment app directly.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To launch a payment app directly, the following conditions must be met:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;show()&lt;/code&gt; is triggered with a user gesture (for example, a mouse click).&lt;/li&gt;
&lt;li&gt;There is only a single payment app that:
&lt;ul&gt;
&lt;li&gt;Supports the requested payment method identifier.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Safari currently only supports Apple Pay so it always launches the app directly, skipping the Payment Request UI. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;jit-register&quot;&gt;When is a web-based payment app registered just-in-time (JIT)? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#jit-register&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Web-based payment apps can be launched without the user&#39;s explicit prior visit
to the payment app website and registering the service worker. The service
worker can be registered just-in-time when the user chooses to pay with the
web-based payment app. There are two variations for the registration timing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the Payment Request UI is shown to the user, the app is registered
just-in-time and launched when the user clicks &lt;strong&gt;Continue&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If the Payment Request UI is skipped, the payment app is registered
just-in-time and launched directly. Skipping the Payment Request UI to launch
a just-in-time registered app requires a user gesture, which prevents
unexpected registration of cross-origin service workers.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; While a single payment method identifier can support multiple payment apps, JIT-registration happens only when the payment method manifest points to a single payment app. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/setting-up-a-payment-method/#next-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that you have your payment app discoverable, learn how to develop a platform-specific
payment app and a web-based payment app.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/android-payment-apps-developers-guide&quot;&gt;Android payment apps: developer&#39;s guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/web-based-payment-apps-overview&quot;&gt;Web based payment apps developer guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Life of a payment transaction</title>
    <link href="https://web.dev/life-of-a-payment-transaction/"/>
    <updated>2020-05-25T00:00:00Z</updated>
    <id>https://web.dev/life-of-a-payment-transaction/</id>
    <content type="html" mode="escaped">&lt;p&gt;Web Payments APIs are dedicated payment features built into the browser
for the first time. With Web Payments, merchant integration with payment apps
becomes simpler while the customer experience gets streamlined and more secure.&lt;/p&gt;
&lt;p&gt;To learn more about the benefits of using Web Payments check out &lt;a href=&quot;https://web.dev/empowering-payment-apps-with-web-payments&quot;&gt;Empowering
payment apps with Web Payments&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This article walks you through a payment transaction on a merchant website and
helps you understand how payment app integration works.&lt;/p&gt;
&lt;p&gt;The process involves 6 steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The merchant initiates a payment transaction.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The merchant shows a payment button.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The customer presses the payment button.&lt;/p&gt;
 &lt;img alt=&quot;A diagram of a cheese shop website with a BobPay (payment app) button.&quot; decoding=&quot;async&quot; height=&quot;298&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/NQIh5tt5wsQFC5yKLCaU.svg&quot; width=&quot;786&quot; /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The browser launches the payment app.&lt;/p&gt;
 &lt;img alt=&quot;A diagram of the cheese shop website with BobPay app launched in a modal. The modal shows shipping options and total cost.&quot; decoding=&quot;async&quot; height=&quot;366&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/IHztIcfJKeWDUIkugTkb.svg&quot; width=&quot;671&quot; /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If the customer changes any details (such as shipping options or their
address), the merchant updates the transaction details reflecting the change.&lt;/p&gt;
 &lt;img alt=&quot;A diagram showing the customer choosing a different shipping option in BobPay app modal. A second diagram showing the merchant updating the total cost displayed in BobPay.&quot; decoding=&quot;async&quot; height=&quot;702&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/BR9Od63aOdG9CaaD1z7K.svg&quot; width=&quot;777&quot; /&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After the customer confirms the purchase, the merchant validates the payment
and completes the transaction.&lt;/p&gt;
 &lt;img alt=&quot;A diagram showing the customer pressing the &amp;quot;Pay&amp;quot; button in BobPay, followed by a diagram of the cheese shop page showing &amp;quot;Payment accepted&amp;quot;.&quot; decoding=&quot;async&quot; height=&quot;708&quot; loading=&quot;lazy&quot; src=&quot;https://web-dev.imgix.net/image/tcFciHGuF3MxnTr1y5ue01OGLBn2/9Q6VqimbOxJ3ZXHvB8ry.svg&quot; width=&quot;778&quot; /&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;step-1-the-merchant-initiates-a-payment-transaction&quot;&gt;Step 1: The merchant initiates a payment transaction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#step-1-the-merchant-initiates-a-payment-transaction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a customer decides to make a purchase, the merchant initiates the payment
transaction by constructing a
&lt;a href=&quot;https://developers.google.com/web/fundamentals/payments/basics/how-payment-request-api-works&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequest&lt;/code&gt;&lt;/a&gt;
object. This object includes important information about the transaction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Acceptable payment methods and their data to process the transaction.&lt;/li&gt;
&lt;li&gt;Details, such as the total price (required) and information about the items.&lt;/li&gt;
&lt;li&gt;Options in which merchants can request shipping information such as a shipping
address and a shipping option.&lt;/li&gt;
&lt;li&gt;Merchants can also request the billing address, the payer&#39;s name, email, and
phone number.&lt;/li&gt;
&lt;li&gt;Merchants can also include optional &lt;a href=&quot;https://developers.google.com/web/fundamentals/payments/merchant-guide/deep-dive-into-payment-request#changing_the_shipping_type&quot; rel=&quot;noopener&quot;&gt;shipping
type&lt;/a&gt;
(&lt;code&gt;shipping&lt;/code&gt;, &lt;code&gt;delivery&lt;/code&gt;, or &lt;code&gt;pickup&lt;/code&gt;) in the &lt;code&gt;PaymentRequest&lt;/code&gt;. The payment app
can use that as a hint to display the correct labels in its UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;supportedMethods&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://bobpay.xyz/pay&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;transactionId&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;****&#39;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;displayItems&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Anvil L/S Crew Neck - Grey M x1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;22.15&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Total due&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;22.15&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requestShipping&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requestBillingAddress&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requestPayerEmail&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requestPayerPhone&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;requestPayerName&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;shippingType&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;delivery&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;details&gt;
&lt;summary&gt;
  Including a transaction ID
&lt;/summary&gt;
&lt;p&gt;Some payment handlers may require the merchant to provide the transaction ID
which they have issued in advance as part of the transaction information. A
typical integration includes communication between the merchant&#39;s and the
payment handler&#39;s server to reserve the total price. This prevents malicious
customers from manipulating the price and cheating the merchant with a
validation at the end of the transaction.&lt;/p&gt;
&lt;p&gt;The merchant can pass a transaction ID as part of the
&lt;a href=&quot;https://www.w3.org/TR/payment-request/#dom-paymentmethoddata&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentMethodData&lt;/code&gt;&lt;/a&gt;
object&#39;s &lt;code&gt;data&lt;/code&gt; property.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;Provided the transaction information, the browser goes through a discovery
process of payment apps specified in the &lt;code&gt;PaymentRequest&lt;/code&gt; based on the payment
method identifiers. This way, the browser can determine the payment app to
launch as soon as the merchant is ready to proceed with the transaction.&lt;/p&gt;
&lt;p&gt;To learn how the discovery process works in detail check out &lt;a href=&quot;https://web.dev/setting-up-a-payment-method#how-a-browser-discovers-a-payment-app&quot;&gt;Setting up a
payment
method&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;step-2-the-merchant-shows-a-payment-button&quot;&gt;Step 2: The merchant shows a payment button &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#step-2-the-merchant-shows-a-payment-button&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Merchants can support many payment methods, but should only present the payment
buttons for those that a customer can actually use. Showing a payment button
that is unusable is poor user experience. If a merchant can predict that a
payment method specified in the &lt;code&gt;PaymentRequest&lt;/code&gt; object won&#39;t work for the
customer, they can provide a fallback solution or not show that button at all.&lt;/p&gt;
&lt;p&gt;Using a &lt;code&gt;PaymentRequest&lt;/code&gt; instance, a merchant can query whether a customer has
the payment app available.&lt;/p&gt;
&lt;h3 id=&quot;does-the-customer-have-the-payment-app-available&quot;&gt;Does the customer have the payment app available? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#does-the-customer-have-the-payment-app-available&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/PaymentRequest/canMakePayment&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;canMakePayment()&lt;/code&gt;&lt;/a&gt;
method of &lt;code&gt;PaymentRequest&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; if a payment app is available on the
customer&#39;s device. &amp;quot;Available&amp;quot; means that a payment app that supports the
payment method is discovered, and that the platform-specific payment app is installed, or
the web-based payment app is &lt;a href=&quot;https://web.dev/setting-up-a-payment-method#jit-register&quot;&gt;ready to be
registered&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; canMakePayment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;canMakePayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;canMakePayment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Fallback to other means of payment or hide the button.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;show&quot;&gt;Step 3: The customer presses the payment button &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#show&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the customer presses the payment button, the merchant calls the &lt;code&gt;show()&lt;/code&gt;
method of the &lt;code&gt;PaymentRequest&lt;/code&gt; instance which immediately triggers the launch of
the payment UI.&lt;/p&gt;
&lt;p&gt;In case the final total price is set dynamically (for example, retrieved from a
server), the merchant can defer the launch of the payment UI until the total is
known.&lt;/p&gt;
&lt;h3 id=&quot;deferring-the-launch-of-the-payment-ui&quot;&gt;Deferring the launch of the payment UI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#deferring-the-launch-of-the-payment-ui&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Check out a demo of &lt;a href=&quot;https://rsolomakhin.github.io/pr/wait/&quot; rel=&quot;noopener&quot;&gt;deferring the payment
UI&lt;/a&gt; until the final total price is
determined.&lt;/p&gt;
&lt;p&gt;To defer the payment UI, the merchant passes a promise to the &lt;code&gt;show()&lt;/code&gt; method.
The browser will show a loading indicator until the promise resolves and the
transaction is ready to begin.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;getTotalAmount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Fetch the total amount from the server, etc.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; result &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTotalAmount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Process the result…&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;handleError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If there is no promise specified as an argument for &lt;code&gt;show()&lt;/code&gt;, the browser will
launch the payment UI immediately.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; If the payment handler is designed to return a transaction ID upon setting the total price, the ID can be passed as part of the promise result. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;launch&quot;&gt;Step 4: The browser launches the payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#launch&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The browser can launch a platform-specific or a web-based payment app. (You can learn more
about &lt;a href=&quot;https://web.dev/setting-up-a-payment-method#how-chrome-determines-which-payment-app-to-launch&quot;&gt;how Chrome determines which payment app to
launch&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;How the payment app is built is up to the developer for the most part, but the
events emitted from and to the merchant, as well as the structure of the data
passed along with those events, are standardized.&lt;/p&gt;
&lt;p&gt;When the payment app is launched, it receives &lt;a href=&quot;https://w3c.github.io/payment-handler/#the-paymentrequestevent&quot; rel=&quot;noopener&quot;&gt;the transaction
information&lt;/a&gt;
passed to the &lt;code&gt;PaymentRequest&lt;/code&gt; object in Step 1, which includes the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Payment method data&lt;/li&gt;
&lt;li&gt;Total price&lt;/li&gt;
&lt;li&gt;Payment options&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The payment app uses the transaction information to label its UI.&lt;/p&gt;
&lt;h2 id=&quot;step-5-how-a-merchant-can-update-the-transaction-details-depending-on-customers-actions&quot;&gt;Step 5: How a merchant can update the transaction details depending on customer&#39;s actions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#step-5-how-a-merchant-can-update-the-transaction-details-depending-on-customers-actions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Customers have an option to change the transaction details such as payment
method and shipping option in the payment app. While the customer makes changes,
the merchant receives the change events and updates the transaction details.&lt;/p&gt;
&lt;p&gt;There are four types of events a merchant can receive:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Payment method change event&lt;/li&gt;
&lt;li&gt;Shipping address change event&lt;/li&gt;
&lt;li&gt;Shipping option change event&lt;/li&gt;
&lt;li&gt;Merchant validation event&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;payment-method-change-event&quot;&gt;Payment method change event &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#payment-method-change-event&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A payment app can support multiple payment methods and a merchant may offer a
special discount depending on the customer&#39;s selection. To cover this use case,
the payment method change event can inform the merchant of the new payment
method so that they can update the total price with the discount and return it
back to the payment app.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;paymentmethodchange&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Add discount etc.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;shipping-address-change-event&quot;&gt;Shipping address change event &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#shipping-address-change-event&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A payment app can optionally provide the customer&#39;s shipping address. This is
convenient for customers because they don&#39;t have to manually enter any details
into a form and they can store their shipping address in their preferred payment
apps, rather than on multiple different merchant websites.&lt;/p&gt;
&lt;p&gt;If a customer updates their shipping address in a payment app after the
transaction has been initiated, a &lt;code&gt;&#39;shippingaddresschange&#39;&lt;/code&gt; event will be sent
to the merchant. This event helps the merchant determine the shipping cost based
on the new address, update the total price, and return it to the payment app.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;shippingaddresschange&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Update the details&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If the merchant can&#39;t ship to the updated address, they can provide an error
message by adding an error parameter to the transaction details returned to the
payment app.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Merchants don&#39;t receive customers&#39; full shipping address until they&#39;ve authorized the payment. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;shipping-option-change-event&quot;&gt;Shipping option change event &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#shipping-option-change-event&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A merchant can offer multiple shipping options to the customer and can delegate
that choice to the payment app. The shipping options are displayed as a list of
prices and service names the customer can select from. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Standard shipping - Free&lt;/li&gt;
&lt;li&gt;Express shipping - 5 USD&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a customer updates the shipping option in a payment app, a
&lt;code&gt;&#39;shippingoptionchange&#39;&lt;/code&gt; event will be sent to the merchant. The merchant can
then determine the shipping cost, update the total price, and return it to the
payment app.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;shippingoptionchange&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Update the details&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The merchant can dynamically modify the shipping options based on the customer&#39;s
shipping address as well. This is useful when a merchant wants to offer
different sets of shipping options for domestic and international customers.&lt;/p&gt;
&lt;h3 id=&quot;merchant-validation-event&quot;&gt;Merchant validation event &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#merchant-validation-event&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For additional security, a payment app can perform a merchant validation before
proceeding to the payment flow. The design of the validation mechanism is up to
the payment app, but the merchant validation event serves to inform the merchant
of the URL they can use to validate themselves.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;merchantvalidation&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Use `e.validateURL` to validate&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The support for the merchant validation event is limited to Apple Safari. Chromium-based browsers have not implemented this event as of May 2020. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;step-6-the-merchant-validates-the-payment-and-completes-the-transaction&quot;&gt;Step 6: The merchant validates the payment and completes the transaction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#step-6-the-merchant-validates-the-payment-and-completes-the-transaction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the customer successfully authorizes the payment, the &lt;code&gt;show()&lt;/code&gt; method
returns a promise that resolves to a
&lt;a href=&quot;https://w3c.github.io/payment-request/#paymentresponse-interface&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentResponse&lt;/code&gt;&lt;/a&gt;.
The &lt;code&gt;PaymentResponse&lt;/code&gt; object includes the following information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Payment result details&lt;/li&gt;
&lt;li&gt;Shipping address&lt;/li&gt;
&lt;li&gt;Shipping option&lt;/li&gt;
&lt;li&gt;Contact information&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, the browser UI may still show a loading indicator meaning that
the transaction is not completed yet.&lt;/p&gt;
&lt;p&gt;If the payment app is terminated because of a payment failure or error, the
promise returned from &lt;code&gt;show()&lt;/code&gt; rejects, and the browser terminates the payment
transaction.&lt;/p&gt;
&lt;h3 id=&quot;processing-and-validating-the-payment&quot;&gt;Processing and validating the payment &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#processing-and-validating-the-payment&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;details&lt;/code&gt; in &lt;code&gt;PaymentResponse&lt;/code&gt; is the payment credential object returned
from the payment app. The merchant can use the credential to process or validate
the payment. How this critical process works is up to the payment handler.&lt;/p&gt;
&lt;h3 id=&quot;completing-or-retrying-the-transaction&quot;&gt;Completing or retrying the transaction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#completing-or-retrying-the-transaction&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;After the merchant determines whether the transaction has succeded or failed,
they can either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Call the &lt;code&gt;.complete()&lt;/code&gt; method to complete the transaction and dismiss the
loading indicator.&lt;/li&gt;
&lt;li&gt;Let the customer retry by calling the &lt;code&gt;retry()&lt;/code&gt; method.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;doPaymentRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;methodData&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; details&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; options&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; response &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// AbortError, SecurityError&lt;/span&gt;&lt;br /&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; errors &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;checkAllValuesAreGood&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;retry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;errors&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;validateResponse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;response&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Something went wrong…&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;fail&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Must be called as a result of a click&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// or some explicit user action.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;doPaymentRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/life-of-a-payment-transaction/#next-steps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Learn how to declare a payment method identifier in detail in &lt;a href=&quot;https://web.dev/setting-up-a-payment-method&quot;&gt;Setting up a
payment method&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learn how to build a platform-specific payment app in
&lt;a href=&quot;https://web.dev/android-payment-apps-developers-guide&quot;&gt;Android payment apps developer&#39;s guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learn how to build a web-based payment app in &lt;a href=&quot;https://web.dev/web-based-payment-apps-overview&quot;&gt;Web-based payment apps developer&#39;s
guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author><author>
      <name>Milica Mihajlija</name>
    </author>
  </entry>
  
  <entry>
    <title>Empowering payment apps with Web Payments</title>
    <link href="https://web.dev/empowering-payment-apps-with-web-payments/"/>
    <updated>2020-05-25T00:00:00Z</updated>
    <id>https://web.dev/empowering-payment-apps-with-web-payments/</id>
    <content type="html" mode="escaped">&lt;p&gt;One of the key ecosystem drivers for the web are payments. With secure,
seamless, and flexible payment systems, the web can become a sustainable and
profitable platform. The Web Payments standards have the potential to be a key
building block that will enable seamless integration of payment solutions into
merchant checkout flows.&lt;/p&gt;
&lt;h2 id=&quot;what-is-web-payments&quot;&gt;What is Web Payments? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#what-is-web-payments&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web Payments is a series of new standardized payment APIs available in modern
browsers, including &lt;a href=&quot;https://www.w3.org/TR/payment-request/&quot; rel=&quot;noopener&quot;&gt;Payment Request
API&lt;/a&gt;, &lt;a href=&quot;https://www.w3.org/TR/payment-handler/&quot; rel=&quot;noopener&quot;&gt;Payment Handler
API&lt;/a&gt; and &lt;a href=&quot;https://www.w3.org/Payments/WG/charter-201912.html#scope&quot; rel=&quot;noopener&quot;&gt;a few
others&lt;/a&gt;. These new
browser primitives simplify online payments and enable payment apps to integrate
with browsers easier than ever.&lt;/p&gt;
&lt;p&gt;The standards are flexible; they work with various types of payment systems and
are intended to work on any browser on any device, payment method, or payment
service provider. This flexibility enables development simplicity, deployment
consistency, and future compatibility with emerging payment technologies.&lt;/p&gt;
&lt;p&gt;Research shows that &lt;a href=&quot;https://baymard.com/blog/checkout-flow-average-form-fields&quot; rel=&quot;noopener&quot;&gt;long checkout flows lead to cart
abandonment&lt;/a&gt;. With
Web Payments, checkout flow is simplified to a few taps instead of manual entry
of billing data for every purchase. See a demo below of how Google Pay leverages
Web Payments to build a seamless flow. The same can be achieved by any other
payment app:&lt;/p&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/hzMuAwPAGpNmgxHpaHAq.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;Checkout flow with Google Pay and Web Payments.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The customer goes to checkout and presses the &lt;strong&gt;GPay&lt;/strong&gt; button.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Google Pay app launches &lt;em&gt;in front of the merchant website&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The customer confirms payment in the Google Pay app after examining the
details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The merchant verifies the payment and the purchase is approved.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web Payments consists of a few different pieces of technologies and the support
status depends on the browser.&lt;/p&gt;
&lt;div class=&quot;table-wrapper scrollbar&quot;&gt;
  &lt;table&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Chromium&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Safari&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Firefox&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Android&lt;/td&gt;
      &lt;td&gt;Desktop&lt;/td&gt;
      &lt;td&gt;Mobile&lt;/td&gt;
      &lt;td&gt;Desktop/Mobile&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Request API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Payment Handler API&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;iOS/Android payment app&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; *Safari supports Apple Pay but no third party payment apps. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;the-benefits-of-integrating-web-payments-in-a-payment-app&quot;&gt;The benefits of integrating Web Payments in a payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#the-benefits-of-integrating-web-payments-in-a-payment-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By integrating with Web Payments, payment apps can provide better user
experience to customers, have better developer experience, and stricter
security.&lt;/p&gt;
&lt;h3 id=&quot;better-user-experience&quot;&gt;Better user experience &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#better-user-experience&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;In-context payments:&lt;/strong&gt; Payments are made in
&lt;a href=&quot;https://material.io/components/sheets-bottom&quot; rel=&quot;noopener&quot;&gt;modals&lt;/a&gt;, in context of the
merchant website, without redirects or pop-up windows.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Faster checkout&lt;/strong&gt;: Customers can save their payment details securely in
their browser or a payment app, ready to be used on any supporting merchant site.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Streamlined purchase experience:&lt;/strong&gt; After completing (or aborting) the
payment, the customer is on the merchant website exactly where they left off.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;better-developer-experience&quot;&gt;Better developer experience &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#better-developer-experience&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Easy integration:&lt;/strong&gt; Web Payments can be extended from an existing platform-specific
payment app or a web-based payment app.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Low integration cost:&lt;/strong&gt; Merchants can integrate Web Payments with JavaScript
and basic level server-side integration.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Standards:&lt;/strong&gt; The protocol and data format for exchanging information with
merchants is standardized and doesn&#39;t require deep integration.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;stricter-security&quot;&gt;Stricter security &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#stricter-security&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Sideloading&quot; rel=&quot;noopener&quot;&gt;Sideloading&lt;/a&gt; prevention when
invoking platform-specific payment apps.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Designed with upcoming security and privacy paradigms in mind.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using Web Payments also enables payment apps to bring any kind of payment method
to the web such as e-money, cryptocurrency, bank transfers, and more. Web
Payments is designed with sustainability in mind and doesn&#39;t put any
restrictions on payment processing and payment methods.&lt;/p&gt;
&lt;h2 id=&quot;comparing-web-payments-to-other-approaches&quot;&gt;Comparing Web Payments to other approaches &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#comparing-web-payments-to-other-approaches&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Consider the existing approaches to integrating payments on the web:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;iframes:&lt;/strong&gt; Using JavaScript to inject the payment handler&#39;s website in an
iframe and collect the customer&#39;s payment credential through a form.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pop-ups:&lt;/strong&gt; Using JavaScript to open a pop-up window and collect the
customer&#39;s payment credentials, either through a form or by having the
customer authenticate and select a payment credential.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Redirects:&lt;/strong&gt; Merchant redirects the customer to a payment handler&#39;s website
and lets the customer authenticate and select payment credentials. The
redirect URL is communicated via a server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;OAuth:&lt;/strong&gt; Merchant lets the customer authenticate and authorize with a
payment handler&#39;s identity via OAuth, select a payment method, shipping
address etc through in-context iframe UI.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#39;s how they compare to Web Payments:&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Web Payments&lt;/td&gt;
      &lt;td&gt;iframe&lt;/td&gt;
      &lt;td&gt;Popup&lt;/td&gt;
      &lt;td&gt;Redirect&lt;/td&gt;
      &lt;td&gt;OAuth&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;In-context payments&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;✔*&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Dynamic price updates&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Streamlined purchase experience&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Platform-specific app integration&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Low integration cost&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Standards&lt;/td&gt;
      &lt;td&gt;✔&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; *Redirecting to a platform-specific payment app can be done in-context with the merchant website though redirecting to another website completely loses the context. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;integrating-web-payments-in-existing-apps&quot;&gt;Integrating Web Payments in existing apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#integrating-web-payments-in-existing-apps&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can integrate Web Payments in both platform-specific and web-based payment apps: if the
platform-specific payment app is not installed, the web-based payment app can be used as a
fallback. Customers and merchants can seamlessly send and receive payments
through a payment method of their choice, depending on the environment.&lt;/p&gt;
&lt;h3 id=&quot;platform-specific-payment-apps&quot;&gt;Platform-specific payment apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#platform-specific-payment-apps&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Ideal for payment apps that already have a large install base and want to give
existing users a consistent experience on the web.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unlike &lt;a href=&quot;https://developer.android.com/guide/components/intents-filters&quot; rel=&quot;noopener&quot;&gt;Android&#39;s &amp;quot;Intent&amp;quot;
feature&lt;/a&gt;, Web
Payments performs signature verification before running the payment app which
makes malicious payment apps impossible to be sideloaded.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the video above, Google Pay is a platform-specific payment app.&lt;/p&gt;
&lt;h3 id=&quot;web-based-payment-apps&quot;&gt;Web based payment apps &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#web-based-payment-apps&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;More future proof: typical payment app techniques like redirects or pop-ups
are based on third party cookies &lt;a href=&quot;https://blog.chromium.org/2020/01/building-more-private-web-path-towards.html&quot; rel=&quot;noopener&quot;&gt;that may become
obsolete&lt;/a&gt;.
While it&#39;s still hard to foresee the consequences, Web Payments look to the
web with better privacy and a world without third party cookies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The web-based route is ideal for web services that have a large number of
customers with their card on file.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/kM6NP47k4Xzl4tHWISCm.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;
    Checkout flow with a web-based payment app.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;how-does-merchant-adoption-work&quot;&gt;How does merchant adoption work? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#how-does-merchant-adoption-work&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For a payment app to be available on a merchant, the merchant needs to
explicitly adopt it. Technically speaking, the merchant has to specify the
payment app&#39;s identifier (payment method identifier) and use the Payment Request
API with it.&lt;/p&gt;
&lt;p&gt;We suggest that you provide good documentation in integration guides and SDKs or
libraries to facilitate integration. For example, Google Pay provides &lt;a href=&quot;https://developers.google.com/pay/api/web/overview&quot; rel=&quot;noopener&quot;&gt;a
developer&#39;s guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Working with payment gateways is also a good option as they can help scale your
outreach as well.&lt;/p&gt;
&lt;h2 id=&quot;how-much-does-it-cost&quot;&gt;How much does it cost? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/empowering-payment-apps-with-web-payments/#how-much-does-it-cost&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web Payments is all about standard technology in the browser. Payment apps
adopting it nor activating it on the browser won&#39;t charge them any fees by
itself.&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Android payment app developers guide</title>
    <link href="https://web.dev/android-payment-apps-developers-guide/"/>
    <updated>2020-05-25T00:00:00Z</updated>
    <id>https://web.dev/android-payment-apps-developers-guide/</id>
    <content type="html" mode="escaped">&lt;p&gt;The &lt;a href=&quot;https://www.w3.org/TR/payment-request/&quot; rel=&quot;noopener&quot;&gt;Payment Request API&lt;/a&gt; brings to the
web a built-in browser-based interface that allows users to enter required payment
information easier than ever before. The API can also invoke platform-specific payment
apps.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 60, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      60
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 55, Behind a flag&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;flag&quot; title=&quot;Behind a flag&quot; aria-label=&quot;Behind a flag&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 15, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
15
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari 11.1, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
11.1
&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/PaymentRequest#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;
  &lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot;&gt;      &lt;source src=&quot;https://storage.googleapis.com/web-dev-uploads/video/YLflGBAPWecgtKJLqCJHSzHqe2J2/hzMuAwPAGpNmgxHpaHAq.mp4&quot; type=&quot;video/mp4&quot; /&gt;    &lt;/video&gt;
  &lt;figcaption&gt;Checkout flow with platform-specific Google Pay app that uses Web Payments.
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Compared to using just Android Intents, Web Payments allow better integration
with the browser, security, and user experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The payment app is launched as a modal, in context of the merchant website.&lt;/li&gt;
&lt;li&gt;Implementation is supplemental to your existing payment app, enabling you to
take advantage of your user base.&lt;/li&gt;
&lt;li&gt;The payment app&#39;s signature is checked to prevent
&lt;a href=&quot;https://en.wikipedia.org/wiki/Sideloading&quot; rel=&quot;noopener&quot;&gt;sideloading&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Payment apps can support multiple payment methods.&lt;/li&gt;
&lt;li&gt;Any payment method, such as cryptocurrency, bank transfers, and more, can be
integrated. Payment apps on Android devices can even integrate methods that
require access to the hardware chip on the device.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; To understand how merchants integrate with payment apps, check out &lt;a href=&quot;https://web.dev/life-of-a-payment-transaction/&quot;&gt;Life of a payment transaction&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;It takes four steps to implement Web Payments in an Android payment app:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Let merchants discover your payment app.&lt;/li&gt;
&lt;li&gt;Let a merchant know if a customer has an enrolled instrument (such as credit
card) that is ready to pay.&lt;/li&gt;
&lt;li&gt;Let a customer make payment.&lt;/li&gt;
&lt;li&gt;Verify the caller&#39;s signing certificate.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To see Web Payments in action, check out the
&lt;a href=&quot;https://github.com/GoogleChromeLabs/android-web-payment/&quot; rel=&quot;noopener&quot;&gt;android-web-payment&lt;/a&gt;
demo.&lt;/p&gt;
&lt;h2 id=&quot;step-1-let-merchants-discover-your-payment-app&quot;&gt;Step 1: Let merchants discover your payment app &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#step-1-let-merchants-discover-your-payment-app&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In order for a merchant to use your payment app, they need to use the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Payment_Request_API&quot; rel=&quot;noopener&quot;&gt;Payment
Request API&lt;/a&gt; and
specify the payment method you support using the &lt;a href=&quot;https://www.w3.org/TR/payment-method-id/&quot; rel=&quot;noopener&quot;&gt;payment method
identifier&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have a payment method identifier that is unique to your payment app, you
can set up your own &lt;a href=&quot;https://w3c.github.io/payment-method-manifest/&quot; rel=&quot;noopener&quot;&gt;payment method
manifest&lt;/a&gt; so browsers can
discover your app.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; To learn how the discovery process works in detail and how to set up a new payment method check out &lt;a href=&quot;https://web.dev/setting-up-a-payment-method&quot;&gt;Setting up a payment method&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;step-2-let-a-merchant-know-if-a-customer-has-an-enrolled-instrument-that-is-ready-to-pay&quot;&gt;Step 2: Let a merchant know if a customer has an enrolled instrument that is ready to pay &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#step-2-let-a-merchant-know-if-a-customer-has-an-enrolled-instrument-that-is-ready-to-pay&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The merchant can call &lt;code&gt;hasEnrolledInstrument()&lt;/code&gt; to &lt;a href=&quot;https://web.dev/life-of-a-payment-transaction#ready-to-pay&quot;&gt;query whether the customer
is able to make a payment&lt;/a&gt;. You can
implement &lt;code&gt;IS_READY_TO_PAY&lt;/code&gt; as an Android service to answer this query.&lt;/p&gt;
&lt;h3 id=&quot;androidmanifestxml&quot;&gt;&lt;code&gt;AndroidManifest.xml&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#androidmanifestxml&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Declare your service with an intent filter with the action
&lt;code&gt;org.chromium.intent.action.IS_READY_TO_PAY&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;service&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;.SampleIsReadyToPayService&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;exported&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;true&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;intent-filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;action&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;org.chromium.intent.action.IS_READY_TO_PAY&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;intent-filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;IS_READY_TO_PAY&lt;/code&gt; service is optional. If there&#39;s no such intent handler in
the payment app, then the web browser assumes that the app can always make
payments.&lt;/p&gt;
&lt;h3 id=&quot;aidl&quot;&gt;AIDL &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#aidl&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The API for the &lt;code&gt;IS_READY_TO_PAY&lt;/code&gt; service is defined in AIDL. Create two AIDL
files with the following content:&lt;/p&gt;
&lt;p class=&quot;label&quot;&gt;app/src/main/aidl/org/chromium/IsReadyToPayServiceCallback.aidl&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;chromium&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; IsReadyToPayServiceCallback &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    oneway void &lt;span class=&quot;token function&quot;&gt;handleIsReadyToPay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;boolean isReadyToPay&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p class=&quot;label&quot;&gt;app/src/main/aidl/org/chromium/IsReadyToPayService.aidl&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;chromium&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; org&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;chromium&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;IsReadyToPayServiceCallback&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;interface&lt;/span&gt; IsReadyToPayService &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    oneway void &lt;span class=&quot;token function&quot;&gt;isReadyToPay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;IsReadyToPayServiceCallback callback&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;implementing-isreadytopayservice&quot;&gt;Implementing &lt;code&gt;IsReadyToPayService&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#implementing-isreadytopayservice&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The simplest implementation of &lt;code&gt;IsReadyToPayService&lt;/code&gt; is shown in the following
example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; SampleIsReadyToPayService &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Service&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; binder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IsReadyToPayService&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Stub&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isReadyToPay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IsReadyToPayServiceCallback&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      callback&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleIsReadyToPay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onBind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;intent&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Intent&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IBinder&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; binder&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;response&quot;&gt;Response &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#response&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The service can send its response via &lt;code&gt;handleIsReadyToPay(Boolean)&lt;/code&gt; method.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;callback&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;handleIsReadyToPay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;permission&quot;&gt;Permission &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#permission&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can use &lt;code&gt;Binder.getCallingUid()&lt;/code&gt; to check who the caller is. Note that you
have to do this in the &lt;code&gt;isReadyToPay&lt;/code&gt; method, not in the &lt;code&gt;onBind&lt;/code&gt; method.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isReadyToPay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;callback&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; IsReadyToPayServiceCallback&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; callingPackage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; packageManager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getNameForUid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Binder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCallingUid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;See &lt;a href=&quot;https://web.dev/android-payment-apps-developers-guide/#heading=h.czr8ye23zg2e&quot;&gt;Verify the caller&#39;s signing certificate&lt;/a&gt; about how
to verify that the calling package has the right signature.&lt;/p&gt;
&lt;h2 id=&quot;step-3-let-a-customer-make-payment&quot;&gt;Step 3: Let a customer make payment &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#step-3-let-a-customer-make-payment&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The merchant calls &lt;code&gt;show()&lt;/code&gt; to &lt;a href=&quot;https://web.dev/life-of-a-payment-transaction#launch&quot;&gt;launch the payment
app&lt;/a&gt;
so the customer can make a payment. The payment app is invoked via an Android
intent &lt;code&gt;PAY&lt;/code&gt; with transaction information in the intent parameters.&lt;/p&gt;
&lt;p&gt;The payment app responds with &lt;code&gt;methodName&lt;/code&gt; and &lt;code&gt;details&lt;/code&gt;, which are payment app
specific and are opaque to the browser. The browser converts the &lt;code&gt;details&lt;/code&gt;
string into a JavaScript object for the merchant via JSON deserialization, but
does not enforce any validity beyond that. The browser does not modify the
&lt;code&gt;details&lt;/code&gt;; that parameter&#39;s value is passed directly to the merchant.&lt;/p&gt;
&lt;h3 id=&quot;androidmanifestxml-2&quot;&gt;&lt;code&gt;AndroidManifest.xml&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#androidmanifestxml-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The activity with the &lt;code&gt;PAY&lt;/code&gt; intent filter should have a &lt;code&gt;&amp;lt;meta-data&amp;gt;&lt;/code&gt; tag &lt;a href=&quot;https://web.dev/setting-up-a-payment-method&quot;&gt;that
identifies the default payment method identifier for the
app&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To support multiple payment methods, add a &lt;code&gt;&amp;lt;meta-data&amp;gt;&lt;/code&gt; tag with a
&lt;code&gt;&amp;lt;string-array&amp;gt;&lt;/code&gt; resource.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;activity&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;.PaymentActivity&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;theme&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;@style/Theme.SamplePay.Dialog&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;intent-filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;action&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;org.chromium.intent.action.PAY&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;intent-filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta-data&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;org.chromium.default_payment_method_name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;value&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://bobbucks.dev/pay&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta-data&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;org.chromium.payment_method_names&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token attr-name&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;android:&lt;/span&gt;resource&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;@array/method_names&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;activity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;resource&lt;/code&gt; must be a list of strings, each of which must be a valid,
absolute URL with an HTTPS scheme as shown here.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-xml&quot;&gt;&lt;code class=&quot;language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;string-array&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;method_names&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;https://alicepay.com/put/optional/path/here&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;https://charliepay.com/put/optional/path/here&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;string-array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;parameters&quot;&gt;Parameters &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#parameters&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The following parameters are passed to the activity as Intent extras:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;methodNames&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;methodData&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;topLevelOrigin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;topLevelCertificateChain&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;paymentRequestOrigin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;total&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;modifiers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;paymentRequestId&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; extras&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bundle&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; intent&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;extras&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;methodnames&quot;&gt;methodNames &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#methodnames&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The names of the methods being used. The elements are the keys in the
&lt;code&gt;methodData&lt;/code&gt; dictionary. These are the methods that the payment app supports.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; methodNames&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;String&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getStringArrayList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;methodNames&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;methoddata&quot;&gt;&lt;code&gt;methodData&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#methoddata&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;A mapping from each of the &lt;code&gt;methodNames&lt;/code&gt; to the
&lt;a href=&quot;https://w3c.github.io/payment-request/#declaring-multiple-ways-of-paying&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;methodData&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; methodData&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Bundle&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBundle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;methodData&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;merchantname&quot;&gt;merchantName &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#merchantname&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The contents of the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; HTML tag of the merchant&#39;s checkout page (the
browser&#39;s top-level browsing context).&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; merchantName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;merchantName&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;toplevelorigin&quot;&gt;&lt;code&gt;topLevelOrigin&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#toplevelorigin&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The merchant&#39;s origin without the scheme (The scheme-less origin of the
top-level browsing context). For example, &lt;code&gt;https://mystore.com/checkout&lt;/code&gt; is
passed as &lt;code&gt;mystore.com&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; topLevelOrigin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;topLevelOrigin&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;toplevelcertificatechain&quot;&gt;&lt;code&gt;topLevelCertificateChain&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#toplevelcertificatechain&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The merchant&#39;s certificate chain (The certificate chain of the top-level
browsing context). Null for localhost and file on disk, which are both secure
contexts without SSL certificates. Each &lt;code&gt;Parcelable&lt;/code&gt; is a Bundle with a
&lt;code&gt;certificate&lt;/code&gt; key and a byte array value.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; topLevelCertificateChain&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Array&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;Parcelable&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;br /&gt;    extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getParcelableArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;topLevelCertificateChain&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; list&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; List&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ByteArray&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; topLevelCertificateChain&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mapNotNull&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; p &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Bundle&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getByteArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;certificate&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;paymentrequestorigin&quot;&gt;&lt;code&gt;paymentRequestOrigin&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#paymentrequestorigin&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The scheme-less origin of the iframe browsing context that invoked the &lt;code&gt;new PaymentRequest(methodData, details, options)&lt;/code&gt; constructor in JavaScript. If the
constructor was invoked from the top-level context, then the value of this
parameter equals the value of &lt;code&gt;topLevelOrigin&lt;/code&gt; parameter.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; paymentRequestOrigin&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;paymentRequestOrigin&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;total&quot;&gt;&lt;code&gt;total&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#total&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The JSON string representing the total amount of the transaction.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; total&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;total&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Here&#39;s an example content of the string:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;currency&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;USD&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;25.00&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h4 id=&quot;modifiers&quot;&gt;&lt;code&gt;modifiers&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#modifiers&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The output of &lt;code&gt;JSON.stringify(details.modifiers)&lt;/code&gt;, where &lt;code&gt;details.modifiers&lt;/code&gt;
contain only &lt;code&gt;supportedMethods&lt;/code&gt; and &lt;code&gt;total&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&quot;paymentrequestid&quot;&gt;&lt;code&gt;paymentRequestId&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#paymentrequestid&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;PaymentRequest.id&lt;/code&gt; field that &amp;quot;push-payment&amp;quot; apps should associate with the
transaction state. Merchant websites will use this field to query the
&amp;quot;push-payment&amp;quot; apps for the state of transaction out of band.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; paymentRequestId&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; extras&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;paymentRequestId&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;response-2&quot;&gt;Response &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#response-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The activity can send its response back through &lt;code&gt;setResult&lt;/code&gt; with &lt;code&gt;RESULT_OK&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Activity&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;RESULT_OK&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Intent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;putExtra&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;methodName&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://bobbucks.dev/pay&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token function&quot;&gt;putExtra&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;details&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;{\&quot;token\&quot;: \&quot;put-some-data-here\&quot;}&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;finish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;You must specify two parameters as Intent extras:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;methodName&lt;/code&gt;: The name of the method being used.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;details&lt;/code&gt;: JSON string containing information necessary for the merchant to
complete the transaction. If success is &lt;code&gt;true&lt;/code&gt;, then &lt;code&gt;details&lt;/code&gt; must be
constructed in such a way that &lt;code&gt;JSON.parse(details)&lt;/code&gt; will succeed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can pass &lt;code&gt;RESULT_CANCELED&lt;/code&gt; if the transaction was not completed in the
payment app, for example, if the user failed to type in the correct PIN code for
their account in the payment app. The browser may let the user choose a
different payment app.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token function&quot;&gt;setResult&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;RESULT_CANCELED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;finish&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If the activity result of a payment response received from the invoked payment
app is set to &lt;code&gt;RESULT_OK&lt;/code&gt;, then Chrome will check for non-empty &lt;code&gt;methodName&lt;/code&gt; and
&lt;code&gt;details&lt;/code&gt; in its extras. If the validation fails Chrome will return a rejected
promise from &lt;code&gt;request.show()&lt;/code&gt; with one of the following developer facing error
messages:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Payment app returned invalid response. Missing field &quot;details&quot;.&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Payment app returned invalid response. Missing field &quot;methodName&quot;.&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;permission-2&quot;&gt;Permission &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#permission-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The activity can check the caller with its &lt;code&gt;getCallingPackage()&lt;/code&gt; method.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; caller&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; callingPackage&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The final step is to verify the caller&#39;s signing certificate to confirm that the
calling package has the right signature.&lt;/p&gt;
&lt;h2 id=&quot;step-4-verify-the-callers-signing-certificate&quot;&gt;Step 4: Verify the caller&#39;s signing certificate &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/android-payment-apps-developers-guide/#step-4-verify-the-callers-signing-certificate&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can check the caller&#39;s package name with &lt;code&gt;Binder.getCallingUid()&lt;/code&gt; in
&lt;code&gt;IS_READY_TO_PAY&lt;/code&gt;, and with &lt;code&gt;Activity.getCallingPackage()&lt;/code&gt; in &lt;code&gt;PAY&lt;/code&gt;. In order to
actually verify that the caller is the browser you have in mind, you should
check its signing certificate and make sure that it matches with the correct
value.&lt;/p&gt;
&lt;p&gt;If you&#39;re targeting API level 28 and above and are integrating with a browser
that has a single signing certificate, you can use
&lt;code&gt;PackageManager.hasSigningCertificate()&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; packageName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; … &lt;span class=&quot;token comment&quot;&gt;// The caller&#39;s package name&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; certificate&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ByteArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; … &lt;span class=&quot;token comment&quot;&gt;// The correct signing certificate.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; verified &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; packageManager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasSigningCertificate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;br /&gt;  callingPackage&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  certificate&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  PackageManager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CERT_INPUT_SHA256&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;PackageManager.hasSigningCertificate()&lt;/code&gt; is preferred for single certificate
browsers, because it correctly handles certificate rotation. (Chrome has a
single signing certificate.) Apps that have multiple signing certificates cannot
rotate them.&lt;/p&gt;
&lt;p&gt;If you need to support older API levels 27 and below, or if you need to handle
browsers with multiple signing certificates, you can use
&lt;code&gt;PackageManager.GET_SIGNATURES&lt;/code&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-kotlin&quot;&gt;&lt;code class=&quot;language-kotlin&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; packageName&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; String &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; … &lt;span class=&quot;token comment&quot;&gt;// The caller&#39;s package name&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; certificates&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Set&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;ByteArray&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; … &lt;span class=&quot;token comment&quot;&gt;// The correct set of signing certificates&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; packageInfo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getPackageInfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;packageName&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PackageManager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GET_SIGNATURES&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; sha256 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; MessageDigest&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getInstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string-literal singleline&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;SHA-256&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; signatures &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; packageInfo&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;signatures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; sha256&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;digest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toByteArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;val&lt;/span&gt; verified &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; signatures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; certificates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;br /&gt;    signatures&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; s &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; certificates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; it&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;contentEquals&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content>
    <author>
      <name>Yuichi Araki</name>
    </author><author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Why you need &quot;cross-origin isolated&quot; for powerful features</title>
    <link href="https://web.dev/why-coop-coep/"/>
    <updated>2020-05-04T00:00:00Z</updated>
    <id>https://web.dev/why-coop-coep/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;introduction&quot;&gt;Introduction &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#introduction&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;Making your website &amp;quot;cross-origin isolated&amp;quot; using COOP and
COEP&lt;/a&gt; we explained how to adopt to &amp;quot;cross-origin
isolated&amp;quot; state using COOP and COEP. This is a companion article that explains
why cross-origin isolation is required to enable powerful features on the browser.&lt;/p&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; This article uses many similar-sounding terminologies. To make things clearer, let&#39;s define them:  * &lt;a href=&quot;https://wicg.github.io/cross-origin-embedder-policy/&quot;&gt;COEP: Cross Origin Embedder Policy&lt;/a&gt; * &lt;a href=&quot;https://github.com/whatwg/html/pull/5334/files&quot;&gt;COOP: Cross Origin Opener Policy&lt;/a&gt; * &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)&quot;&gt;CORP: Cross Origin Resource Policy&lt;/a&gt; * &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/CORS&quot;&gt;CORS: Cross Origin Resource Sharing&lt;/a&gt; * &lt;a href=&quot;https://www.chromium.org/Home/chromium-security/corb-for-developers&quot;&gt;CORB: Cross Origin Read Blocking&lt;/a&gt; &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;background&quot;&gt;Background &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#background&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The web is built on the &lt;a href=&quot;https://web.dev/same-origin-policy/&quot;&gt;same-origin
policy&lt;/a&gt;: a security feature that restricts
how documents and scripts can interact with resources from another origin. This
principle restricts the ways websites can access cross-origin resources. For
example, a document from &lt;code&gt;https://a.example&lt;/code&gt; is prevented from accessing data
hosted at &lt;code&gt;https://b.example&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, the same-origin policy has had some historical exceptions. Any website can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Embed cross-origin iframes&lt;/li&gt;
&lt;li&gt;Include cross-origin resources such as images or scripts&lt;/li&gt;
&lt;li&gt;Open cross-origin popup windows with a DOM reference&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the web could be designed from scratch, these exceptions wouldn&#39;t exist.
Unfortunately, by the time the web community realized the key benefits of a
strict same-origin policy, the web was already relying on these exceptions.&lt;/p&gt;
&lt;p&gt;The security side-effects of such a lax same-origin policy were patched in two
ways. One way was through the introduction of a new protocol called &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/CORS&quot; rel=&quot;noopener&quot;&gt;Cross
Origin Resource Sharing (CORS)&lt;/a&gt;
whose purpose is to make sure that the server allows sharing a resource with a
given origin. The other way is by implicitly removing direct script access to
cross-origin resources while preserving backward compatibility. Such
cross-origin resources are called &amp;quot;opaque&amp;quot; resources. For example, this is why
manipulating the pixels of a cross-origin image via &lt;code&gt;CanvasRenderingContext2D&lt;/code&gt;
fails unless CORS is applied to the image.&lt;/p&gt;
&lt;p&gt;All these policy decisions are happening within a browsing context group.&lt;/p&gt;
&lt;img alt=&quot;Browsing Context Group&quot; decoding=&quot;async&quot; height=&quot;469&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/z1Gr4mmJMo383dR9FQUk.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;For a long time, the combination of CORS and opaque resources was enough to make
browsers safe. Sometimes edge cases (such as &lt;a href=&quot;https://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/&quot; rel=&quot;noopener&quot;&gt;JSON
vulnerabilities&lt;/a&gt;)
were discovered, and needed to be patched, but overall the principle of not
allowing direct read access to the raw bytes of cross-origin resources was
successful.&lt;/p&gt;
&lt;p&gt;This all changed with
&lt;a href=&quot;https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)&quot; rel=&quot;noopener&quot;&gt;Spectre&lt;/a&gt;, which
makes any data that is loaded to the same browsing context group as your code
potentially readable. By measuring the time certain operations take, attackers
can guess the contents of the CPU caches, and through that, the contents of the
process&#39; memory. Such timing attacks are possible with low-granularity timers
that exist in the platform, but can be sped up with high-granularity timers,
both explicit (like &lt;code&gt;performance.now()&lt;/code&gt;) and implicit (like
&lt;code&gt;SharedArrayBuffer&lt;/code&gt;s). If &lt;code&gt;evil.com&lt;/code&gt; embeds a cross-origin image, they can use a
Spectre attack to read its pixel data, which makes protections relying on
&amp;quot;opaqueness&amp;quot; ineffective.&lt;/p&gt;
&lt;img alt=&quot;Spectr&quot; decoding=&quot;async&quot; height=&quot;500&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/wN636enwMtBrrOfhzEoq.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;Ideally, all cross-origin requests should be explicitly vetted by the server
that owns the resource. If vetting is not provided by
the resource-owning server, then the data will never make it into the browsing
context group of an evil actor, and therefore will stay out of reach of any Spectre
attacks a web page could carry out. We call it a cross-origin isolated state.
This is exactly what COOP+COEP is about.&lt;/p&gt;
&lt;p&gt;Under a cross-origin isolated state, the requesting site is considered less
dangerous and this unlocks powerful features such as &lt;code&gt;SharedArrayBuffer&lt;/code&gt;,
&lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt; and &lt;a href=&quot;https://www.w3.org/TR/hr-time/&quot; rel=&quot;noopener&quot;&gt;high resolution
timers&lt;/a&gt; with better precision which could
otherwise be used for Spectre-like attacks. It also prevents modifying
&lt;code&gt;document.domain&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;coep&quot;&gt;Cross Origin Embedder Policy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#coep&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://wicg.github.io/cross-origin-embedder-policy/&quot; rel=&quot;noopener&quot;&gt;Cross Origin Embedder
Policy (COEP)&lt;/a&gt; prevents a
document from loading any cross-origin resources that don&#39;t explicitly grant
the document permission (using CORP or CORS). With this feature, you can declare
that a document cannot load such resources.&lt;/p&gt;
&lt;img alt=&quot;How COEP works&quot; decoding=&quot;async&quot; height=&quot;410&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/MAhaVZdShm8tRntWieU4.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;To activate this policy, append the following HTTP header to the document:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Embedder-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;require-corp&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;code&gt;require-corp&lt;/code&gt; keyword is the only accepted value for COEP. This enforces
the policy that the document can only load resources from the same origin, or
resources explicitly marked as loadable from another origin.&lt;/p&gt;
&lt;p&gt;For resources to be loadable from another origin, they need to support either
Cross Origin Resource Sharing (CORS) or Cross Origin Resource Policy (CORP).&lt;/p&gt;
&lt;h3 id=&quot;cors&quot;&gt;Cross Origin Resource Sharing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#cors&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If a cross origin resource supports &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/CORS&quot; rel=&quot;noopener&quot;&gt;Cross Origin Resource Sharing
(CORS)&lt;/a&gt;, you may use the
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTML/Attributes/crossorigin&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;crossorigin&lt;/code&gt;
attribute&lt;/a&gt;
to load it to your web page without being blocked by COEP.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://third-party.example.com/image.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;crossorigin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;For example, if this image resource is served with CORS headers, use the
&lt;code&gt;crossorigin&lt;/code&gt; attribute so that the request to fetch the resource will use &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Request/mode&quot; rel=&quot;noopener&quot;&gt;CORS
mode&lt;/a&gt;. This also
prevents the image from being loaded unless it sets CORS headers.&lt;/p&gt;
&lt;p&gt;Similarly, you may fetch cross origin data through the &lt;code&gt;fetch()&lt;/code&gt; method, which
doesn&#39;t require special handling as long as the server responds with &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/CORS#The_HTTP_response_headers&quot; rel=&quot;noopener&quot;&gt;the right
HTTP
headers&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;corp&quot;&gt;Cross Origin Resource Policy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#corp&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)&quot; rel=&quot;noopener&quot;&gt;Cross Origin Resource Policy
(CORP)&lt;/a&gt;
was originally introduced as an opt-in to protect your resources from being
loaded by another origin. In the context of COEP, CORP can specify the resource
owner&#39;s policy for who can load a resource.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Cross-Origin-Resource-Policy&lt;/code&gt; header takes three possible values:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Resource-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-site&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Resources that are marked &lt;code&gt;same-site&lt;/code&gt; can only be loaded from the same site.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Resource-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Resources that are marked &lt;code&gt;same-origin&lt;/code&gt; can only be loaded from the same origin.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Resource-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;cross-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Resources that are marked &lt;code&gt;cross-origin&lt;/code&gt; can be loaded by any website. (&lt;a href=&quot;https://mikewest.github.io/corpp/#integration-fetch&quot; rel=&quot;noopener&quot;&gt;This
value&lt;/a&gt; was added to the
CORP spec along with COEP.)&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Once you add the COEP header, you won&#39;t be able to bypass the restriction by using service workers. If the document is protected by a COEP header, the policy is respected before the response enters the document process, or before it enters the service worker that is controlling the document. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;coop&quot;&gt;Cross Origin Opener Policy &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#coop&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/whatwg/html/pull/5334/files&quot; rel=&quot;noopener&quot;&gt;Cross Origin Opener Policy
(COOP)&lt;/a&gt; allows you to ensure
that a top-level window is isolated from other documents by putting them in a
different browsing context group, so that they cannot directly interact with the
top-level window. For example, if a document with COOP opens a pop-up, its
&lt;code&gt;window.opener&lt;/code&gt; property will be &lt;code&gt;null&lt;/code&gt;. Also, the &lt;code&gt;.closed&lt;/code&gt; property of the
opener&#39;s reference to it will return &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;img alt=&quot;COOP&quot; decoding=&quot;async&quot; height=&quot;452&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/eUu74n3GIlK1fj9ACxF8.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The &lt;code&gt;Cross-Origin-Opener-Policy&lt;/code&gt; header takes three possible values:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Documents that are marked &lt;code&gt;same-origin&lt;/code&gt; can share the same browsing context
group with same-origin documents that are also explicitly marked &lt;code&gt;same-origin&lt;/code&gt;.&lt;/p&gt;
&lt;img alt=&quot;COOP&quot; decoding=&quot;async&quot; height=&quot;507&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/he8FaRE2ef67lamrFG60.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin-allow-popups&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;A top-level document with &lt;code&gt;same-origin-allow-popups&lt;/code&gt; retains references to any
of its popups which either don&#39;t set COOP or which opt out of isolation by
setting a COOP of &lt;code&gt;unsafe-none&lt;/code&gt;.&lt;/p&gt;
&lt;img alt=&quot;COOP&quot; decoding=&quot;async&quot; height=&quot;537&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/AJdm6vFq4fQXUWOTFeFa.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;unsafe-none&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;unsafe-none&lt;/code&gt; is the default and allows the document to be added to its opener&#39;s
browsing context group unless the opener itself has a COOP of &lt;code&gt;same-origin&lt;/code&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; The &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Window/open#Window_features&quot;&gt;&lt;code&gt;noopener&lt;/code&gt;&lt;/a&gt; attribute has a similar effect to what you would expect from COOP except that it works only from the opener side. (You can&#39;t disassociate your window when it is opened by a third party.) When you attach &lt;code&gt;noopener&lt;/code&gt; by doing something such as &lt;code&gt;window.open(url, &#39;_blank&#39;, &#39;noopener&#39;)&lt;/code&gt; or &lt;code&gt;&amp;lt;a target=&amp;quot;_blank&amp;quot; rel=&amp;quot;noopener&amp;quot;&amp;gt;&lt;/code&gt;, you can deliberately disassociate your window from the opened window.  While &lt;code&gt;noopener&lt;/code&gt; can be replaced by COOP, it&#39;s still useful for when you want to protect your website in browsers that don&#39;t support COOP. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you want guaranteed access to powerful features like &lt;code&gt;SharedArrayBuffer&lt;/code&gt;,
&lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt; or &lt;a href=&quot;https://www.w3.org/TR/hr-time/&quot; rel=&quot;noopener&quot;&gt;high resolution
timers&lt;/a&gt; with better precision, just remember
that your document needs to use both COEP with the value of &lt;code&gt;require-corp&lt;/code&gt; and
COOP with the value of &lt;code&gt;same-origin&lt;/code&gt;. In the absence of either, the browser will
not guarantee sufficient isolation to safely enable those powerful features. You
can determine your page&#39;s situation by checking if
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/crossOriginIsolated&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;self.crossOriginIsolated&lt;/code&gt;&lt;/a&gt;
returns &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Learn the steps to implement this at &lt;a href=&quot;https://web.dev/coop-coep/&quot;&gt;Making your website &amp;quot;cross-origin
isolated&amp;quot; using COOP and COEP&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/why-coop-coep/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.google.com/document/d/1zDlfvfTJ_9e8Jdc8ehuV4zMEu9ySMCiTGMS9y0GU92k/edit&quot; rel=&quot;noopener&quot;&gt;COOP and COEP
explained&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/Planned_changes&quot; rel=&quot;noopener&quot;&gt;Planned changes to shared memory - JavaScript |
MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author><author>
      <name>Domenic Denicola</name>
    </author>
  </entry>
  
  <entry>
    <title>Understanding &quot;same-site&quot; and &quot;same-origin&quot;</title>
    <link href="https://web.dev/same-site-same-origin/"/>
    <updated>2020-04-15T00:00:00Z</updated>
    <id>https://web.dev/same-site-same-origin/</id>
    <content type="html" mode="escaped">&lt;p&gt;&amp;quot;same-site&amp;quot; and &amp;quot;same-origin&amp;quot; are frequently cited but often misunderstood
terms. For example, they are mentioned in the context of page transitions,
&lt;code&gt;fetch()&lt;/code&gt; requests, cookies, opening popups, embedded resources, and
iframes.&lt;/p&gt;
&lt;h2 id=&quot;origin&quot;&gt;Origin &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/same-site-same-origin/#origin&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;img alt=&quot;Origin&quot; decoding=&quot;async&quot; height=&quot;130&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/Zn352nyD12uz6ORlLZiT.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;&amp;quot;Origin&amp;quot; is a combination of a
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#Scheme_or_protocol&quot; rel=&quot;noopener&quot;&gt;scheme&lt;/a&gt;
(also known as the
&lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/Protocol&quot; rel=&quot;noopener&quot;&gt;protocol&lt;/a&gt;, for
example &lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/HTTP&quot; rel=&quot;noopener&quot;&gt;HTTP&lt;/a&gt; or
&lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/HTTPS&quot; rel=&quot;noopener&quot;&gt;HTTPS&lt;/a&gt;),
&lt;a href=&quot;https://en.wikipedia.org/wiki/Hostname&quot; rel=&quot;noopener&quot;&gt;hostname&lt;/a&gt;, and
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#Port&quot; rel=&quot;noopener&quot;&gt;port&lt;/a&gt;
(if specified). For example, given a URL of &lt;code&gt;https://www.example.com:443/foo&lt;/code&gt; ,
the &amp;quot;origin&amp;quot; is &lt;code&gt;https://www.example.com:443&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;same-origin-and-cross-origin&quot;&gt;&amp;quot;same-origin&amp;quot; and &amp;quot;cross-origin&amp;quot; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/same-site-same-origin/#same-origin-and-cross-origin&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Websites that have the combination of the same scheme, hostname, and port are
considered &amp;quot;same-origin&amp;quot;. Everything else is considered &amp;quot;cross-origin&amp;quot;.&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Origin A&lt;/th&gt;
        &lt;th&gt;Origin B&lt;/th&gt;
        &lt;th&gt;Explanation of whether Origin A and B are &quot;same-origin&quot; or &quot;cross-origin&quot;&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td rowspan=&quot;7&quot;&gt;https://www.example.com:443&lt;/td&gt;
        &lt;td&gt;https://&lt;strong&gt;www.evil.com&lt;/strong&gt;:443&lt;/td&gt;
        &lt;td&gt;cross-origin: different domains&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;https://&lt;strong&gt;example.com&lt;/strong&gt;:443&lt;/td&gt;
        &lt;td&gt;cross-origin: different subdomains&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;https://&lt;strong&gt;login&lt;/strong&gt;.example.com:443&lt;/td&gt;
        &lt;td&gt;cross-origin: different subdomains&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;http&lt;/strong&gt;://www.example.com:443&lt;/td&gt;
        &lt;td&gt;cross-origin: different schemes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;https://www.example.com:&lt;strong&gt;80&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;cross-origin: different ports&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;https://www.example.com:443&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;same-origin: exact match&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;https://www.example.com&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;same-origin: implicit port number (443) matches&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;site&quot;&gt;Site &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/same-site-same-origin/#site&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  The definition of &amp;quot;site&amp;quot; has evolved and &lt;a href=&quot;https://github.com/whatwg/url/issues/448&quot;&gt;the spec says it includes the scheme&lt;/a&gt;. This change has been included from late 2019. This effectively changes the definition of &amp;quot;same-site&amp;quot; and &amp;quot;cross-site&amp;quot; as well. What has been called &amp;quot;&lt;a href=&quot;https://web.dev/schemeful-samesite/&quot;&gt;schemeful same-site&lt;/a&gt;&amp;quot; is now &amp;quot;same-site&amp;quot; and a new concept of &amp;quot;schemeless same-site&amp;quot; emerged. Read on to learn more.  &lt;/div&gt;&lt;/aside&gt;
&lt;img alt=&quot;Site (TLD+1)&quot; decoding=&quot;async&quot; height=&quot;165&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/GbXtpqme6JcvlxpWRcYf.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/TLD&quot; rel=&quot;noopener&quot;&gt;Top-level domains (TLDs)&lt;/a&gt; such
as &lt;code&gt;.com&lt;/code&gt; and &lt;code&gt;.org&lt;/code&gt; are listed in the &lt;a href=&quot;https://www.iana.org/domains/root/db&quot; rel=&quot;noopener&quot;&gt;Root Zone
Database&lt;/a&gt;. In the example above, &amp;quot;site&amp;quot; is
the combination of the
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Identifying_resources_on_the_Web#Scheme_or_protocol&quot; rel=&quot;noopener&quot;&gt;scheme&lt;/a&gt;,
the &lt;a href=&quot;https://developer.mozilla.org/docs/Glossary/TLD&quot; rel=&quot;noopener&quot;&gt;TLD&lt;/a&gt; and the part of the
domain just before it (We call it TLD+1). For example, given a URL of
&lt;code&gt;https://www.example.com:443/foo&lt;/code&gt; , the &amp;quot;site&amp;quot; is &lt;code&gt;https://example.com&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;public-suffix-list-and-etld&quot;&gt;Public Suffix List and eTLD &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/same-site-same-origin/#public-suffix-list-and-etld&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For domains that include things such as &lt;code&gt;.co.jp&lt;/code&gt; or &lt;code&gt;.github.io&lt;/code&gt;, just using
&lt;code&gt;.jp&lt;/code&gt; or &lt;code&gt;.io&lt;/code&gt; is not granular enough to identify the &amp;quot;site&amp;quot;. There is no way to
algorithmically determine the level of registrable domains for a particular TLD.
That&#39;s why a list of public suffixes defined in the &lt;a href=&quot;https://wiki.mozilla.org/Public_Suffix_List&quot; rel=&quot;noopener&quot;&gt;Public Suffix
List&lt;/a&gt; was created. These public
suffixes are also called &lt;em&gt;effective TLDs (eTLDs)&lt;/em&gt;. The list of eTLDs is
maintained at &lt;a href=&quot;https://publicsuffix.org/list/&quot; rel=&quot;noopener&quot;&gt;publicsuffix.org/list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To identify the &amp;quot;site&amp;quot; part of a domain that includes an eTLD, apply the same
practice as the example with &lt;code&gt;.com&lt;/code&gt;. Taking
&lt;code&gt;https://www.project.github.io:443/foo&lt;/code&gt; as an example, the scheme is &lt;code&gt;https&lt;/code&gt;,
the eTLD is &lt;code&gt;.github.io&lt;/code&gt; and the eTLD+1 is &lt;code&gt;project.github.io&lt;/code&gt;, so
&lt;code&gt;https://project.github.io&lt;/code&gt; is considered the &amp;quot;site&amp;quot; for this URL.&lt;/p&gt;
&lt;img alt=&quot;Site (eTLD+1)&quot; decoding=&quot;async&quot; height=&quot;157&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/7ihtYJeEPX4epAe37onN.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;h3 id=&quot;same-site-cross-site&quot;&gt;&amp;quot;same-site&amp;quot; and &amp;quot;cross-site&amp;quot; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/same-site-same-origin/#same-site-cross-site&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Websites that have the same scheme and the same eTLD+1 are considered
&amp;quot;same-site&amp;quot;. Websites that have a different scheme or a different eTLD+1 are
&amp;quot;cross-site&amp;quot;.&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Origin A&lt;/th&gt;
        &lt;th&gt;Origin B&lt;/th&gt;
        &lt;th&gt;Explanation of whether Origin A and B are &quot;same-site&quot; or &quot;cross-site&quot;&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td rowspan=&quot;6&quot;&gt;https://www.example.com:443&lt;/td&gt;
        &lt;td&gt;https://&lt;strong&gt;www.evil.com&lt;/strong&gt;:443&lt;/td&gt;
        &lt;td&gt;cross-site: different domains&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;https://&lt;strong&gt;login&lt;/strong&gt;.example.com:443&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;same-site: different subdomains don&#39;t matter&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;http&lt;/strong&gt;://www.example.com:443&lt;/td&gt;
        &lt;td&gt;cross-site: different schemes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;https://www.example.com:&lt;strong&gt;80&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;same-site: different ports don&#39;t matter&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;https://www.example.com:443&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;same-site: exact match&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;https://www.example.com&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;same-site: ports don&#39;t matter&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;h3 id=&quot;schemeless-same-site&quot;&gt;&amp;quot;schemeless same-site&amp;quot; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/same-site-same-origin/#schemeless-same-site&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;img alt=&quot;schemeless same-site&quot; decoding=&quot;async&quot; height=&quot;123&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/G2VfM8BA5Q5LTaz22Puu.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;p&gt;The definition of &amp;quot;same-site&amp;quot; evolved to consider the URL scheme as part of the
site in order to prevent HTTP being used as &lt;a href=&quot;https://tools.ietf.org/html/draft-west-cookie-incrementalism-01#page-8&quot; rel=&quot;noopener&quot;&gt;a weak
channel&lt;/a&gt;.
The older concept of &amp;quot;same-site&amp;quot; without scheme comparison is now called
&amp;quot;schemeless same-site&amp;quot;. For example, &lt;code&gt;http://www.example.com&lt;/code&gt; and
&lt;code&gt;https://www.example.com&lt;/code&gt; are considered schemeless same-site but not same-site,
because only the eTLD+1 part matters and the scheme is not taken into account.&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;Origin A&lt;/th&gt;
        &lt;th&gt;Origin B&lt;/th&gt;
        &lt;th&gt;Explanation of whether Origin A and B are &quot;schemeless same-site&quot;&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td rowspan=&quot;6&quot;&gt;https://www.example.com:443&lt;/td&gt;
        &lt;td&gt;https://&lt;strong&gt;www.evil.com&lt;/strong&gt;:443&lt;/td&gt;
        &lt;td&gt;cross-site: different domains&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;https://&lt;strong&gt;login&lt;/strong&gt;.example.com:443&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;schemeless same-site: different subdomains don&#39;t matter&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;http&lt;/strong&gt;://www.example.com:443&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;schemeless same-site: different schemes don&#39;t matter&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;https://www.example.com:&lt;strong&gt;80&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;schemeless same-site: different ports don&#39;t matter&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;https://www.example.com:443&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;schemeless same-site: exact match&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;&lt;strong&gt;https://www.example.com&lt;/strong&gt;&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;schemeless same-site: ports don&#39;t matter&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;how-to-check-if-a-request-is-same-site,-same-origin,-or-cross-site&quot;&gt;How to check if a request is &amp;quot;same-site&amp;quot;, &amp;quot;same-origin&amp;quot;, or &amp;quot;cross-site&amp;quot; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/same-site-same-origin/#how-to-check-if-a-request-is-same-site,-same-origin,-or-cross-site&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All modern browsers (Safari support &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=238265&quot; rel=&quot;noopener&quot;&gt;landing
soon&lt;/a&gt;) send requests along with
a &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Headers/Sec-Fetch-Site&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Sec-Fetch-Site&lt;/code&gt; HTTP
header&lt;/a&gt;. The
header has one of the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cross-site&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;same-site&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;same-origin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;none&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  &lt;code&gt;same-site&lt;/code&gt; here means schemeful same-site, rather than the old schemeless same-site.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;By examining the value of &lt;code&gt;Sec-Fetch-Site&lt;/code&gt;, you can determine if the request is
&amp;quot;same-site&amp;quot;, &amp;quot;same-origin&amp;quot;, or &amp;quot;cross-site&amp;quot;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  You can reasonably trust the value of &lt;code&gt;Sec-Fetch-Site&lt;/code&gt; header because: &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/fetch-metadata/#sec-prefix&quot;&gt;HTTP headers starting with &lt;code&gt;Sec-&lt;/code&gt; can not be modified by JavaScript&lt;/a&gt;.&lt;/li&gt; &lt;li&gt;These headers are always set by the browser.&lt;/li&gt; &lt;/ul&gt;  Even if a server receives a manipulated value for the &lt;code&gt;Sec-Fetch-Site&lt;/code&gt; header, sent by a random HTTP client, no user or browser will be harmed by breaking the same-origin policy.  &lt;/div&gt;&lt;/aside&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Making your website &quot;cross-origin isolated&quot; using COOP and COEP</title>
    <link href="https://web.dev/coop-coep/"/>
    <updated>2020-04-13T00:00:00Z</updated>
    <id>https://web.dev/coop-coep/</id>
    <content type="html" mode="escaped">&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  &lt;code&gt;SharedArrayBuffer&lt;/code&gt; on Chrome desktop requires cross-origin isolation starting from Chrome 92. Learn more at &lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/&quot;&gt;SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome 92&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;&lt;strong&gt;Updates&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;June 21, 2022&lt;/strong&gt;: Worker scripts also need care when cross-origin isolation
is enabled. Added some explanations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aug 5, 2021&lt;/strong&gt;: JS Self-Profiling API has been mentioned as one of APIs that
require cross-origin isolation, but reflecting &lt;a href=&quot;https://github.com/shhnjk/shhnjk.github.io/tree/main/investigations/js-self-profiling#conclusion&quot; rel=&quot;noopener&quot;&gt;recent change of the
direction&lt;/a&gt;,
it&#39;s removed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;May 6, 2021&lt;/strong&gt;: Based on feedback and issues reported we&#39;ve decided to adjust
the timeline for &lt;code&gt;SharedArrayBuffer&lt;/code&gt; usage in none cross-origin isolated sites
to be restricted in Chrome M92.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;April 16, 2021&lt;/strong&gt;: Added notes about &lt;a href=&quot;https://github.com/mikewest/credentiallessness/&quot; rel=&quot;noopener&quot;&gt;a new COEP credentialless
mode&lt;/a&gt; and &lt;a href=&quot;https://github.com/whatwg/html/issues/6364&quot; rel=&quot;noopener&quot;&gt;COOP
same-origin-allow-popups to be a relaxed
condition&lt;/a&gt; for cross-origin
isolation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;March 5, 2021&lt;/strong&gt;: Removed limitations for &lt;code&gt;SharedArrayBuffer&lt;/code&gt;,
&lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt;, and debugging functionalities,
which are now fully enabled in Chrome 89. Added upcoming capabilities,
&lt;code&gt;performance.now()&lt;/code&gt; and &lt;code&gt;performance.timeOrigin&lt;/code&gt;, that will have higher
precision.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;February 19, 2021&lt;/strong&gt;: Added a note about feature policy
&lt;code&gt;allow=&amp;quot;cross-origin-isolated&amp;quot;&lt;/code&gt; and debugging functionality on DevTools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;October 15, 2020&lt;/strong&gt;: &lt;code&gt;self.crossOriginIsolated&lt;/code&gt; is available from Chrome 87.
Reflecting that, &lt;code&gt;document.domain&lt;/code&gt; is immutable when
&lt;code&gt;self.crossOriginIsolated&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;.
&lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt; is ending its origin trial and
is enabled by default in Chrome 89. Shared Array Buffer on Android Chrome will
be available from Chrome 88.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;XLNJYhjA-0c&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;p&gt;Some web APIs increase the risk of side-channel attacks like Spectre. To
mitigate that risk, browsers offer an opt-in-based isolated environment called
cross-origin isolated. With a cross-origin isolated state, the webpage will be
able to use privileged features including:&lt;/p&gt;
&lt;div&gt;
  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th&gt;API&lt;/th&gt;
        &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;a href=&quot;https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer&quot;&gt;
          &lt;code&gt;SharedArrayBuffer&lt;/code&gt;&lt;/a&gt;
        &lt;/td&gt;
        &lt;td&gt;
          Required for WebAssembly threads. This is available from Android
          Chrome 88. Desktop version is currently enabled by default with the
          help of &lt;a href=&quot;https://www.chromium.org/Home/chromium-security/site-isolation&quot;&gt;
          Site Isolation&lt;/a&gt;, but will require the cross-origin isolated state
          and &lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/&quot;&gt;
          will be disabled by default in Chrome 92&lt;/a&gt;.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;a href=&quot;https://web.dev/monitor-total-page-memory-usage/&quot;&gt;
          &lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt;&lt;/a&gt;
        &lt;/td&gt;
        &lt;td&gt;
          Available from Chrome 89.
        &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;
          &lt;a href=&quot;https://crbug.com/1180178&quot;&gt;
          &lt;code&gt;performance.now()&lt;/code&gt;, &lt;code&gt;performance.timeOrigin&lt;/code&gt;&lt;/a&gt;
        &lt;/td&gt;
        &lt;td&gt;
          Currently available in many browsers with the resolution limited to
          100 microseconds or higher. With cross-origin isolation, the
          resolution can be 5 microseconds or higher.
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
    &lt;caption&gt;Features that will be available behind cross-origin isolated
    state.&lt;/caption&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The cross-origin isolated state also prevents modifications of
&lt;code&gt;document.domain&lt;/code&gt;. (Being able to alter &lt;code&gt;document.domain&lt;/code&gt; allows communication
between same-site documents and has been considered a loophole in the
same-origin policy.)&lt;/p&gt;
&lt;p&gt;To opt in to a cross-origin isolated state, you need to send the following
HTTP headers on the main document:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-http&quot;&gt;&lt;code class=&quot;language-http&quot;&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Embedder-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;require-corp&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token header&quot;&gt;&lt;span class=&quot;token header-name keyword&quot;&gt;Cross-Origin-Opener-Policy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token header-value&quot;&gt;same-origin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;These headers instruct the browser to block loading of resources or iframes
which haven&#39;t opted into being loaded by cross-origin documents, and prevent
cross-origin windows from directly interacting with your document. This also
means those resources being loaded cross-origin require opt-ins.&lt;/p&gt;
&lt;p&gt;You can determine whether a web page is in a cross-origin isolated state by
examining
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/crossOriginIsolated&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;self.crossOriginIsolated&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This article shows how to use these new headers. In &lt;a href=&quot;https://web.dev/why-coop-coep&quot;&gt;a follow-up
article&lt;/a&gt; I will provide more background and context.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  This article is aimed at those who would like to get their websites ready for using &lt;code&gt;SharedArrayBuffer&lt;/code&gt;, WebAssembly threads, &lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt; or high resolution timer with better precision in a more robust manner across browser platforms.  &lt;/div&gt;&lt;/aside&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; This article uses many similar-sounding terminologies. To make things clearer, let&#39;s define them first:  * &lt;a href=&quot;https://wicg.github.io/cross-origin-embedder-policy/&quot;&gt;COEP: Cross Origin Embedder Policy&lt;/a&gt; * &lt;a href=&quot;https://github.com/whatwg/html/pull/5334/files&quot;&gt;COOP: Cross Origin Opener Policy&lt;/a&gt; * &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP)&quot;&gt;CORP: Cross Origin Resource Policy&lt;/a&gt; * &lt;a href=&quot;https://developer.mozilla.org/docs/Web/HTTP/CORS&quot;&gt;CORS: Cross Origin Resource Sharing&lt;/a&gt; * &lt;a href=&quot;https://www.chromium.org/Home/chromium-security/corb-for-developers&quot;&gt;CORB: Cross Origin Read Blocking&lt;/a&gt; &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;deploy-coop-and-coep-to-make-your-website-cross-origin-isolated&quot;&gt;Deploy COOP and COEP to make your website cross-origin isolated &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#deploy-coop-and-coep-to-make-your-website-cross-origin-isolated&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; Learn practical steps to enable cross-origin isolation at &lt;a href=&quot;https://web.dev/cross-origin-isolation-guide/&quot;&gt;A guide to enable cross-origin isolation&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;integrate-coop-and-coep&quot;&gt;Integrate COOP and COEP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#integrate-coop-and-coep&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;h4 id=&quot;1-set-the-cross-origin-opener-policy-same-origin-header-on-the-top-level-document&quot;&gt;1. Set the &lt;code&gt;Cross-Origin-Opener-Policy: same-origin&lt;/code&gt; header on the top-level document &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#1-set-the-cross-origin-opener-policy-same-origin-header-on-the-top-level-document&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;By enabling &lt;code&gt;COOP: same-origin&lt;/code&gt; on a top-level document, windows with the same
origin, and windows opened from the document, will have a separate browsing
context group unless they are in the same origin with the same COOP setting.
Thus, isolation is enforced for opened windows and mutual communication between
both windows is disabled.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  This will break integrations that require cross-origin window interactions such as OAuth and payments. To mitigate this problem, we are &lt;a href=&quot;https://github.com/whatwg/html/issues/6364&quot;&gt;exploring relaxing the condition&lt;/a&gt; to enable cross-origin isolation to &lt;code&gt;Cross-Origin-Opener-Policy: same-origin-allow-popups&lt;/code&gt;. This way the communication with the window opened by itself will be possible.  If you want to enable cross-origin isolation but are blocked by this issue, we recommend &lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/#origin-trial&quot;&gt;registering for an origin trial&lt;/a&gt; and waiting until the new condition is available. We are not planning to terminate the origin trial until this issue is safely resolved.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;A browsing context group is a set of windows that can reference each other. For
example, a top-level document and its child documents embedded via &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;.
If a website (&lt;code&gt;https://a.example&lt;/code&gt;) opens a popup window (&lt;code&gt;https://b.example&lt;/code&gt;),
the opener window and the popup window share the same browsing context, therefore
they have access to each other via DOM APIs such as &lt;code&gt;window.opener&lt;/code&gt;.&lt;/p&gt;
&lt;img alt=&quot;Browsing Context Group&quot; decoding=&quot;async&quot; height=&quot;469&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 470px) 470px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/g42eZMpIKNbUL0cN6yjC.png?auto=format&amp;w=940 940w&quot; width=&quot;470&quot; /&gt;
&lt;p&gt;You can check if the window opener and its openee are in separate browsing
context groups &lt;a href=&quot;https://web.dev/coop-coep/#devtools-coop&quot;&gt;from DevTools&lt;/a&gt;.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-quaternary-box-bg color-quaternary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewbox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Code brackets&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M9.41 16.59L8 18l-6-6 6-6 1.41 1.41L4.83 12l4.58 4.59zm5.18-9.18L16 6l6 6-6 6-1.41-1.41L19.17 12l-4.58-4.59z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; &lt;a href=&quot;https://cross-origin-isolation.glitch.me/coop&quot;&gt;See the impact of different COOP parameters&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h4 id=&quot;2-ensure-resources-have-corp-or-cors-enabled&quot;&gt;2. Ensure resources have CORP or CORS enabled &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#2-ensure-resources-have-corp-or-cors-enabled&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Make sure that all resources in the page are loaded with CORP or CORS HTTP
headers. This step is required for &lt;a href=&quot;https://web.dev/coop-coep/#enable-coep&quot;&gt;step four, enabling COEP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here is what you need to do depending on the nature of the resource:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the resource is expected to be loaded &lt;strong&gt;only from the same origin&lt;/strong&gt;, set
the &lt;code&gt;Cross-Origin-Resource-Policy: same-origin&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;If the resource is expected to be loaded &lt;strong&gt;only from the same site but cross
origin&lt;/strong&gt;, set the &lt;code&gt;Cross-Origin-Resource-Policy: same-site&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;If the resource is &lt;strong&gt;loaded from cross origin(s) under your control&lt;/strong&gt;, set the
&lt;code&gt;Cross-Origin-Resource-Policy: cross-origin&lt;/code&gt; header if possible.&lt;/li&gt;
&lt;li&gt;For cross origin resources that you have no control over:
&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;crossorigin&lt;/code&gt; attribute in the loading HTML tag if the resource is
served with CORS. (For example, &lt;code&gt;&amp;lt;img src=&amp;quot;***&amp;quot; crossorigin&amp;gt;&lt;/code&gt;.)&lt;/li&gt;
&lt;li&gt;Ask the owner of the resource to support either CORS or CORP.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;For iframes, follow the same principles above and set the
&lt;code&gt;Cross-Origin-Resource-Policy: cross-origin&lt;/code&gt; (or &lt;code&gt;same-site&lt;/code&gt;, &lt;code&gt;same-origin&lt;/code&gt;
depending on the context).&lt;/li&gt;
&lt;li&gt;Scripts loaded with a &lt;code&gt;WebWorker&lt;/code&gt; must be served from same-origin,
so you don&#39;t need a CORP or CORS headers.&lt;/li&gt;
&lt;li&gt;For a document or a worker served with &lt;code&gt;COEP: require-corp&lt;/code&gt;, cross-origin
subresources loaded without CORS must set the &lt;code&gt;Cross-Origin-Resource-Policy: cross-origin&lt;/code&gt; header to opt into being embedded. For example, this applies to
&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;, &lt;code&gt;importScripts&lt;/code&gt;, &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Gotchas&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  You can enable cross-origin isolation on a document embedded within an iframe by applying &lt;code&gt;allow=&amp;quot;cross-origin-isolated&amp;quot;&lt;/code&gt; permissions policy to the &lt;code&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt; tag and meeting the same conditions described in this document. Note that entire chain of the documents including parent frames and child frames must be cross-origin isolated as well.  &lt;/div&gt;&lt;/aside&gt;
&lt;aside class=&quot;aside flow color-secondary-box-text bg-secondary-box-bg&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Highlighter pen&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M10.22 9.49l-5.91 6c-.77.8-.7 2.05.08 2.85L.77 22h5.68l.74-.75c.78.81 1.95.86 2.73.05l5.96-6.05-5.66-5.76zm12.46-4l-2.82-2.87c-.78-.8-2.07-.84-2.84-.04l-5.75 5.85 5.66 5.75 5.69-5.78c.77-.81.83-2.11.06-2.91z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Key Term&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; It&#39;s important that you understand the difference between &amp;quot;same-site&amp;quot; and &amp;quot;same-origin&amp;quot;. Learn about the difference at &lt;a href=&quot;https://web.dev/same-site-same-origin&quot;&gt;Understanding same-site and same-origin&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h4 id=&quot;3-use-the-coep-report-only-http-header-to-assess-embedded-resources&quot;&gt;3. Use the COEP Report-Only HTTP header to assess embedded resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#3-use-the-coep-report-only-http-header-to-assess-embedded-resources&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Before fully enabling COEP, you can do a dry run by using the
&lt;code&gt;Cross-Origin-Embedder-Policy-Report-Only&lt;/code&gt; header to examine whether the policy
actually works. You will receive reports without blocking embedded content.&lt;/p&gt;
&lt;p&gt;Recursively apply this to &lt;strong&gt;all&lt;/strong&gt; documents including the top-level document,
iframes and worker scripts. For information on the Report-Only HTTP header, see
&lt;a href=&quot;https://web.dev/coop-coep/#observe-issues-using-the-reporting-api&quot;&gt;Observe issues using the Reporting
API&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;enable-coep&quot;&gt;4. Enable COEP &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#enable-coep&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Once you&#39;ve confirmed that everything works, and that all resources can be
successfully loaded, switch the &lt;code&gt;Cross-Origin-Embedder-Policy-Report-Only&lt;/code&gt;
header to the &lt;code&gt;Cross-Origin-Embedder-Policy&lt;/code&gt; header with the same value to all
documents including those that are embedded via iframes and worker scripts.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-quaternary-box-bg color-quaternary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewbox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Code brackets&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M9.41 16.59L8 18l-6-6 6-6 1.41 1.41L4.83 12l4.58 4.59zm5.18-9.18L16 6l6 6-6 6-1.41-1.41L19.17 12l-4.58-4.59z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; &lt;a href=&quot;https://cross-origin-isolation.glitch.me/coep&quot;&gt;See the impact of different COEP / CORP parameters&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; &lt;a href=&quot;https://squoosh.app/&quot;&gt;Squoosh&lt;/a&gt; (an image optimization PWA) &lt;a href=&quot;https://github.com/GoogleChromeLabs/squoosh/pull/829/files#diff-316f969413f2d9a065fcc08c7a5589c088dd1e21deebadccfc5a4372ac5e0cbbR22-R23&quot;&gt;now uses COOP / COEP&lt;/a&gt; to gain access to Wasm Threads (and Shared Array Buffer) as well on Android Chrome. &lt;/div&gt;&lt;/aside&gt;
&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  We&#39;ve been exploring ways to deploy &lt;code&gt;Cross-Origin-Resource-Policy&lt;/code&gt; at scale, as cross-origin isolation requires all subresources to explicitly opt-in. And we have come up with the idea of going in the opposite direction: &lt;a href=&quot;https://developer.chrome.com/blog/coep-credentialless-origin-trial/&quot;&gt;a new COEP &amp;quot;credentialless&amp;quot; mode&lt;/a&gt; that allows loading resources without the CORP header by stripping all their credentials. We hope this will lighten your burden of making sure the subresources are sending the &lt;code&gt;Cross-Origin-Resource-Policy&lt;/code&gt; header.  However, since &lt;code&gt;credentialless&lt;/code&gt; mode is available on Chrome from version 96 but not supported by any other browsers yet, some developers might find it challenging to deploy COOP or COEP. If you prefer not to enable cross-origin isolation yet, we recommend &lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/#origin-trial&quot;&gt;registering for an origin trial&lt;/a&gt; and waiting until &lt;code&gt;credentialless&lt;/code&gt; is available in more browsers.  &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;determine-whether-isolation-succeeded-with-selfcrossoriginisolated&quot;&gt;Determine whether isolation succeeded with &lt;code&gt;self.crossOriginIsolated&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#determine-whether-isolation-succeeded-with-selfcrossoriginisolated&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;self.crossOriginIsolated&lt;/code&gt; property returns &lt;code&gt;true&lt;/code&gt; when the web page is in a
cross-origin isolated state and all resources and windows are isolated within
the same browsing context group. You can use this API to determine whether you
have successfully isolated the browsing context group and gained access to
powerful features like &lt;code&gt;performance.measureUserAgentSpecificMemory()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;debug-issues-using-chrome-devtools&quot;&gt;Debug issues using Chrome DevTools &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#debug-issues-using-chrome-devtools&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;youtube&quot;&gt;  &lt;lite-youtube videoid=&quot;D5DLVo_TlEA&quot;&gt;  &lt;/lite-youtube&gt;&lt;/div&gt;
&lt;p&gt;For resources that are rendered on the screen such as images, it&#39;s fairly easy
to detect COEP issues because the request will be blocked and the page will
indicate a missing image. However, for resources that don&#39;t
necessarily have a visual impact, such as scripts or styles, COEP issues might
go unnoticed. For those, use the DevTools Network panel. If
there&#39;s an issue with COEP, you should see
&lt;code&gt;(blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)&lt;/code&gt; in the &lt;strong&gt;Status&lt;/strong&gt;
column.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;COEP issues in the Status column of the Network panel.&quot; decoding=&quot;async&quot; height=&quot;444&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/iGwe4M1EgHzKb2Tvt5bl.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;You can then click the entry to see more details.&lt;/p&gt;
&lt;figure&gt;
  &lt;img alt=&quot;Details of the COEP issue are shown in the Headers tab after clicking a network resource in the Network panel.&quot; decoding=&quot;async&quot; height=&quot;241&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/admin/1oTBjS9q8KGHWsWYGq1N.jpg?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;You can also determine the status of iframes and popup windows through the
&lt;strong&gt;Application&lt;/strong&gt; panel. Go to the &amp;quot;Frames&amp;quot; section on the left hand side and
expand &amp;quot;top&amp;quot; to see the breakdown of the resource structure.&lt;/p&gt;
&lt;span id=&quot;devtools-coep-iframe&quot;&gt;
You can check the iframe&#39;s status such as availability of `SharedArrayBuffer`,
etc.
&lt;/span&gt;
&lt;figure&gt;
&lt;img alt=&quot;Chrome DevTools iframe inspector&quot; decoding=&quot;async&quot; height=&quot;480&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9titfaieIs0gwSKnkL3S.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;span id=&quot;devtools-coop&quot;&gt;
You can also check the popup windows&#39;s status such as whether it&#39;s cross-origin
isolated.
&lt;/span&gt;
&lt;figure&gt;
&lt;img alt=&quot;Chrome DevTools popup window inspector&quot; decoding=&quot;async&quot; height=&quot;480&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/kKvPUo2ZODZu8byK7gTB.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;observe-issues-using-the-reporting-api&quot;&gt;Observe issues using the Reporting API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#observe-issues-using-the-reporting-api&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://web.dev/reporting-api&quot;&gt;Reporting API&lt;/a&gt; is another mechanism through which you can
detect various issues. You can configure the Reporting API to instruct your
users&#39; browser to send a report whenever COEP blocks the loading of a resource
or COOP isolates a pop-up window. Chrome has supported the Reporting API since
version 69 for a variety of uses including COEP and COOP.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  Are you already using the Reporting API with the &lt;code&gt;Report-To&lt;/code&gt; header? Chrome is transitioning to a new version of the Reporting API, which replaces &lt;code&gt;Report-To&lt;/code&gt; with &lt;code&gt;Reporting-Endpoints&lt;/code&gt;; consider migrating to the new version. Check out &lt;a href=&quot;https://web.dev/reporting-api-migration&quot;&gt;Migrate to Reporting API v1&lt;/a&gt; for details.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;To learn how to configure the Reporting API and set up a server to receive
reports, head over to &lt;a href=&quot;https://web.dev/reporting-api/#using-the-reporting-api&quot;&gt;Using the Reporting
API&lt;/a&gt;.&lt;/p&gt;
&lt;h4 id=&quot;example-coep-report&quot;&gt;Example COEP report &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#example-coep-report&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;An example &lt;a href=&quot;https://html.spec.whatwg.org/multipage/origin.html#coep-report-type&quot; rel=&quot;noopener&quot;&gt;COEP
report&lt;/a&gt;
payload when cross-origin resource is blocked looks like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;25101&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;blocked-url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://third-party-test.glitch.me/check.svg?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;blockedURL&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://third-party-test.glitch.me/check.svg?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;destination&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;image&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;disposition&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;enforce&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;corp&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;coep&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://cross-origin-isolation.glitch.me/?coep=require-corp&amp;amp;coop=same-origin&amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;user_agent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-bad-bg color-state-bad-text&quot;&gt;&lt;p class=&quot;cluster color-state-bad-text&quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; role=&quot;img&quot; aria-label=&quot;Error sign&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15v-2h2v2h-2zm0-10v6h2V7h-2z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Caution&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; &lt;code&gt;blocked-url&lt;/code&gt; is there for backward compatibility only and &lt;a href=&quot;https://github.com/whatwg/html/pull/5848&quot;&gt;will be removed eventually&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h4 id=&quot;example-coop-report&quot;&gt;Example COOP report &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#example-coop-report&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;An example &lt;a href=&quot;https://html.spec.whatwg.org/multipage/origin.html#reporting&quot; rel=&quot;noopener&quot;&gt;COOP
report&lt;/a&gt; payload
when a pop-up window is opened isolated looks like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;disposition&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;enforce&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;effectivePolicy&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;same-origin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;nextResponseURL&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://third-party-test.glitch.me/popup?report-only&amp;amp;coop=same-origin&amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;navigation-from-response&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;coop&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://cross-origin-isolation.glitch.me/coop?coop=same-origin&amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;user_agent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When different browsing context groups try to access each other (only on
&amp;quot;report-only&amp;quot; mode), COOP also sends a report. For example, a report when
&lt;code&gt;postMessage()&lt;/code&gt; is attempted would look like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;51785&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;columnNumber&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;disposition&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;reporting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;effectivePolicy&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;same-origin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;lineNumber&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;83&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;property&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;postMessage&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;sourceFile&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://cross-origin-isolation.glitch.me/popup.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;access-from-coop-page-to-openee&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;coop&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://cross-origin-isolation.glitch.me/coop?report-only&amp;amp;coop=same-origin&amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;user_agent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;51785&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;disposition&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;reporting&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;effectivePolicy&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;same-origin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;property&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;postMessage&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;access-to-coop-page-from-openee&quot;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;coop&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://cross-origin-isolation.glitch.me/coop?report-only&amp;amp;coop=same-origin&amp;amp;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token property&quot;&gt;&quot;user_agent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36&quot;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use a combination of COOP and COEP HTTP headers to opt a web page into a special
cross-origin isolated state. You will be able to examine
&lt;code&gt;self.crossOriginIsolated&lt;/code&gt; to determine whether a web page is in a cross-origin
isolated state.&lt;/p&gt;
&lt;p&gt;We&#39;ll keep this post updated as new features are made available to this
cross-origin isolated state, and further improvements are made to DevTools
around COOP and COEP.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/coop-coep/#resources&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/why-coop-coep/&quot;&gt;Why you need &amp;quot;cross-origin isolated&amp;quot; for powerful features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/cross-origin-isolation-guide/&quot;&gt;A guide to enable cross-origin isolation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/enabling-shared-array-buffer/&quot; rel=&quot;noopener&quot;&gt;SharedArrayBuffer updates in Android Chrome 88 and Desktop Chrome
92&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/monitor-total-page-memory-usage/&quot;&gt;Monitor your web page&#39;s total memory usage with
&lt;code&gt;measureUserAgentSpecificMemory()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Updates to the Web Payments APIs</title>
    <link href="https://web.dev/web-payments-updates/"/>
    <updated>2019-06-13T00:00:00Z</updated>
    <id>https://web.dev/web-payments-updates/</id>
    <content type="html" mode="escaped">&lt;p&gt;Web Payments have been publicly available in browsers since 2016. The core
feature—the &lt;a href=&quot;https://www.w3.org/TR/payment-request/&quot; rel=&quot;noopener&quot;&gt;Payment Request API&lt;/a&gt;—is
now available across multiple browsers: Chrome, Safari, Edge and soon Firefox.
If you&#39;re new to Web Payments take a look at the &lt;a href=&quot;https://developers.google.com/web/fundamentals/payments/?hl=en&quot; rel=&quot;noopener&quot;&gt;&amp;quot;Web Payments
Overview&amp;quot;&lt;/a&gt; to
get started.&lt;/p&gt;
&lt;p&gt;Since the launch of the Payment Request API and the &lt;a href=&quot;https://w3c.github.io/payment-handler/&quot; rel=&quot;noopener&quot;&gt;Payment Handler
API&lt;/a&gt;, there have been quite a few
changes made to their respective specifications. These changes won&#39;t break your
working code, but we recommend that you look out for them. This post summarizes
those updates and will continue accumulating those API changes.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; If you want to subscribe to further upcoming changes to Chrome&#39;s Web Payments implementation, join the &lt;a href=&quot;https://groups.google.com/a/chromium.org/forum/#!forum/paymentrequest&quot;&gt;Public Payment Request Announcements group&lt;/a&gt;.  Alternatively, join the &lt;a href=&quot;https://spectrum.chat/web-payments&quot;&gt;public Web Payments community&lt;/a&gt; for the same updates. You may ask questions there as well.  If you want to check older updates to Chrome, head over to &lt;a href=&quot;https://developer.chrome.com/blog/payment-request-updates/&quot;&gt;&amp;quot;Changes in the Payment Request API&amp;quot; article at Web Fundamentals&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;new-method-hasenrolledinstrument&quot;&gt;New method: &lt;code&gt;hasEnrolledInstrument()&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-updates/#new-method-hasenrolledinstrument&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the previous version of the Payment Request API, &lt;code&gt;canMakePayment()&lt;/code&gt; was used
to check for the user&#39;s presence of the user&#39;s payment instrument. In a recent
update to the spec, &lt;code&gt;canMakePayment()&lt;/code&gt; has been replaced with
&lt;a href=&quot;https://w3c.github.io/payment-request/#hasenrolledinstrument-method&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;hasEnrolledInstrument()&lt;/code&gt;&lt;/a&gt;
without changing its functionality.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://chromestatus.com/feature/5646573451083776&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;hasEnrolledInstrument()&lt;/code&gt;&lt;/a&gt;
method has &lt;a href=&quot;https://chromestatus.com/feature/5646573451083776&quot; rel=&quot;noopener&quot;&gt;consensus from all major browsers&lt;/a&gt;.
Chrome has implemented it in version 74 and both &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=197386&quot; rel=&quot;noopener&quot;&gt;Webkit&lt;/a&gt;
and &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1528663&quot; rel=&quot;noopener&quot;&gt;Gecko&lt;/a&gt; have tracking
bugs but have not yet implemented the method as of June 2019.&lt;/p&gt;
&lt;p&gt;To use the new &lt;code&gt;hasEnrolledInstrument()&lt;/code&gt; method, replace code that looks like
this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Checking for instrument presence.&lt;/span&gt;&lt;br /&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;canMakePayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleInstrumentPresence&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;With code that looks like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Checking for instrument presence.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hasEnrolledInstrument&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// hasEnrolledInstrument() is available.&lt;/span&gt;&lt;br /&gt;  request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasEnrolledInstrument&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleInstrumentPresence&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;canMakePayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleInstrumentPresence&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;canmakepayment-no-longer-checks-for-instrument-presence&quot;&gt;&lt;code&gt;canMakePayment()&lt;/code&gt; no longer checks for instrument presence &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-updates/#canmakepayment-no-longer-checks-for-instrument-presence&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Because &lt;code&gt;hasEnrolledInstrument()&lt;/code&gt; now handles checking for the user&#39;s payment
instrument,
&lt;a href=&quot;https://w3c.github.io/payment-request/#canmakepayment-method&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;canMakePayment()&lt;/code&gt;&lt;/a&gt;
has been updated to only check for payment app availability.&lt;/p&gt;
&lt;p&gt;This change to &lt;code&gt;canMakePayment()&lt;/code&gt; is bound to the implementation of
&lt;code&gt;hasEnrolledInstrument()&lt;/code&gt;. As of June 2019, it is implemented in Chrome 74 but
not in any other browsers. Be sure to check if the &lt;code&gt;hasEnrolledInstrument()&lt;/code&gt;
method is available in the user&#39;s browser before attempting to use it.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Checking for payment app availability without checking for instrument presence.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hasEnrolledInstrument&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// `canMakePayment()` behavior change corresponds to&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// `hasEnrolledInstrument()` availability.&lt;/span&gt;&lt;br /&gt;  request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;canMakePayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handlePaymentAppAvailable&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cannot check for payment app availability without checking for instrument presence.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;languagecode-removed-from-basic-card-payment-method&quot;&gt;&lt;code&gt;languageCode&lt;/code&gt; removed from &lt;code&gt;basic-card&lt;/code&gt; payment method &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-updates/#languagecode-removed-from-basic-card-payment-method&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;PaymentAddress.languageCode&lt;/code&gt; has been removed from the shipping addresses and
billing addresses for &lt;code&gt;basic-card&lt;/code&gt;. The billing addresses of other payment
methods (such as Google Pay) are not affected.&lt;/p&gt;
&lt;p&gt;This change has been implemented &lt;a href=&quot;https://chromestatus.com/feature/4992562146312192&quot; rel=&quot;noopener&quot;&gt;in Chrome 74, Firefox, and Safari&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;paymentrequestshow-now-takes-an-optional-detailspromise&quot;&gt;&lt;code&gt;PaymentRequest.show()&lt;/code&gt; now takes an optional &lt;code&gt;detailsPromise&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-updates/#paymentrequestshow-now-takes-an-optional-detailspromise&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://w3c.github.io/payment-request/#show-method&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequest.show()&lt;/code&gt;&lt;/a&gt;
allows a merchant to present a payment request UI before the final total is
known. The merchant has ten seconds to resolve the &lt;code&gt;detailsPromise&lt;/code&gt; before a
timeout. This feature is intended for a quick server-side roundtrip.&lt;/p&gt;
&lt;p&gt;This feature has shipped in Chrome 75 and Safari.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Not implemented in Chrome 74 and older.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// There&#39;s no way to feature-detect this, so check a few&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// older versions of Chrome that you&#39;re seeing hit your servers.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;Chrome&lt;span class=&quot;token escape&quot;&gt;\/&lt;/span&gt;&lt;span class=&quot;token group punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token group punctuation&quot;&gt;(&lt;/span&gt;6&lt;span class=&quot;token char-class&quot;&gt;&lt;span class=&quot;token char-class-punctuation punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token range&quot;&gt;0&lt;span class=&quot;token range-punctuation operator&quot;&gt;-&lt;/span&gt;9&lt;/span&gt;&lt;span class=&quot;token char-class-punctuation punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token group punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token alternation keyword&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;token group punctuation&quot;&gt;(&lt;/span&gt;7&lt;span class=&quot;token char-class&quot;&gt;&lt;span class=&quot;token char-class-punctuation punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token range&quot;&gt;0&lt;span class=&quot;token range-punctuation operator&quot;&gt;-&lt;/span&gt;4&lt;/span&gt;&lt;span class=&quot;token char-class-punctuation punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token group punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token group punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;userAgent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Supported in Chrome 75+.&lt;/span&gt;&lt;br /&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolveDetailsPromise&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rejectDetailsPromise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Find out the exact total amount and call&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// `resolveDetailsPromise(details)`.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Use a 3 second timeout as an example.&lt;/span&gt;&lt;br /&gt;  window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;resolveDetailsPromise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;details&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 3 seconds.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleResponse&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;handleError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;paymentrequesteventchangepaymentmethod&quot;&gt;&lt;code&gt;PaymentRequestEvent.changePaymentMethod()&lt;/code&gt; &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-updates/#paymentrequesteventchangepaymentmethod&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Payment Handler API feature
&lt;a href=&quot;https://chromestatus.com/feature/5698314223747072&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PaymentRequestEvent.changePaymentMethod()&lt;/code&gt;&lt;/a&gt;
allows payment handlers (e.g., Google Pay) to trigger the
&lt;a href=&quot;https://w3c.github.io/payment-request/#dom-paymentmethodchangeevent&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;onpaymentmethodchange&lt;/code&gt;&lt;/a&gt;
event handler. &lt;code&gt;changePaymentMethod()&lt;/code&gt; returns a promise that resolves to a
&lt;a href=&quot;https://w3c.github.io/payment-handler/#dom-paymentmethodchangeresponse&quot; rel=&quot;noopener&quot;&gt;merchant
response&lt;/a&gt;
with updated price information (e.g., tax recalculation).&lt;/p&gt;
&lt;p&gt;Both &lt;code&gt;PaymentRequestEvent.changePaymentMethod()&lt;/code&gt; and the &lt;code&gt;paymentmethodchange&lt;/code&gt;
event are available in Chrome 76 and Webkit has implemented the
&lt;a href=&quot;https://webkit.org/blog/9167/whats-new-in-the-payment-request-api-for-apple-pay/&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;paymentmethodchange&lt;/code&gt; event in its Technology
Preview&lt;/a&gt;.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// In service worker context, `self` is the global object.&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;paymentrequest&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;evt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;respondWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;confirmPaymentFunction&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; rejectPaymentFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;changePaymentMethod &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Not implemented in this version of Chrome.&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Notify merchant that the user selected a different payment method.&lt;/span&gt;&lt;br /&gt;    evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;changePaymentMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://paymentapp.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;US&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;responseFromMerchant&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;responseFromMerchant &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Merchant ignored the &#39;paymentmethodchange&#39; event.&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;handleResponseFromMerchant&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;responseFromMerchant&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token function&quot;&gt;handleError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Merchant example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;onpaymentmethodchange &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Feature not available in this browser.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;paymentmethodchange&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;evt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  evt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateWith&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;updateDetailsBasedOnPaymentMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;evt&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; paymentDetails&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; &lt;strong&gt;Try it yourself&lt;/strong&gt;! We&#39;ve put together &lt;a href=&quot;https://rsolomakhin.github.io/pr/apps/pmc/&quot;&gt;an example so you can experiment with this API&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;improved-local-development&quot;&gt;Improved local development &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-updates/#improved-local-development&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Chrome 76 adds two small improvements for developer productivity. If your local
development environment uses a self-signed certificate, you can now use the
&lt;code&gt;--ignore-certificate-errors&lt;/code&gt; command line flag to make Chrome allow Web
Payments APIs in your development environment. If you develop using a local web
server that does not support HTTPS, you can also use the
&lt;code&gt;--unsafely-treat-insecure-origin-as-secure=&amp;lt;origin&amp;gt;&lt;/code&gt; flag to make Chrome treat
the HTTP origin as HTTPS.&lt;/p&gt;
</content>
    <author>
      <name>Rouslan Solomakhin</name>
    </author><author>
      <name>Danyao Wang</name>
    </author><author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>How Payment Request API works</title>
    <link href="https://web.dev/how-payment-request-api-works/"/>
    <updated>2018-09-10T00:00:00Z</updated>
    <id>https://web.dev/how-payment-request-api-works/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;payment-request-api&quot;&gt;Payment Request API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-request-api-works/#payment-request-api&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When a customer tries to purchase something from your website, the site must ask
the customer to provide payment information and, optionally, other information
such as shipping preference. You can achieve this easily and quickly using the
&lt;a href=&quot;https://w3c.github.io/payment-request/&quot; rel=&quot;noopener&quot;&gt;Payment Request API (PR API)&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;basic-structure&quot;&gt;Basic structure &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-request-api-works/#basic-structure&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Constructing a &lt;code&gt;PaymentRequest&lt;/code&gt; object requires two parameters: &lt;em&gt;payment
methods&lt;/em&gt; and &lt;em&gt;payment details&lt;/em&gt;. In addition, a third &lt;em&gt;payment options&lt;/em&gt; parameter
is optional. A basic request could be created like this:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; request &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PaymentRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;paymentMethods&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; paymentDetails&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Let&#39;s look at how each parameter is built and used.&lt;/p&gt;
&lt;h3 id=&quot;payment-methods&quot;&gt;Payment methods &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-request-api-works/#payment-methods&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first parameter, &lt;em&gt;paymentMethods&lt;/em&gt;, is a list of supported payment methods in
an array variable. Each element in the array comprises two components,
&lt;code&gt;supportedMethods&lt;/code&gt; and, optionally, &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;supportedMethods&lt;/code&gt;, the merchant needs to specify a &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-1-provide-the-payment-method-identifier&quot;&gt;Payment Method
Identifier&lt;/a&gt;
such as &lt;code&gt;https://bobbucks.dev/pay&lt;/code&gt;. The existence and content of &lt;code&gt;data&lt;/code&gt; depends on
the content of &lt;code&gt;supportedMethods&lt;/code&gt; and payment app provider&#39;s design.&lt;/p&gt;
&lt;p&gt;Both pieces of information should be provided by the payment app provider.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Supported payment methods&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paymentMethods &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;supportedMethods&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://bobbucks.dev/pay&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Optional parameters defined by the payment app provider.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;payment-details&quot;&gt;Payment details &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-request-api-works/#payment-details&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The second parameter, &lt;em&gt;paymentDetails&lt;/em&gt;, is passed as an object and specifies
payment details for the transaction. It contains the required value &lt;code&gt;total&lt;/code&gt;,
which specifies the total amount due from the customer. This parameter can also
optionally list the purchased items.&lt;/p&gt;
&lt;p&gt;In the example below, the optional purchased items list (just one item, in this
case) is shown, as is the required total amount due. In both cases the currency
unit is specified with each individual amount.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paymentDetails &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;displayItems&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Anvil L/S Crew Neck - Grey M x1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;22.15&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Total due&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;USD&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;22.15&#39;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;check-whether-the-payment-method-is-available&quot;&gt;Check whether the payment method is available &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-request-api-works/#check-whether-the-payment-method-is-available&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before invoking the payment procedure, the merchant can check whether the user and
the environment are ready for making a payment.&lt;/p&gt;
&lt;p&gt;Calling &lt;code&gt;canMakePayment()&lt;/code&gt; checks if the browser supports at
least one payment method specified in the object.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;canMakePayment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// This browser supports the specified payment method.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// This browser does NOT support the specified payment method.&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// An exception&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Learn more about &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/PaymentRequest/canMakePayment&quot; rel=&quot;noopener&quot;&gt;PaymentRequest.canMakePayment() on MDN&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-show-method&quot;&gt;The &lt;code&gt;show()&lt;/code&gt; method &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-request-api-works/#the-show-method&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After setting the two parameters and creating the &lt;code&gt;request&lt;/code&gt; object as shown
above, you can call the &lt;code&gt;show()&lt;/code&gt; method, which displays the payment app user
interface.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt;  To call the &lt;code&gt;show()&lt;/code&gt; method, you must add a &lt;a href=&quot;https://developer.chrome.com/blog/user-activation/&quot;&gt;user activation&lt;/a&gt;. This means the call must be inside an event listener, such as &lt;code&gt;click&lt;/code&gt;. Note that Chrome &lt;a href=&quot;https://chromestatus.com/feature/5948593429020672&quot;&gt;enforces this constraint from version 102&lt;/a&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;div&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;request&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// [process payment]&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// send to a PSP etc.&lt;/span&gt;&lt;br /&gt;  response&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;success&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt;  &lt;code&gt;basic-card&lt;/code&gt; payment method is deprecated from Chrome 100. If the browser doesn&#39;t support any of the specified payment methods, it will throw &lt;code&gt;NotSupportedError&lt;/code&gt;. Make sure to first check the payment method availability with &lt;code&gt;canMakePayment()&lt;/code&gt;.  &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;How payment app user interface will look is completely up to the payment app
provider. After the customer agrees to make a payment, a JSON object is passed
to the merchant which contains all the required information to transfer money.
The merchant can then send it to the PSP to process the payment.&lt;/p&gt;
&lt;p&gt;Finally, you may close the Payment Request UI by completing the process with
&lt;code&gt;response.complete(&#39;success&#39;)&lt;/code&gt; or &lt;code&gt;response.complete(&#39;fail&#39;)&lt;/code&gt; depending on the
result that the PSP returns.&lt;/p&gt;
&lt;h2 id=&quot;next-up&quot;&gt;Next up &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-request-api-works/#next-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Learn more about &lt;a href=&quot;https://web.dev/payments/&quot;&gt;Web Payments&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>How the payment ecosystem works</title>
    <link href="https://web.dev/how-payment-ecosystem-works/"/>
    <updated>2018-09-10T00:00:00Z</updated>
    <id>https://web.dev/how-payment-ecosystem-works/</id>
    <content type="html" mode="escaped">&lt;p&gt;Let&#39;s see how the payment ecosystem works with Web Payments.&lt;/p&gt;
&lt;h2 id=&quot;the-anatomy-of-web-payments&quot;&gt;The anatomy of Web Payments &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-ecosystem-works/#the-anatomy-of-web-payments&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Web Payments&lt;/em&gt; comprises multiple web standards:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Payment Request API:&lt;/strong&gt; The &lt;a href=&quot;https://web.dev/how-payment-request-api-works/&quot;&gt;Payment Request
API&lt;/a&gt; enables fast and easy checkouts
through a native browser UI. It provides a consistent checkout flow while
reducing the need for users to enter their shipping and payment information
on every checkout.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Payment Handler API:&lt;/strong&gt; The &lt;a href=&quot;https://web.dev/web-based-payment-apps-overview/&quot;&gt;Payment Handler
API&lt;/a&gt; opens up the ecosystem to
payment providers by allowing their web-based payment applications to act as
payment methods on merchant websites through the standard Payment Request
API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Payment Method Identifiers:&lt;/strong&gt; The &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-1-provide-the-payment-method-identifier&quot;&gt;Payment Method
Identifiers&lt;/a&gt;
defines how strings (&lt;code&gt;https://google.com/pay&lt;/code&gt;,
&lt;code&gt;https://apple.com/apple-pay&lt;/code&gt;, and so on) can be used to identify a payment
method. Along with standardized payment method identifiers, it allows anyone
to define their own payment method with URL-based payment method
identifiers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Payment Method Manifest:&lt;/strong&gt; The &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-2-serve-the-payment-method-manifest&quot;&gt;Payment Method
Manifest&lt;/a&gt;
defines the machine-readable manifest file, known as a payment method
manifest, describing how a payment method participates in the payment
ecosystem, and how such files are to be used.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-the-payment-request-process-works&quot;&gt;How the payment request process works &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-ecosystem-works/#how-the-payment-request-process-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are typically four participants in an online transaction.&lt;/p&gt;
&lt;table&gt;
  &lt;tr&gt;
   &lt;th style=&quot;width:30%;&quot;&gt;Players&lt;/th&gt;
   &lt;th style=&quot;width:50%;&quot;&gt;Description&lt;/th&gt;
   &lt;th style=&quot;width:20%;&quot;&gt;API usage&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Customers&lt;/td&gt;
   &lt;td&gt;Users who go through a checkout flow to purchase item(s) online.
   &lt;/td&gt;
   &lt;td&gt;N/A&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Merchants&lt;/td&gt;
   &lt;td&gt;Businesses selling products on their website.
   &lt;/td&gt;
   &lt;td&gt;Payment Request API&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Payment Service Providers (PSPs)&lt;/td&gt;
   &lt;td&gt;Third-party companies that actually process payments,
   which involves charging customers and crediting merchants.
   Alternatively called payment gateways or payment processors.
   &lt;/td&gt;
   &lt;td&gt;Payment Request API&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
   &lt;td&gt;Payment Handlers&lt;/td&gt;
   &lt;td&gt;Third-party companies which provide applications that typically
   store customers&#39; payment credentials and on their authorization
   provide them to merchants to process a transaction.
   &lt;/td&gt;
   &lt;td&gt;Payment Handler API&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;figure&gt;
  &lt;img alt=&quot;The typical sequence of events in processing a credit card payment on the web&quot; decoding=&quot;async&quot; height=&quot;532&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/blpCp1iuXVShq3dw9LRH.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;figcaption&gt;&lt;i&gt;The typical sequence of events in processing a credit card
  payment on the web&lt;/i&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;The Customer visits a merchant&#39;s website, adds items to a shopping cart, and
starts the checkout flow.&lt;/li&gt;
&lt;li&gt;The Merchant needs the customer&#39;s payment credentials to process the
transaction. They present a payment request UI to the customer using &lt;a href=&quot;https://web.dev/how-payment-request-api-works&quot;&gt;&lt;strong&gt;the
Payment Request API&lt;/strong&gt;&lt;/a&gt;. The UI lists various
methods of payment specified by &lt;a href=&quot;https://web.dev/setting-up-a-payment-method/#step-1-provide-the-payment-method-identifier&quot;&gt;&lt;strong&gt;the Payment Method
Identifiers&lt;/strong&gt;&lt;/a&gt;.
The payment methods can include credit card numbers saved to the browser, or
payment handlers such as Google Pay, Samsung Pay, and similar. The Merchant can
optionally request the customer&#39;s shipping address and contact information.&lt;/li&gt;
&lt;li&gt;If the customer chooses a payment method like Google Pay, Chrome launches
either a platform-native payment app or a web-based payment app. This step
is completely up to the payment handler&#39;s implementation, based on &lt;strong&gt;the
Payment Method Manifest&lt;/strong&gt;. After the customer authorizes the payment, the
payment handler returns a response to the Payment Request API, which relays
it to the merchant site. (If the payment is push type such as bank
transfers, cryptocurrencies, the payment is already processed when the
merchant receives the response.)&lt;/li&gt;
&lt;li&gt;The merchant site sends a payment credential to a PSP to process the payment
and initiate funds transfer. Usually, verifying the payment on the server
side is also required.&lt;/li&gt;
&lt;li&gt;The PSP processes the payment, securely requesting a funds transfer from the
customer&#39;s bank or credit card issuer to the merchant, and then returns a
success or failure result to the merchant website.&lt;/li&gt;
&lt;li&gt;The merchant website notifies the customer of the success or failure of the
transaction and displays the next step, for example, shipping the purchased item.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;caveat-psp-reliance&quot;&gt;Caveat: PSP Reliance &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-ecosystem-works/#caveat-psp-reliance&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are a merchant and want to accept credit card payments, PSPs are an
important link in the payment processing chain. Implementing the Payment Request
API does not remove the need for a PSP.&lt;/p&gt;
&lt;p&gt;Merchants usually rely on a third-party PSP to perform payment processing for
convenience and expense reasons. This is primarily because most PSPs maintain
compliance with &lt;a href=&quot;https://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard&quot; rel=&quot;noopener&quot;&gt;PCI
DSS&lt;/a&gt;,
an information security standard that regulates the safety of cardholder data.&lt;/p&gt;
&lt;p&gt;Because achieving and maintaining strict PCI DSS compliance can be expensive and
difficult, most merchants find that relying on a compliant PSP avoids going
through the certification process themselves. Some large and financially robust
companies, however, obtain their own PCI DSS certification specifically to avoid
such third-party reliance.&lt;/p&gt;
&lt;p&gt;It&#39;s especially important when you are handling a primary account number (PAN)
as a payment credential, that is the number embossed on the card. Handling one
with JavaScript requires &lt;a href=&quot;https://www.pcisecuritystandards.org/documents/PCI-DSS-v3_2-SAQ-A_EP.pdf&quot; rel=&quot;noopener&quot;&gt;PCI SAQ
A-EP&lt;/a&gt;
compliance.&lt;/p&gt;
&lt;p&gt;Thus, delegating payment processing to a PCI DSS-compliant PSP both simplifies
the merchant site&#39;s requirements and ensures payment information integrity for
the customer.&lt;/p&gt;
&lt;h2 id=&quot;next-up&quot;&gt;Next up &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/how-payment-ecosystem-works/#next-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Learn about the Payment Request API&#39;s fields and methods in &lt;a href=&quot;https://web.dev/how-payment-request-api-works&quot;&gt;How the Payment
Request API
Works&lt;/a&gt;.&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Web Payments overview</title>
    <link href="https://web.dev/web-payments-overview/"/>
    <updated>2018-09-10T00:00:00Z</updated>
    <id>https://web.dev/web-payments-overview/</id>
    <content type="html" mode="escaped">&lt;p&gt;Web Payments is an emerging web standard being developed by the W3C to
simplify online payments and enable a broader set of players to participate
easily in the payments ecosystem on the web. The standards are flexible; they
work with various types of payment systems and are intended to work on any
browser on any device, payment method, or payment service provider. This
flexibility enables development simplicity, deployment consistency, and future
compatibility with emerging payment technologies.&lt;/p&gt;
&lt;h2 id=&quot;benefits-of-web-payments&quot;&gt;Benefits of Web Payments &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-overview/#benefits-of-web-payments&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;For consumers&lt;/strong&gt;, they simplify checkout flow, by making it a few taps instead
of typing small characters many times on a virtual keyboard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For merchants&lt;/strong&gt;, they make it easier to implement with a variety of payment
options already filtered for the customer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For payment handlers&lt;/strong&gt;, they allow bringing any type of payment methods to the
web with relatively easy integration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For payment service providers&lt;/strong&gt;, they bring new payment methods and enhance
the ability of businesses to serve more customers with a better developer
experience and more secure solutions.&lt;/p&gt;
&lt;h2 id=&quot;three-principles-of-web-payments&quot;&gt;Three principles of Web Payments &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-overview/#three-principles-of-web-payments&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;section style=&quot;display:flex;background-color:#f7f7f7;padding-bottom:32px;&quot;&gt;
  &lt;div style=&quot;min-width:50%;padding-top:32px;&quot;&gt;
    &lt;img alt=&quot;Standard and Open&quot; decoding=&quot;async&quot; height=&quot;508&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/voaNzDaJcKQFBwtuFem7.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;/div&gt;
  &lt;div style=&quot;min-width:50%&quot;&gt;
    &lt;h3&gt;Standard and open&lt;/h3&gt;
    Web Payments are an open payment standard for the web platform for the first time
    in history. They are available for anyone to implement.&lt;/div&gt;
&lt;/section&gt;
&lt;section style=&quot;display:flex;padding-bottom:32px;&quot;&gt;
  &lt;div style=&quot;min-width:50%&quot;&gt;
    &lt;h3&gt;Easy and consistent&lt;/h3&gt;
    Web Payments make checkout easy for the user, by reusing stored
payments and address information and removing the need for the user to fill in checkout forms.
Since the UI is implemented by the browser natively, users see a familiar and consistent checkout
experience on any website that uses the standard.&lt;/div&gt;
  &lt;div style=&quot;min-width:50%;padding-top:32px;&quot;&gt;
    &lt;img alt=&quot;Easy and Consistent&quot; decoding=&quot;async&quot; height=&quot;508&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/DXwSsz8wgEO3ffCT2s15.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;/div&gt;
&lt;/section&gt;
&lt;section style=&quot;display:flex;background-color:#f7f7f7;padding-bottom:32px;&quot;&gt;
  &lt;div style=&quot;min-width:50%;padding-top:32px;&quot;&gt;
    &lt;img alt=&quot;Secure and Flexible&quot; decoding=&quot;async&quot; height=&quot;508&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/YLflGBAPWecgtKJLqCJHSzHqe2J2/9ksUqSzpIvHLiazAoyTk.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
  &lt;/div&gt;
  &lt;div style=&quot;min-width:50%&quot;&gt;
    &lt;h3&gt;Secure and flexible&lt;/h3&gt;
    Web Payments provide industry-leading payment technology to the
web, and can easily integrate a secure payment solution.&lt;/div&gt;
&lt;/section&gt;
&lt;h2 id=&quot;next-up&quot;&gt;Next up &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/web-payments-overview/#next-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Learn &lt;a href=&quot;https://web.dev/how-payment-ecosystem-works&quot;&gt;How payment ecosystem works&lt;/a&gt; with Web
Payments.&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Credential Management API Feature Detection Check-up</title>
    <link href="https://web.dev/webauthn-credential-management/"/>
    <updated>2018-03-14T00:00:00Z</updated>
    <id>https://web.dev/webauthn-credential-management/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#summary&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/webauthn/&quot; rel=&quot;noopener&quot;&gt;WebAuthn&lt;/a&gt; helps increase security by bringing
public-key credential based authentication to the Web, and is soon to be
supported in Chrome, Firefox and Edge (&lt;a href=&quot;https://docs.microsoft.com/microsoft-edge/dev-guide/device/web-authentication#differences-between-microsoft-edge-and-the-spec&quot; rel=&quot;noopener&quot;&gt;with the updated
spec&lt;/a&gt;).
It adds a new kind of &lt;code&gt;Credential&lt;/code&gt; object, which, however, may break websites
that use &lt;a href=&quot;https://www.w3.org/TR/credential-management-1/&quot; rel=&quot;noopener&quot;&gt;the Credential Management
API&lt;/a&gt; without feature-detecting
the specific credential types they&#39;re using.&lt;/p&gt;
&lt;h3 id=&quot;if-you-are-currently-doing-this-for-feature-detection&quot;&gt;If you are currently doing this for feature detection &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#if-you-are-currently-doing-this-for-feature-detection&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;preventSilentAccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// use CM API&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;do-these-instead&quot;&gt;Do these instead &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#do-these-instead&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Call navigator.credentials.get() to retrieve stored&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// PasswordCredentials or FederatedCredentials.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Get/Store PasswordCredential&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Get/Store FederatedCredential&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;preventSilentAccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Call navigator.credentials.preventSilentAccess()&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;See &lt;a href=&quot;https://github.com/GoogleChromeLabs/credential-management-sample/pull/15/files&quot; rel=&quot;noopener&quot;&gt;changes&lt;/a&gt; made to the sample code as an example.&lt;/p&gt;
&lt;p&gt;Read on to learn more.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; If you are using Google identity as a primary way for your users to sign-in, consider using the &lt;a href=&quot;https://developers.google.com/identity/gsi/web/guides/overview&quot;&gt;one tap sign-up and automatic sign-in&lt;/a&gt; JavaScript library built on the Credential Management API. It combines Google sign-in and password-based sign-in into one API call, and adds support for one-tap account creation. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;what-is-the-credential-management-api&quot;&gt;What is the Credential Management API &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#what-is-the-credential-management-api&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/credential-management-1/&quot; rel=&quot;noopener&quot;&gt;The Credential Management API&lt;/a&gt;
(CM API) gives websites programmatic access to the user agent’s credential store
for storing/retrieving user credentials for the calling origin.&lt;/p&gt;
&lt;p&gt;Basic APIs are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;navigator.credentials.get()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;navigator.credentials.store()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;navigator.credentials.create()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;navigator.credentials.preventSilentAccess()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The original CM API specification defines 2 credential types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PasswordCredential&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FederatedCredential&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;PasswordCredential&lt;/code&gt; is a credential that contains user&#39;s id and password.
The &lt;code&gt;FederatedCredential&lt;/code&gt; is a credential that contains user&#39;s id and a string
that represents an identity provider.&lt;/p&gt;
&lt;p&gt;With these 2 credentials, websites can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Let the user sign-in with a previously saved password-based or federated
credential as soon as they land (auto sign-in),&lt;/li&gt;
&lt;li&gt;Store the password-based or federated credential the user has signed in with,&lt;/li&gt;
&lt;li&gt;Keep the user&#39;s sign-in credentials up-to-date (e.g. after a password change)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-webauthn&quot;&gt;What is WebAuthn &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#what-is-webauthn&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/TR/webauthn/&quot; rel=&quot;noopener&quot;&gt;WebAuthn&lt;/a&gt; (Web Authentication) adds public-key
credentials to the CM API. For example, it gives websites a standardized way to
implement second-factor authentication using &lt;a href=&quot;https://fidoalliance.org/&quot; rel=&quot;noopener&quot;&gt;FIDO
2.0&lt;/a&gt; compliant authenticator devices.&lt;/p&gt;
&lt;p&gt;On a technical level, WebAuthn extends the CM API with the &lt;code&gt;PublicKeyCredential&lt;/code&gt;
interface.&lt;/p&gt;
&lt;h2 id=&quot;what-is-the-problem&quot;&gt;What is the problem? &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#what-is-the-problem&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Previously we have been guiding developers to feature detect the CM API with
following code:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;preventSilentAccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Use CM API&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; you can see from the descriptions above&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; the &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;navigator.credentials&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt; is&lt;br /&gt;now expanded to support &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;key credentials &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; addition to password&lt;br /&gt;credentials and federated credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The problem is that user agents don&#39;t necessarily support all kinds &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;&lt;br /&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; If you &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt; feature detect using &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;navigator.credentials&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; your&lt;br /&gt;website may &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt; when you are using a certain credential type not supported by&lt;br /&gt;the browser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;Supported credential types by browsers&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;table &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;properties with-heading-tint&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;tbody&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; FederatedCredential&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;PublicKeyCredential&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Chrome&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Available&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;In development&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Firefox&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Aiming to ship on &lt;span class=&quot;token number&quot;&gt;60&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Edge&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;th&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;N&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;Implemented &lt;span class=&quot;token keyword&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;a href&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://blogs.windows.com/msedgedev/2016/04/12/a-world-without-passwords-windows-hello-in-microsoft-edge/&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;older &lt;span class=&quot;token constant&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;a&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; New &lt;span class=&quot;token constant&quot;&gt;API&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; coming soon&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;td&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tr&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;tbody&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;table&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;## The solution&lt;br /&gt;You can avoid &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt; by modifying feature detection code &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; follows to explicitly&lt;br /&gt;test &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; the credential type that you intend to use&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;`js&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Call navigator.credentials.get() to retrieve stored&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// PasswordCredentials or FederatedCredentials.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Get/Store PasswordCredential&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Get/Store FederatedCredential&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;preventSilentAccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Call navigator.credentials.preventSilentAccess()&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;See &lt;a href=&quot;https://github.com/GoogleChromeLabs/credential-management-sample/pull/15/files&quot; rel=&quot;noopener&quot;&gt;actual
changes&lt;/a&gt; made to the sample code as an example.&lt;/p&gt;
&lt;p&gt;For a reference, here&#39;s how to detect &lt;code&gt;PublicKeyCredential&lt;/code&gt; added in WebAuthn:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PublicKeyCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// use CM API with PublicKeyCredential added in the WebAuthn spec&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;timeline&quot;&gt;Timeline &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#timeline&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Earliest available implementation of WebAuthn is Firefox and is &lt;a href=&quot;https://wiki.mozilla.org/RapidRelease/Calendar&quot; rel=&quot;noopener&quot;&gt;planned to be stable around early May 2018&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;finally&quot;&gt;Finally &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/webauthn-credential-management/#finally&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you have any questions, send them over to
&lt;a href=&quot;https://twitter.com/agektmr&quot; rel=&quot;noopener&quot;&gt;@agektmr&lt;/a&gt; or
agektmr@chromium.org.&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Sign in Users</title>
    <link href="https://web.dev/security-credential-management-retrieve-credentials/"/>
    <updated>2016-11-08T00:00:00Z</updated>
    <id>https://web.dev/security-credential-management-retrieve-credentials/</id>
    <content type="html" mode="escaped">&lt;p&gt;To sign in users, retrieve the credentials from the browser&#39;s password
manager and use those to automatically log in users.
For users with multiple accounts,
let them select the account with just one tap using the account chooser.&lt;/p&gt;
&lt;h2 id=&quot;auto-sign-in&quot;&gt;Auto Sign-in &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#auto-sign-in&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Auto sign-in can happen anywhere on your website;
not only the top page but other leaf pages too.
This is useful when users reach various pages in your website,
via a search engine.&lt;/p&gt;
&lt;p&gt;To enable auto sign-in:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get credential information.&lt;/li&gt;
&lt;li&gt;Authenticate the user.&lt;/li&gt;
&lt;li&gt;Update the UI or proceed to the personalized page.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;get-credential-information&quot;&gt;Get credential information &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#get-credential-information&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 51, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      51
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 60, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      60
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 18, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      18
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 13, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      13
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;To get credential information, invoke
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.get()&lt;/code&gt;&lt;/a&gt;.
Specify the type of credentials to request
by giving it a &lt;code&gt;password&lt;/code&gt; or &lt;code&gt;federated&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Always use &lt;code&gt;mediation: &#39;silent&#39;&lt;/code&gt; for auto sign-ins,
so you can easily dismiss the process if the user:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Has no credentials stored.&lt;/li&gt;
&lt;li&gt;Has multiple credentials stored.&lt;/li&gt;
&lt;li&gt;Is signed out.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before getting a credential,
don’t forget to check if the user is already signed in:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isSignedIn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;federated&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;providers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://accounts.google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;mediation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;silent&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The promise returned by &lt;code&gt;navigator.credentials.get()&lt;/code&gt; resolves
with either a credential object or &lt;code&gt;null&lt;/code&gt;.
To determine whether it is a &lt;code&gt;PasswordCredential&lt;/code&gt; or a &lt;code&gt;FederatedCredential&lt;/code&gt;,
simply look at the &lt;code&gt;.type&lt;/code&gt; property of the object,
which will be either &lt;code&gt;password&lt;/code&gt; or &lt;code&gt;federated&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If the &lt;code&gt;.type&lt;/code&gt; is &lt;code&gt;federated&lt;/code&gt;,
the &lt;code&gt;.provider&lt;/code&gt; property is a string that represents the identity provider.&lt;/p&gt;
&lt;h3 id=&quot;authenticate-user&quot;&gt;Authenticate user &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#authenticate-user&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once you have the credential,
run an authentication flow depending on the type of credential,
&lt;code&gt;password&lt;/code&gt; or &lt;code&gt;federated&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sendRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;federated&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gSignIn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When the promise resolves,
check if you&#39;ve received a credential object.
If not, it means auto sign-in couldn’t happen.
Silently dismiss the auto sign-in process.&lt;/p&gt;
&lt;h3 id=&quot;update-ui&quot;&gt;Update UI &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#update-ui&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If the authentication is successful,
update the UI or forward the user to the personalized page:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;profile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token function&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;dont-forget-to-show-authentication-error-message&quot;&gt;Don’t forget to show authentication error message &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#dont-forget-to-show-authentication-error-message&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To avoid user confusion,
users should see a blue toast saying “Signing in”
at the time of getting the credential object:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Blue toast showing user is signing in.&quot; decoding=&quot;async&quot; height=&quot;123&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 386px) 386px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/4nT0MfpnEaOvFAmZxkLM.png?auto=format&amp;w=772 772w&quot; width=&quot;386&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;One important tip: if you succeed in obtaining a credential object
but fail to authenticate the user, you should show an error message:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token function&quot;&gt;showError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Sign-in Failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;full-code-example&quot;&gt;Full code example &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#full-code-example&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isSignedIn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;federated&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token literal-property property&quot;&gt;providers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://accounts.google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;mediation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;silent&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sendRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;federated&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gSignIn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token function&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token function&quot;&gt;showError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Sign-in Failed&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;sign-in-via-account-chooser&quot;&gt;Sign-in via account chooser &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#sign-in-via-account-chooser&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If a user requires mediation, or has multiple accounts,
use the account chooser to let the user sign-in,
skipping the ordinary sign-in form, for example:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Google account chooser showing multiple accounts.&quot; decoding=&quot;async&quot; height=&quot;346&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 390px) 390px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/C47gYyWYVMMhDmtYSLOWazuyePF2/drlYzW650dtEob0LyzRl.png?auto=format&amp;w=780 780w&quot; width=&quot;390&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;The steps to sign in via the account chooser are the same as in
&lt;a href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#auto-sign-in&quot;&gt;auto sign-in&lt;/a&gt;,
with an additional call to show the account chooser
as part of getting credential information:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Get the credential information and show the account chooser.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#authenticate-user&quot;&gt;Authenticate the user&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#update-ui&quot;&gt;Update the UI or proceed to a personalized page&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;get-credential-information-and-show-account-chooser&quot;&gt;Get credential information and show account chooser &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#get-credential-information-and-show-account-chooser&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Show an account chooser in response to a defined user action,
for example, when the user taps the &amp;quot;Sign-In&amp;quot; button. Call
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.get()&lt;/code&gt;&lt;/a&gt;,
and add &lt;code&gt;mediation: &#39;optional&#39;&lt;/code&gt; or &lt;code&gt;mediation: &#39;required&#39;&lt;/code&gt; to show the account chooser.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;mediation&lt;/code&gt; is &lt;code&gt;required&lt;/code&gt;, the user is always shown an account chooser to sign in.
This option allows users with multiple accounts to easily switch between them.
When &lt;code&gt;mediation&lt;/code&gt; is &lt;code&gt;optional&lt;/code&gt;,
the user is explicitly shown an account chooser to sign in after a
&lt;a href=&quot;https://web.dev/web/fundamentals/security/credential-management/retrieve-credentials#turn_off_auto_sign-in_for_future_visits&quot;&gt;&lt;code&gt;navigator.credentials.preventSilentAccess()&lt;/code&gt;&lt;/a&gt;
call.
This is normally to ensure automatic sign-in doesn&#39;t happen
after the user chooses to sign-out or unregister.&lt;/p&gt;
&lt;p&gt;Example showing &lt;code&gt;mediation: &#39;optional&#39;&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; signin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    signin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;     &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;       navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token literal-property property&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token literal-property property&quot;&gt;federated&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;token literal-property property&quot;&gt;providers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;             &lt;span class=&quot;token string&quot;&gt;&#39;https://accounts.google.com&#39;&lt;/span&gt;&lt;br /&gt;           &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;         &lt;span class=&quot;token literal-property property&quot;&gt;mediation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;optional&#39;&lt;/span&gt;&lt;br /&gt;       &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Once the user selects an account,
the promise resolves with the credential.
If the users cancels the account chooser,
or there are no credentials stored,
the promise resolves with &lt;code&gt;null&lt;/code&gt;.
In that case, fall back to the sign in form experience.&lt;/p&gt;
&lt;h3 id=&quot;dont-forget-to-fall-back-to-sign-in-form&quot;&gt;Don&#39;t forget to fall back to sign-in form &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#dont-forget-to-fall-back-to-sign-in-form&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You should fall back to a sign-in form for any of these reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No credentials are stored.&lt;/li&gt;
&lt;li&gt;The user dismissed the account chooser without selecting an account.&lt;/li&gt;
&lt;li&gt;The API is not available.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;profile&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token function&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;full-code-example-2&quot;&gt;Full code example &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#full-code-example-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; signin &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;signin&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;federated&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token literal-property property&quot;&gt;providers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://accounts.google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;mediation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;optional&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;password&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sendRequest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;federated&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;gSignIn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;              &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;profile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token function&quot;&gt;updateUI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;profile&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        location&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;/signin&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;federated-login&quot;&gt;Federated Login &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#federated-login&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Federated login lets users sign in with one tap and
without having to remember additional login details for your website.&lt;/p&gt;
&lt;p&gt;To implement federated login:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Authenticate the user with a third-party identity.&lt;/li&gt;
&lt;li&gt;Store the identity information.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#update-ui&quot;&gt;Update the UI or proceed to a personalized page&lt;/a&gt; (same as in auto sign-in).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;authenticate-user-with-third-party-identity&quot;&gt;Authenticate user with third-party identity &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#authenticate-user-with-third-party-identity&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When a user taps on a federated login button,
run the specific identity provider authentication flow with the
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FederatedCredential&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FederatedCredential&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 51, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      51
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox, Not supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Edge 79, Supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
79
&lt;/span&gt;
&lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
&lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
&lt;span class=&quot;visually-hidden&quot;&gt;Safari, Not supported&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;no&quot; title=&quot;Not supported&quot; aria-label=&quot;Not supported&quot;&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;/span&gt;
&lt;/li&gt;&lt;p&gt;&lt;/p&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/FederatedCredential#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;For example, if the provider is Google, use the
&lt;a href=&quot;https://web.dev/identity/sign-in/web/&quot;&gt;Google Sign-In JavaScript library&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;mediation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;optional&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;federated&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token literal-property property&quot;&gt;providers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;https://account.google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;cred&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cred&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Instantiate an auth object&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; auth2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; gapi&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;auth2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getAuthInstance&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Is this user already signed in?&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;auth2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isSignedIn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; googleUser &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; auth2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;currentUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;        &lt;span class=&quot;token comment&quot;&gt;// Same user as in the credential object?&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;googleUser&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBasicProfile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getEmail&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; cred&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token comment&quot;&gt;// Continue with the signed-in user.&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;googleUser&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;      &lt;span class=&quot;token comment&quot;&gt;// Otherwise, run a new authentication flow.&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; auth2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;signIn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;login_hint&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Google Sign-In results in an ID token as a proof of authentication.&lt;/p&gt;
&lt;p&gt;In general, federated logins are built on top of standard protocols such as
&lt;a href=&quot;http://openid.net/connect/&quot; rel=&quot;noopener&quot;&gt;OpenID Connect&lt;/a&gt; or
&lt;a href=&quot;https://oauth.net/2/&quot; rel=&quot;noopener&quot;&gt;OAuth&lt;/a&gt;.
To learn how to authenticate with federated accounts,
refer to respective federated identity providers&#39; docs.
Popular examples include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/identity/sign-in/web/&quot;&gt;Google Sign-In&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.facebook.com/docs/facebook-login&quot; rel=&quot;noopener&quot;&gt;Facebook Login&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.twitter.com/web/sign-in/implementing&quot; rel=&quot;noopener&quot;&gt;Twitter Sign-in&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.github.com/v3/oauth/&quot; rel=&quot;noopener&quot;&gt;GitHub OAuth&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;store-identity-information&quot;&gt;Store identity information &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#store-identity-information&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once authentication is done, you can store the identity information.
The information you’ll store here is the &lt;code&gt;id&lt;/code&gt; from the identity provider
and a provider string that represents the identity provider
(&lt;code&gt;name&lt;/code&gt; and &lt;code&gt;iconURL&lt;/code&gt; are optional).
Learn more about this information in the
&lt;a href=&quot;https://w3c.github.io/webappsec-credential-management/#credential&quot; rel=&quot;noopener&quot;&gt;Credential Management specification&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To store federated account details, instantiate a new
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FederatedCredential&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FederatedCredential&lt;/code&gt;&lt;/a&gt;
object with the user&#39;s identifier and the provider&#39;s identifier.
Then invoke
&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/store&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.store()&lt;/code&gt;&lt;/a&gt;
to store the identity information.&lt;/p&gt;
&lt;p&gt;After successful federation,
instantiate a &lt;code&gt;FederatedCredential&lt;/code&gt; synchronously, or asynchronously:&lt;/p&gt;
&lt;p&gt;Example of synchronous approach:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Create credential object synchronously.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; cred &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;FederatedCredential&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// id in IdP&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://account.google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// A string representing IdP&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// name in IdP&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;iconURL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; iconUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Profile image url&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Example of asynchronous approach:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Create credential object asynchronously.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; cred &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token literal-property property&quot;&gt;federated&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; id&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;https://accounts.google.com&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;iconURL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; iconUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Then store the credential object:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Store it&lt;/span&gt;&lt;br /&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cred&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// continuation&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;sign-out&quot;&gt;Sign out &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#sign-out&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sign out your users when the sign-out button is tapped.
First terminate the session,
then turn off auto sign-in for future visits.
(How you terminate your sessions is totally up to you.)&lt;/p&gt;
&lt;h3 id=&quot;turn-off-auto-sign-in-for-future-visits&quot;&gt;Turn off auto sign-in for future visits &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#turn-off-auto-sign-in-for-future-visits&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Call
&lt;code&gt;navigator.credentials.preventSilentAccess()&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;signoutUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;preventSilentAccess&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;credentials&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;preventSilentAccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This will ensure the auto sign-in won’t happen until next time the user enables auto sign-in.
To resume auto sign-in, a user can choose to intentionally sign in
by choosing the account they wish to sign in with from the account chooser.
Then the user is always signed back in until they explicitly sign out.&lt;/p&gt;
&lt;h2 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management-retrieve-credentials/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author><author>
      <name>Meggin Kearney</name>
    </author>
  </entry>
  
  <entry>
    <title>The Credential Management API</title>
    <link href="https://web.dev/security-credential-management/"/>
    <updated>2016-11-08T00:00:00Z</updated>
    <id>https://web.dev/security-credential-management/</id>
    <content type="html" mode="escaped">&lt;p&gt;The &lt;a href=&quot;https://www.w3.org/TR/credential-management/&quot; rel=&quot;noopener&quot;&gt;Credential Management API&lt;/a&gt;
is a standards-based browser API that provides a programmatic interface
between the site and the browser for seamless sign-in across devices.&lt;/p&gt;
&lt;p&gt;The Credential Management API:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Removes friction from sign-in flows&lt;/strong&gt; - Users can be automatically signed back into a site even if their session has expired or they saved credentials on another device.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Allows one tap sign in with account chooser&lt;/strong&gt; - Users can choose an account in a native account chooser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stores credentials&lt;/strong&gt; - Your application can store either a username and password combination or even federated account details. These credentials can be synced across devices by the browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;aside class=&quot;aside flow bg-tertiary-box-bg color-tertiary-box-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block &quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; role=&quot;img&quot; aria-label=&quot;Lightbulb&quot; fill=&quot;currentColor&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path d=&quot;M9 21c0 .55.45 1 1 1h4c.55 0 1-.45 1-1v-1H9v1zm3-19C8.14 2 5 5.14 5 9c0 2.38 1.19 4.47 3 5.74V17c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2.26c1.81-1.27 3-3.36 3-5.74 0-3.86-3.14-7-7-7zm2.85 11.1l-.85.6V16h-4v-2.3l-.85-.6A4.997 4.997 0 017 9c0-2.76 2.24-5 5-5s5 2.24 5 5c0 1.63-.8 3.16-2.15 4.1z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Using the Credential Management API requires the page be served from a secure origin. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Want to see it in action? Try the
&lt;a href=&quot;https://credential-management-sample.appspot.com/&quot; rel=&quot;noopener&quot;&gt;Credential Management API Demo&lt;/a&gt;
and take a look at the
&lt;a href=&quot;https://github.com/GoogleChrome/credential-management-sample&quot; rel=&quot;noopener&quot;&gt;code&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;check-credential-management-api-browser-support&quot;&gt;Check Credential Management API browser support &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management/#check-credential-management-api-browser-support&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;wdi-browser-compat&quot;&gt;
  &lt;span class=&quot;wdi-browser-compat__label&quot;&gt;Browser support&lt;/span&gt;
  &lt;ul class=&quot;wdi-browser-compat__items&quot;&gt;
    &lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;chrome&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Chrome 51, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      51
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;firefox&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Firefox 60, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      60
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;edge&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Edge 18, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      18
    &lt;/span&gt;
    &lt;/li&gt;&lt;li class=&quot;wdi-browser-compat__item&quot;&gt;
    &lt;span class=&quot;wdi-browser-compat__icon&quot; data-browser=&quot;safari&quot;&gt;
      &lt;span class=&quot;visually-hidden&quot;&gt;Safari 13, Supported&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class=&quot;wdi-browser-compat__version&quot; data-compat=&quot;yes&quot; title=&quot;Supported&quot; aria-label=&quot;Supported&quot;&gt;
      13
    &lt;/span&gt;
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;a class=&quot;wdi-browser-compat__link&quot; href=&quot;https://developer.mozilla.org/docs/Web/API/Credential#browser_compatibility&quot; target=&quot;_blank&quot;&gt;Source&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Before using the Credential Management API, first check if &lt;code&gt;PasswordCredential&lt;/code&gt;
or &lt;code&gt;FederatedCredential&lt;/code&gt; is supported.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;PasswordCredential &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FederatedCredential&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// Call navigator.credentials.get() to retrieve stored&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;// PasswordCredentials or FederatedCredentials.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-warn-bg color-state-warn-text&quot;&gt;&lt;p class=&quot;cluster &quot;&gt;&lt;span class=&quot;aside__icon box-block color-state-warn-text&quot;&gt;&lt;svg width=&quot;24&quot; height=&quot;24&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; role=&quot;img&quot; aria-label=&quot;Warning sign&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;   &lt;path fill-rule=&quot;evenodd&quot; clip-rule=&quot;evenodd&quot; d=&quot;M23 21L12 2 1 21h22zm-12-3v-2h2v2h-2zm0-4h2v-4h-2v4z&quot;&gt;&lt;/path&gt; &lt;/svg&gt;&lt;/span&gt;&lt;strong&gt;Warning&lt;/strong&gt;&lt;/p&gt;&lt;div class=&quot; flow&quot;&gt; Feature detection by checking &lt;code&gt;navigator.credentials&lt;/code&gt; may break your website on browsers supporting &lt;a href=&quot;https://www.w3.org/TR/webauthn/&quot;&gt;WebAuthn&lt;/a&gt;(PublicKeyCredential) but not all credential types (&lt;code&gt;PasswordCredential&lt;/code&gt; and &lt;code&gt;FederatedCredential&lt;/code&gt;) defined by the Credential Management API. &lt;a href=&quot;https://web.dev/web/updates/2018/03/webauthn-credential-management&quot;&gt;Learn more&lt;/a&gt;. &lt;/div&gt;&lt;/aside&gt;
&lt;h3 id=&quot;sign-in-user&quot;&gt;Sign in user &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management/#sign-in-user&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To sign in the user, retrieve the credentials from the browser&#39;s password
manager and use them to log in the user.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;When a user lands on your site and they are not signed in,
call &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/get&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.get()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use the retrieved credentials to sign in the user.&lt;/li&gt;
&lt;li&gt;Update the UI to indicate the user has been signed in.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Learn more in
&lt;a href=&quot;https://web.dev/security-credential-management-retrieve-credentials#auto-sign-in&quot;&gt;Sign In Users&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;save-or-update-user-credentials&quot;&gt;Save or update user credentials &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management/#save-or-update-user-credentials&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If the user signed in with a federated identity provider such as Google
Sign-In, Facebook, GitHub:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;After the user successfully signs in or creates an account, create the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/FederatedCredential&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;FederatedCredential&lt;/code&gt;&lt;/a&gt; with the user&#39;s email address as
the ID and specify the identity provider with &lt;code&gt;FederatedCredentials.provider&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Save the credential object using &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/store&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.store()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Learn more in
&lt;a href=&quot;https://web.dev/security-credential-management-retrieve-credentials#federated-login&quot;&gt;Sign In Users&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If the user signed in with a username and password:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;After the user successfully signs in or creates an account, create the &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/PasswordCredential&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PasswordCredential&lt;/code&gt;&lt;/a&gt; with the user ID and
the password.&lt;/li&gt;
&lt;li&gt;Save the credential object using &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/CredentialsContainer/store&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;navigator.credentials.store()&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Learn more in
&lt;a href=&quot;https://web.dev/security-credential-management-save-forms&quot;&gt;Save Credentials from Forms&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;sign-out&quot;&gt;Sign out &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management/#sign-out&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When the user signs out, call &lt;a href=&quot;https://web.dev/web/fundamentals/security/credential-management/retrieve-credentials#turn_off_auto_sign-in_for_future_visits&quot;&gt;&lt;code&gt;navigator.credentials.preventSilentAccess()&lt;/code&gt;&lt;/a&gt;
to prevent the user from being automatically signed back in.&lt;/p&gt;
&lt;p&gt;Disabling auto-sign-in also enables users to switch between accounts easily,
for example, between work and personal accounts, or between accounts on
shared devices, without having to re-enter their sign-in information.&lt;/p&gt;
&lt;p&gt;Learn more in
&lt;a href=&quot;https://web.dev/security-credential-management-retrieve-credentials#sign-out&quot;&gt;Sign out&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;feedback&quot;&gt;Feedback &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/security-credential-management/#feedback&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author><author>
      <name>Meggin Kearney</name>
    </author>
  </entry>
  
  <entry>
    <title>Social discovery</title>
    <link href="https://web.dev/social-discovery/"/>
    <updated>2014-10-07T00:00:00Z</updated>
    <id>https://web.dev/social-discovery/</id>
    <content type="html" mode="escaped">&lt;p&gt;You can influence the way your site appears when shared via social media by
adding a few lines of code to each page. This can help bring more people to
your site by providing previews with richer information than would otherwise
be available.&lt;/p&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#summary&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Use schema.org microdata to provide page title, description, and an image for Google+.&lt;/li&gt;
&lt;li&gt;Use Open Graph Protocol (OGP) to provide page title, description, and an image for Facebook.&lt;/li&gt;
&lt;li&gt;Use Twitter Cards to provide page title, description, an image, and a Twitter id for Twitter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can influence the way your site appears when shared via social media by
adding a few lines of code to each page. This can help increase engagement by
providing previews with richer information than would otherwise be available.
Without it, social sites will provide only basic information, without images or
other helpful information.&lt;/p&gt;
&lt;p&gt;Which one do you think is more likely to be clicked? People are drawn to images
and feel more confident they&#39;ll like what they find when they have an early
preview.&lt;/p&gt;
&lt;div class=&quot;switcher&quot;&gt;
  &lt;figure&gt;
    &lt;img alt=&quot;With the appropriate markup: the correct title, a short       description, and an image are included. Adding these items can help       increase engagement.&quot; decoding=&quot;async&quot; height=&quot;536&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 451px) 451px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/iQCTEOefZ4T6nlsyw9E4.png?auto=format&amp;w=902 902w&quot; width=&quot;451&quot; /&gt;
    &lt;figcaption class=&quot;success&quot;&gt;
      With the appropriate markup: the correct title, a short
      description, and an image are included. Adding these items can help
      increase engagement.
     &lt;/figcaption&gt;
  &lt;/figure&gt;
 &lt;figure&gt;
    &lt;img alt=&quot;Without the proper mark up, only the page title is       included.&quot; decoding=&quot;async&quot; height=&quot;268&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 455px) 455px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/tFvEj7JzOBiFWJUBkdNb.png?auto=format&amp;w=910 910w&quot; width=&quot;455&quot; /&gt;
    &lt;figcaption class=&quot;warning&quot;&gt;
      Without the proper mark up, only the page title is
      included.
     &lt;/figcaption&gt;
  &lt;/figure&gt;
&lt;/div&gt;
&lt;p&gt;When someone on a social network wants to share your website with their friends,
they would probably add some notes explaining how awesome it is, and share it.
But describing a website tends be cumbersome and can miss the point from the
page owner&#39;s point of view. Some services restrict the number of characters users can
put in the note.&lt;/p&gt;
&lt;p&gt;By adding the appropriate metadata to your pages, you can simplify the sharing
process for users by providing the title, a description, and an attractive
image. This means they don&#39;t have to spend valuable time (or characters)
describing the link.&lt;/p&gt;
&lt;h2 id=&quot;use-schemaorg-microdata-to-provide-rich-snippets-on-google&quot;&gt;Use schema.org + microdata to provide rich snippets on Google+ &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#use-schemaorg-microdata-to-provide-rich-snippets-on-google&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Crawlers use many methods to parse a page and understand its content. By using
&lt;a href=&quot;http://www.w3.org/TR/microdata/&quot; rel=&quot;noopener&quot;&gt;microdata&lt;/a&gt;, and
&lt;a href=&quot;https://schema.org/&quot; rel=&quot;noopener&quot;&gt;schema.org&lt;/a&gt; vocabulary, you help social sites and search
engines better understand the contents of the page.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemtype&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://schema.org/Article&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;h1&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Enjoy fireworks&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;h1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Fireworks are beautiful.&lt;br /&gt;   This article explains how beautiful fireworks are.&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;//developers.google.com/web/imgs/fireworks.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;While most metadata are embedded in the head section of a web page, microdata
lives where the context exists.&lt;/p&gt;
&lt;h3 id=&quot;add-itemscope-to-define-microdata-scope&quot;&gt;Add &lt;code&gt;itemscope&lt;/code&gt; to define microdata scope &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#add-itemscope-to-define-microdata-scope&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;By adding &lt;code&gt;itemscope&lt;/code&gt;, you can specify the tag as a block of contents about a
particular item.&lt;/p&gt;
&lt;h3 id=&quot;add-itemtype-to-define-type-of-your-website&quot;&gt;Add &lt;code&gt;itemtype&lt;/code&gt; to define type of your website &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#add-itemtype-to-define-type-of-your-website&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can specify the type of item by using the &lt;code&gt;itemtype&lt;/code&gt; attribute along with the
&lt;code&gt;itemscope&lt;/code&gt;. The value of an &lt;code&gt;itemtype&lt;/code&gt; can be determined according to the type
of content on your web page. You should be able to find one that is relevant
in &lt;a href=&quot;https://schema.org/docs/full.html&quot; rel=&quot;noopener&quot;&gt;this page&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;add-itemprop-to-describe-each-item-using-schemaorg-vocabulary&quot;&gt;Add &lt;code&gt;itemprop&lt;/code&gt; to describe each item using schema.org vocabulary &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#add-itemprop-to-describe-each-item-using-schemaorg-vocabulary&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;itemprop&lt;/code&gt; defines properties for &lt;code&gt;itemtype&lt;/code&gt; in the scope. For providing
metadata to social sites, typical &lt;code&gt;itemprop&lt;/code&gt; values are &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;,
and &lt;code&gt;image&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;validate-rich-snippets&quot;&gt;Validate rich snippets &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#validate-rich-snippets&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To validate rich snippets on Google+, you can use tools such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/webmasters/tools/richsnippets&quot; rel=&quot;noopener&quot;&gt;Structured Data Testing Tool&lt;/a&gt; - Webmaster Tools&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt=&quot;Structured data testing tool&quot; decoding=&quot;async&quot; height=&quot;522&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 800px) 800px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=1098 1098w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=1252 1252w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=1428 1428w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/TJjnWguuLs90e2sjWQbf.png?auto=format&amp;w=1600 1600w&quot; width=&quot;800&quot; /&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;use-open-graph-protocol-ogp-to-provide-rich-snippets-on-facebook&quot;&gt;Use Open Graph Protocol (OGP) to provide rich snippets on Facebook &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#use-open-graph-protocol-ogp-to-provide-rich-snippets-on-facebook&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;http://ogp.me/&quot; rel=&quot;noopener&quot;&gt;Open Graph Protocol (OGP)&lt;/a&gt; provides Facebook with the
metadata necessary to allow web pages to have the same functionality as other
Facebook objects.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og: http://ogp.me/ns#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;X-UA-Compatible&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;IE=edge&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;width=device-width, initial-scale=1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://fonts.googleapis.com/icon?family=Material+Icons&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://code.getmdl.io/1.2.1/material.indigo-pink.min.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;defer&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://code.getmdl.io/1.2.1/material.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;      &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Enjoy Fireworks&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Fireworks are beautiful. This article explains how beautiful fireworks are.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://developers.google.com/web/imgs/fireworks.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:url&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/discovery-and-distribution/optimizations-for-crawlers/social-sites.html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:type&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;website&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When included in the head section of your page, this metadata provides rich
snippet information when the page is shared.&lt;/p&gt;
&lt;h3 id=&quot;use-og-namespaced-meta-tags-to-describe-metadata&quot;&gt;Use &lt;code&gt;og:&lt;/code&gt; namespaced &lt;code&gt;meta&lt;/code&gt; tags to describe metadata &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#use-og-namespaced-meta-tags-to-describe-metadata&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;meta&lt;/code&gt; tag consists of a &lt;code&gt;property&lt;/code&gt; attribute and a &lt;code&gt;content&lt;/code&gt; attribute.
Properties and contents may take the following values:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th data-th=&quot;Property&quot;&gt;Property&lt;/th&gt;
      &lt;th data-th=&quot;Content&quot;&gt;Content&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td data-th=&quot;Property&quot;&gt;&lt;code&gt;og:title&lt;/code&gt;&lt;/td&gt;
      &lt;td data-th=&quot;Content&quot;&gt;The title of the web page.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td data-th=&quot;Property&quot;&gt;&lt;code&gt;og:description&lt;/code&gt;&lt;/td&gt;
      &lt;td data-th=&quot;Content&quot;&gt;The description of the web page.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td data-th=&quot;Property&quot;&gt;&lt;code&gt;og:url&lt;/code&gt;&lt;/td&gt;
      &lt;td data-th=&quot;Content&quot;&gt;The canonical url of the web page.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td data-th=&quot;Property&quot;&gt;&lt;code&gt;og:image&lt;/code&gt;&lt;/td&gt;
      &lt;td data-th=&quot;Content&quot;&gt;URL to an image attached to the shared post.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td data-th=&quot;Property&quot;&gt;&lt;code&gt;og:type&lt;/code&gt;&lt;/td&gt;
      &lt;td data-th=&quot;Content&quot;&gt;A string that indicates the type of the web page. You can find one that is suitable for your web page &lt;a href=&quot;https://developers.facebook.com/docs/reference/opengraph/&quot;&gt;here&lt;/a&gt;.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These meta tags provide semantic information to crawlers from social sites,
like &lt;a href=&quot;https://www.facebook.com/&quot; rel=&quot;noopener&quot;&gt;Facebook&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;learn-more&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#learn-more&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To learn more about things you can attach to the post on Facebook, visit the
official Open Graph Protocol site.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://ogp.me/&quot; rel=&quot;noopener&quot;&gt;ogp.me&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;validate-rich-snippets-2&quot;&gt;Validate rich snippets &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#validate-rich-snippets-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To validate your markup on Facebook, you can use tools such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.facebook.com/tools/debug/&quot; rel=&quot;noopener&quot;&gt;Debugger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;use-twitter-cards-to-provide-rich-snippets-on-twitter&quot;&gt;Use Twitter Cards to provide rich snippets on Twitter &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#use-twitter-cards-to-provide-rich-snippets-on-twitter&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://dev.twitter.com/cards/overview&quot; rel=&quot;noopener&quot;&gt;Twitter Cards&lt;/a&gt; are an extension to the
Open &lt;a href=&quot;https://twitter.com/&quot; rel=&quot;noopener&quot;&gt;Graph Protocol applicable for Twitter&lt;/a&gt;. They allow
you to add media attachments like images and video to Tweets with a link to
your web page. By adding the appropriate metadata, Tweets with links to your
page will have a card added that includes the rich detail you&#39;ve added.&lt;/p&gt;
&lt;h3 id=&quot;use-twitter-namespaced-meta-tags-to-describe-metadata&quot;&gt;Use &lt;code&gt;twitter:&lt;/code&gt; namespaced meta tags to describe metadata &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#use-twitter-namespaced-meta-tags-to-describe-metadata&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To get a Twitter Card working, &lt;a href=&quot;https://cards-dev.twitter.com/validator&quot; rel=&quot;noopener&quot;&gt;your domain must be
approved&lt;/a&gt; and must
contain a meta tag that has &lt;code&gt;twitter:card&lt;/code&gt; as the &lt;code&gt;name&lt;/code&gt; attribute instead of
&lt;code&gt;property&lt;/code&gt; attribute.&lt;/p&gt;
&lt;p&gt;Here&#39;s a quick example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og: http://ogp.me/ns#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;X-UA-Compatible&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;IE=edge&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;width=device-width, initial-scale=1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://fonts.googleapis.com/icon?family=Material+Icons&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://code.getmdl.io/1.2.1/material.indigo-pink.min.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;defer&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://code.getmdl.io/1.2.1/material.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;      &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Enjoy Fireworks&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Fireworks are beautiful. This article explains how beautiful fireworks are.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://developers.google.com/web/imgs/fireworks.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:url&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/discovery-and-distribution/optimizations-for-crawlers/social-sites.html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:type&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;website&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;twitter:card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;summary_large_image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;twitter:site&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;agektmr&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;By assigning the Twitter id to the value of twitter:site, Twitter embeds this
information in the shared post so that people can easily engage with the page
owner.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Twitter card.&quot; decoding=&quot;async&quot; height=&quot;868&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 519px) 519px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=964 964w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/bLzeCLmIZlkkdF2xKueg.png?auto=format&amp;w=1038 1038w&quot; width=&quot;519&quot; /&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;learn-more-2&quot;&gt;Learn more &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#learn-more-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To learn more about Twitter Cards, visit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.twitter.com/cards&quot; rel=&quot;noopener&quot;&gt;Twitter&#39;s developer site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;validate-rich-snippets-3&quot;&gt;Validate rich snippets &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#validate-rich-snippets-3&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;To validate your markup, Twitter provides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cards-dev.twitter.com/validator&quot; rel=&quot;noopener&quot;&gt;Card Validator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-best-practice&quot;&gt;The Best Practice &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/social-discovery/#the-best-practice&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Given all three options, the best thing you can do is to include them all in
your web page. Here&#39;s an example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- namespace declaration --&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og: http://ogp.me/ns#&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define microdata scope and type --&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemscope&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemtype&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;http://schema.org/Article&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Social Site Example&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define ogp and itemprop of microdata in one line --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:title&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Enjoy Fireworks&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define ogp image --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://developers.google.com/web/imgs/fireworks.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- use link[href] to define image url for microdata --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;//developers.google.com/web/imgs/fireworks.jpg&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define ogp and itemprop of microdata in one line --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:url&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://example.com/discovery-and-distribution/optimizations-for-crawlers/social-sites2.html&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define ogp type --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:type&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;website&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define twitter cards type --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;twitter:card&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;summary_large_image&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define site&#39;s owner twitter id --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;twitter:site&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;agektmr&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- define description for ogp and itemprop of microdata in one line --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;property&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;og:description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;itemprop&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Fireworks are beautiful. This article explains how beautiful fireworks are.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- general description (separate with ogp and microdata) --&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;description&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;          &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;Fireworks are beautiful. This article explains how beautiful fireworks are.&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;http-equiv&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;X-UA-Compatible&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;IE=edge&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;viewport&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;width=device-width, initial-scale=1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://fonts.googleapis.com/icon?family=Material+Icons&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://code.getmdl.io/1.2.1/material.indigo-pink.min.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;defer&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://code.getmdl.io/1.2.1/material.min.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;br /&gt;      &lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;        &lt;span class=&quot;token property&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2em&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Notice that microdata and OGP share some markup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;itemscope&lt;/code&gt; is located at &lt;code&gt;head&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; are shared between microdata and OGP&lt;/li&gt;
&lt;li&gt;&lt;code&gt;itemprop=&amp;quot;image&amp;quot;&lt;/code&gt; is using &lt;code&gt;link&lt;/code&gt; tag with &lt;code&gt;href&lt;/code&gt; attribute instead of
reusing &lt;code&gt;meta&lt;/code&gt; tag with &lt;code&gt;property=&amp;quot;og:image&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lastly, make sure to validate that your web page appears as expected on each
social site before publishing.&lt;/p&gt;
</content>
    <author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>Introducing WebSockets - Bringing Sockets to the Web</title>
    <link href="https://web.dev/websockets-basics/"/>
    <updated>2012-10-20T00:00:00Z</updated>
    <id>https://web.dev/websockets-basics/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;the-problem-low-latency-client-server-and-server-client-connections&quot;&gt;The problem: Low latency client-server and server-client connections &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#the-problem-low-latency-client-server-and-server-client-connections&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The web has been largely built around the so-called request/response paradigm of HTTP. A client loads up a web page and then nothing happens until the user clicks onto the next page. Around 2005, AJAX started to make the web feel more dynamic. Still, all HTTP communication was steered by the client, which required user interaction or periodic polling to load new data from the server.&lt;/p&gt;
&lt;p&gt;Technologies that enable the server to send data to the client in the very moment when it knows that new data is available have been around for quite some time. They go by names such as &#39;Push&#39; or &lt;a href=&quot;http://en.wikipedia.org/wiki/Comet_(programming)&quot; rel=&quot;noopener&quot;&gt;&#39;Comet&#39;&lt;/a&gt;. One of the most common hacks to create the illusion of a server initiated connection is called long polling. With long polling, the client opens an HTTP connection to the server which keeps it open until sending response. Whenever the server actually has new data it sends the response (other techniques involve &lt;a href=&quot;http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/Socket.html&quot; rel=&quot;noopener&quot;&gt;Flash&lt;/a&gt;, &lt;a href=&quot;http://cometdaily.com/2007/12/27/a-standards-based-approach-to-comet-communication-with-rest/&quot; rel=&quot;noopener&quot;&gt;XHR multipart&lt;/a&gt; requests and so called &lt;a href=&quot;http://cometdaily.com/2007/10/25/http-streaming-and-internet-explorer/&quot; rel=&quot;noopener&quot;&gt;htmlfiles&lt;/a&gt;).
Long polling and the other techniques work quite well. You use them every day in applications such as GMail chat.&lt;/p&gt;
&lt;p&gt;However, all of these work-arounds share one problem: They carry the overhead of HTTP, which doesn&#39;t make them well suited for low latency applications. Think multiplayer first person shooter games in the browser or any other online game with a realtime component.&lt;/p&gt;
&lt;h2 id=&quot;introducing-websocket-bringing-sockets-to-the-web&quot;&gt;Introducing WebSocket: Bringing sockets to the web &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#introducing-websocket-bringing-sockets-to-the-web&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;http://dev.w3.org/html5/websockets/&quot; rel=&quot;noopener&quot;&gt;WebSocket&lt;/a&gt; specification defines an API establishing &amp;quot;socket&amp;quot; connections between a web browser and a server. In plain words: There is an persistent connection between the client and the server and both parties can start sending data at any time.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#getting-started&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You open up a WebSocket connection simply by calling the WebSocket constructor:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; connection &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WebSocket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;ws://html5rocks.websocket.org/echo&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;soap&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;xmpp&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Notice the &lt;code&gt;ws:&lt;/code&gt;. This is the new URL schema for WebSocket connections. There is also
&lt;code&gt;wss:&lt;/code&gt; for secure WebSocket connection the same way &lt;code&gt;https:&lt;/code&gt; is used for secure HTTP
connections.&lt;/p&gt;
&lt;p&gt;Attaching some event handlers immediately to the connection allows you to know when the connection is opened, received incoming messages, or there is an error.&lt;/p&gt;
&lt;p&gt;The second argument accepts optional sub-protocols. It can be a string or an array of strings. Each string should represent a sub-protocol name and server accepts only one of passed sub-protocols in the array. Accepted sub-protocol can be determined by accessing &lt;code&gt;protocol&lt;/code&gt; property of WebSocket object.&lt;/p&gt;
&lt;p&gt;The sub-protocol names must be one of registered sub-protocol names in &lt;a href=&quot;http://www.iana.org/assignments/websocket/websocket.xml&quot; rel=&quot;noopener&quot;&gt;IANA registry&lt;/a&gt;. There is currently only one sub-protocol name (soap) registered as of February 2012.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// When the connection is open, send some data to the server&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onopen&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Ping&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Send the message &#39;Ping&#39; to the server&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Log errors&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onerror&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;WebSocket Error &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Log messages from the server&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Server: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;communicating-with-the-server&quot;&gt;Communicating with the server &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#communicating-with-the-server&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As soon as we have a connection to the server (when the &lt;code&gt;open&lt;/code&gt; event is fired) we can start sending data to the server using the &lt;code&gt;send(&#39;your message&#39;)&lt;/code&gt; method on the connection object. It used to support only strings, but in the latest spec it now can send binary messages too. To send binary data, you can use either &lt;code&gt;Blob&lt;/code&gt; or &lt;code&gt;ArrayBuffer&lt;/code&gt; object.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Sending String&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;your message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Sending canvas ImageData as ArrayBuffer&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; img &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; canvas_context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getImageData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;320&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; binary &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;img&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; img&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;binary&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; img&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;binary&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Sending file as Blob&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; file &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;input[type=&quot;file&quot;]&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;files&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Equally the server might send us messages at any time. Whenever this happens the &lt;code&gt;onmessage&lt;/code&gt; callback fires. The callback receives an event object and the actual message is accessible via the &lt;code&gt;data&lt;/code&gt; property.&lt;/p&gt;
&lt;p&gt;WebSocket can also receive binary messages in the latest spec. Binary frames can be received in &lt;code&gt;Blob&lt;/code&gt; or &lt;code&gt;ArrayBuffer&lt;/code&gt; format. To specify the format of the received binary, set the binaryType property of WebSocket object to either &#39;blob&#39; or &#39;arraybuffer&#39;. The default format is &#39;blob&#39;. (You don&#39;t have to align binaryType param on sending.)&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Setting binaryType to accept received binary as either &#39;blob&#39; or &#39;arraybuffer&#39;&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;binaryType &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;arraybuffer&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;byteLength&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ArrayBuffer object if binary&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Another newly added feature of WebSocket is extensions. Using extensions, it will be possible to send frames &lt;a href=&quot;http://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-05&quot; rel=&quot;noopener&quot;&gt;compressed&lt;/a&gt;, &lt;a href=&quot;http://tools.ietf.org/html/draft-tamplin-hybi-google-mux-02&quot; rel=&quot;noopener&quot;&gt;multiplexed&lt;/a&gt;, etc. You can find server accepted extensions by examining the extensions property of the WebSocket object after the open event. There is no officially published extensions spec just yet as of February 2012.&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Determining accepted extensions&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;connection&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;extensions&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;cross-origin-communication&quot;&gt;Cross-origin communication &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#cross-origin-communication&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Being a modern protocol, cross origin communication is baked right into WebSocket. While you should still make sure only to communicate with clients and servers that you trust, WebSocket enables communication between parties on any domain. The server decides whether to make its service available to all clients or only those that reside on a set of well defined domains.&lt;/p&gt;
&lt;h2 id=&quot;proxy-servers&quot;&gt;Proxy servers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#proxy-servers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every new technology comes with a new set of problems. In the case of WebSocket it is the compatibility with proxy servers which mediate HTTP connections in most company networks. The WebSocket protocol uses the HTTP upgrade system (which is normally used for HTTP/SSL) to &#39;upgrade&#39; an HTTP connection to a WebSocket connection. Some proxy servers do not like this and will drop the connection. Thus, even if a given client uses the WebSocket protocol, it may not be possible to establish a connection. This makes the next section even more important :)&lt;/p&gt;
&lt;h2 id=&quot;use-websockets-today&quot;&gt;Use WebSockets today &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#use-websockets-today&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;WebSocket is still a young technology and not fully implemented in all browsers. However, you can use WebSocket today with libraries that use one of the fallbacks mentioned above whenever WebSocket is not available. A library that has become very popular in this domain is &lt;a href=&quot;http://socket.io/&quot; rel=&quot;noopener&quot;&gt;socket.io&lt;/a&gt; which comes with a client and a server implementation of the protocol and includes fallbacks (socket.io doesn&#39;t support binary messaging yet as of Februrary 2012). There are also commercial solutions such as &lt;a href=&quot;http://pusherapp.com/&quot; rel=&quot;noopener&quot;&gt;PusherApp&lt;/a&gt; which can be easily integrated into any web environment by providing a HTTP API to send WebSocket messages to clients. Due to the extra HTTP request there will always be extra overhead compared to pure WebSocket.&lt;/p&gt;
&lt;h2 id=&quot;the-server-side&quot;&gt;The server side &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#the-server-side&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Using WebSocket creates a whole new usage pattern for server side applications. While traditional server stacks such as LAMP are designed around the HTTP request/response cycle they often do not deal well with a large number of open WebSocket connections. Keeping a large number of connections open at the same time requires an architecture that receives high concurrency at a low performance cost. Such architectures are usually designed around either threading or so called non-blocking IO.&lt;/p&gt;
&lt;h3 id=&quot;server-side-implementations&quot;&gt;Server side implementations &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#server-side-implementations&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Node.js
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://socket.io/&quot; rel=&quot;noopener&quot;&gt;Socket.IO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Worlize/WebSocket-Node&quot; rel=&quot;noopener&quot;&gt;WebSocket-Node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/einaros/ws&quot; rel=&quot;noopener&quot;&gt;ws&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Java
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eclipse.org/jetty/&quot; rel=&quot;noopener&quot;&gt;Jetty&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ruby
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/igrigorik/em-websocket&quot; rel=&quot;noopener&quot;&gt;EventMachine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Python
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/pywebsocket/&quot; rel=&quot;noopener&quot;&gt;pywebsocket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/facebook/tornado&quot; rel=&quot;noopener&quot;&gt;Tornado&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Erlang
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/michilu/shirasu&quot; rel=&quot;noopener&quot;&gt;Shirasu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;C++
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://git.warmcat.com/cgi-bin/cgit/libwebsockets/&quot; rel=&quot;noopener&quot;&gt;libwebsockets&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;.NET
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://superwebsocket.codeplex.com/&quot; rel=&quot;noopener&quot;&gt;SuperWebSocket&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;protocol-versions&quot;&gt;Protocol versions &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#protocol-versions&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The wire protocol (a handshake and the data transfer between client and server) for WebSocket is now &lt;a href=&quot;http://tools.ietf.org/html/rfc6455&quot; rel=&quot;noopener&quot;&gt;RFC6455&lt;/a&gt;. The latest Chrome and Chrome for Android are fully compatible with RFC6455 including binary messaging. Also, Firefox will be compatible on version 11, Internet Explorer on version 10. You can still use older protocol versions but it is not recommended since they are known to be vulnerable. If you have server implementations for older versions of WebSocket protocol, we recommend you to upgrade it to the latest version.&lt;/p&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use cases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#use-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Use WebSocket whenever you need a truly low latency, near realtime connection between the client and the server. Keep in mind that this might involve rethinking how you build your server side applications with a new focus on technologies such as event queues. Some example use cases are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multiplayer online games&lt;/li&gt;
&lt;li&gt;Chat applications&lt;/li&gt;
&lt;li&gt;Live sports ticker&lt;/li&gt;
&lt;li&gt;Realtime updating social streams&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;demos&quot;&gt;Demos &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#demos&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://labs.dinahmoe.com/plink/&quot; rel=&quot;noopener&quot;&gt;Plink&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://paintwith.me/&quot; rel=&quot;noopener&quot;&gt;Paint With Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://connorhd.co.uk/project/pixelatr/&quot; rel=&quot;noopener&quot;&gt;Pixelatr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.dashed.com/&quot; rel=&quot;noopener&quot;&gt;Dashed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://scrabb.ly/&quot; rel=&quot;noopener&quot;&gt;Massively multiplayer online crossword&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.websockets.org/echo.html&quot; rel=&quot;noopener&quot;&gt;Ping server (used in examples above)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://html5demos.com/web-socket&quot; rel=&quot;noopener&quot;&gt;HTML5demos sample&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;references&quot;&gt;References &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/websockets-basics/#references&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://websockets.spec.whatwg.org/&quot; rel=&quot;noopener&quot;&gt;The WebSocket API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://datatracker.ietf.org/doc/html/draft-ietf-hybi-thewebsocketprotocol-03&quot; rel=&quot;noopener&quot;&gt;The WebSocket Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WebSocket&quot; rel=&quot;noopener&quot;&gt;WebSockets - MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Malte Ubl</name>
    </author><author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
  
  <entry>
    <title>The Basics of Web Workers</title>
    <link href="https://web.dev/workers-basics/"/>
    <updated>2012-10-20T00:00:00Z</updated>
    <id>https://web.dev/workers-basics/</id>
    <content type="html" mode="escaped">&lt;h2 id=&quot;the-problem-javascript-concurrency&quot;&gt;The problem: JavaScript concurrency &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#the-problem-javascript-concurrency&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are a number of bottlenecks preventing interesting applications from being ported
(say, from server-heavy implementations) to client-side JavaScript. Some of these include
browser compatibility, static typing, accessibility, and performance. Fortunately, the latter
is quickly becoming a thing of the past as browser vendors rapidly improve the speed of their JavaScript engines.&lt;/p&gt;
&lt;p&gt;One thing that&#39;s remained a hindrance for JavaScript is actually the language itself. JavaScript is
a single-threaded environment, meaning multiple scripts cannot run at the same time. As an example, imagine
a site that needs to handle UI events, query and process large amounts of API data,
and manipulate the DOM. Pretty common, right? Unfortunately all of that can&#39;t be simultaneous
due to limitations in browsers&#39; JavaScript runtime. Script execution happens within a single thread.&lt;/p&gt;
&lt;p&gt;Developers mimic &#39;concurrency&#39; by using techniques like
&lt;code&gt;setTimeout()&lt;/code&gt;, &lt;code&gt;setInterval()&lt;/code&gt;, &lt;code&gt;XMLHttpRequest&lt;/code&gt;, and event handlers.
Yes, all of these features run asynchronously, but non-blocking doesn&#39;t necessarily mean concurrency.
Asynchronous events are processed after the current executing script has yielded. The good news is
that HTML5 gives us something better than these hacks!&lt;/p&gt;
&lt;h2 id=&quot;introducing-web-workers-bring-threading-to-javascript&quot;&gt;Introducing Web Workers: bring threading to JavaScript &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#introducing-web-workers-bring-threading-to-javascript&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;http://www.whatwg.org/specs/web-workers/current-work/&quot; rel=&quot;noopener&quot;&gt;Web Workers&lt;/a&gt; specification defines
an API for spawning background scripts in your web application. Web Workers allow you to do things like
fire up long-running scripts to handle computationally intensive tasks, but without blocking the UI or other
scripts to handle user interactions. They&#39;re going to help put and end to that nasty &#39;unresponsive script&#39; dialog
that we&#39;ve all come to love:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt=&quot;Unresponsive script dialog&quot; decoding=&quot;async&quot; height=&quot;100&quot; loading=&quot;lazy&quot; sizes=&quot;(min-width: 450px) 450px, calc(100vw - 48px)&quot; src=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&quot; srcset=&quot;https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=200 200w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=228 228w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=260 260w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=296 296w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=338 338w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=385 385w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=439 439w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=500 500w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=571 571w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=650 650w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=741 741w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=845 845w, https://web-dev.imgix.net/image/T4FyVKpzu4WKF1kBNvXepbi08t52/6hbuQjRRxR5TaLSCeJWV.gif?auto=format&amp;w=900 900w&quot; width=&quot;450&quot; /&gt;
&lt;figcaption&gt;Common unresponsive script dialog.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Workers utilize thread-like message passing to achieve parallelism. They&#39;re perfect for keeping your
UI refresh, performant, and responsive for users.&lt;/p&gt;
&lt;h3 id=&quot;types-of-web-workers&quot;&gt;Types of Web Workers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#types-of-web-workers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It&#39;s worth noting that the &lt;a href=&quot;http://www.whatwg.org/specs/web-workers/current-work/&quot; rel=&quot;noopener&quot;&gt;specification&lt;/a&gt; discusses
two kinds of Web Workers, &lt;a href=&quot;http://www.whatwg.org/specs/web-workers/current-work/#dedicated-workers-and-the-worker-interface&quot; rel=&quot;noopener&quot;&gt;Dedicated Workers&lt;/a&gt;
and &lt;a href=&quot;http://www.whatwg.org/specs/web-workers/current-work/#sharedworker&quot; rel=&quot;noopener&quot;&gt;Shared Workers&lt;/a&gt;. This article will
only cover dedicated workers. I&#39;ll refer to them as &#39;web workers&#39; or &#39;workers&#39; throughout.&lt;/p&gt;
&lt;h2 id=&quot;getting-started&quot;&gt;Getting started &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#getting-started&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Web Workers run in an isolated thread. As a result, the code that they execute needs to be contained in a separate file.
But before we do that, the first thing to do is create a new &lt;code&gt;Worker&lt;/code&gt; object in your main page. The
constructor takes the name of the worker script:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;task.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If the specified file exists, the browser will spawn a new worker thread, which is downloaded asynchronously.
The worker will not begin until the file has completely downloaded and executed. If the path to your worker returns an 404,
the worker will fail silently.&lt;/p&gt;
&lt;p&gt;After creating the worker, start it by calling the &lt;code&gt;postMessage()&lt;/code&gt; method:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Start the worker.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;communicating-with-a-worker-via-message-passing&quot;&gt;Communicating with a worker via message passing &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#communicating-with-a-worker-via-message-passing&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Communication between a work and its parent page is done using an event model and the &lt;code&gt;postMessage()&lt;/code&gt;
method. Depending on your browser/version, &lt;code&gt;postMessage()&lt;/code&gt; can accept either a string or JSON object as its single argument.
The latest versions of the modern browsers support passing a JSON object.&lt;/p&gt;
&lt;p&gt;Below is a example of using a string to pass &#39;Hello World&#39; to a worker in doWork.js. The worker simply returns
the message that is passed to it.&lt;/p&gt;
&lt;p&gt;Main script:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;doWork.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Worker said: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Hello World&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Send data to our worker.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;doWork.js (the worker):&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;When &lt;code&gt;postMessage()&lt;/code&gt; is called from the main page, our worker handles that message by
defining an &lt;code&gt;onmessage&lt;/code&gt; handler for the &lt;code&gt;message&lt;/code&gt; event. The message payload (in this case &#39;Hello World&#39;)
is accessible in &lt;code&gt;Event.data&lt;/code&gt;. Although this particular example isn&#39;t very exciting, it demonstrates
that &lt;code&gt;postMessage()&lt;/code&gt; is also your means for passing data back to the main thread. Convenient!&lt;/p&gt;
&lt;p&gt;Messages passed between the main page and workers are copied, not shared. For example, in the next example
the &#39;msg&#39; property of the JSON message is accessible in both locations. It appears that the object is
being passed directly to the worker even though it&#39;s running in a separate, dedicated space. In actuality, what is happening
is that the object is being serialized as it&#39;s handed to the worker, and subsequently, de-serialized on the other end. The page and
worker do not share the same instance, so the end result is that a duplicate is created on each pass. Most browsers implement this feature by automatically JSON encoding/decoding the value on either end.&lt;/p&gt;
&lt;p&gt;The following is a more complex example that passes messages using JSON objects.&lt;/p&gt;
&lt;p&gt;Main script:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sayHI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Say HI&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;unknownCmd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Send unknown command&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;onclick&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value javascript language-javascript&quot;&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Stop worker&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;output&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;output&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sayHI&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-property property&quot;&gt;&#39;cmd&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;start&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&#39;msg&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Hi&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// worker.terminate() from this script would also stop the worker.&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-property property&quot;&gt;&#39;cmd&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;stop&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&#39;msg&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;Bye&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;unknownCmd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-property property&quot;&gt;&#39;cmd&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;foobard&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&#39;msg&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;???&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;doWork2.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;result&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;doWork2.js:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;start&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;WORKER STARTED: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;stop&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;WORKER STOPPED: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;msg &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;br /&gt;                    &lt;span class=&quot;token string&quot;&gt;&#39;. (buttons will no longer work)&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Terminates the worker.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Unknown command: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; There are two ways to stop a worker: by calling &lt;code&gt;worker.terminate()&lt;/code&gt; from the main page or by calling &lt;code&gt;self.close()&lt;/code&gt; inside of the worker itself. &lt;/div&gt;&lt;/aside&gt;
&lt;h2 id=&quot;transferrable-objects&quot;&gt;Transferrable objects &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#transferrable-objects&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most browsers implement the &lt;a href=&quot;https://developer.chrome.com/blog/workers-arraybuffer/&quot; rel=&quot;noopener&quot;&gt;structured cloning&lt;/a&gt; algorithm, which allows you to pass more complex types in/out of Workers such as &lt;code&gt;File&lt;/code&gt;, &lt;code&gt;Blob&lt;/code&gt;, &lt;code&gt;ArrayBuffer&lt;/code&gt;, and JSON objects. However, when passing these types of data using
&lt;code&gt;postMessage()&lt;/code&gt;, a copy is still made. Therefore, if you&#39;re passing
a large 50MB file (for example), there&#39;s a noticeable overhead in getting
that file between the worker and the main thread.&lt;/p&gt;
&lt;p&gt;Structured cloning is great, but a copy can take
hundreds of milliseconds. To combat the perf hit, you can use &lt;a href=&quot;http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#transferable-objects&quot; rel=&quot;noopener&quot;&gt;Transferable Objects&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With Transferable Objects, data is transferred from one context to another. It is zero-copy, which vastly improves the performance of sending data to a Worker. Think of it as pass-by-reference if you&#39;re from the C/C++ world. However, unlike pass-by-reference, the &#39;version&#39; from the calling context is no longer available once transferred to the new context. For example, when transferring an ArrayBuffer from your main app to Worker, the original &lt;code&gt;ArrayBuffer&lt;/code&gt; is cleared and no longer usable. Its contents are (quiet literally) transferred to the Worker context.&lt;/p&gt;
&lt;p&gt;To use transferrable objects, use a slightly different signature of &lt;code&gt;postMessage()&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arrayBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;arrayBuffer&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;arrayBuffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; targetOrigin&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;arrayBuffer&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The worker case, the first argument is the data and the second is the
list of items that should be transferred. The first argument doesn&#39;t have
to be an &lt;code&gt;ArrayBuffer&lt;/code&gt; by the way. For example, it can be a JSON
object:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; int8View&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;moreData&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; anotherBuffer&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;br /&gt;                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;int8View&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; anotherBuffer&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The important point being: the second argument must be an array of &lt;code&gt;ArrayBuffer&lt;/code&gt;s.
This is your list of transferrable items.&lt;/p&gt;
&lt;p&gt;For more information on transferrables, see &lt;a href=&quot;https://developer.chrome.com/blog/transferable-objects-lightning-fast/&quot; rel=&quot;noopener&quot;&gt;our post at developer.chrome.com&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-worker-environment&quot;&gt;The worker environment &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#the-worker-environment&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;worker-scope&quot;&gt;Worker scope &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#worker-scope&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In the context of a worker, both &lt;code&gt;self&lt;/code&gt; and &lt;code&gt;this&lt;/code&gt; reference the global scope
for the worker. Thus, the previous example could also be written as:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;start&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;WORKER STARTED: &#39;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;stop&#39;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Alternatively, you could set the &lt;code&gt;onmessage&lt;/code&gt; event handler directly
(though &lt;code&gt;addEventListener&lt;/code&gt; is always encouraged by JavaScript ninjas).&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;features-available-to-workers&quot;&gt;Features available to workers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#features-available-to-workers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Due to their multithreaded behavior, Web Workers only has access to a subset of JavaScript&#39;s features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;navigator&lt;/code&gt; object&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;location&lt;/code&gt; object (read-only)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;XMLHttpRequest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setTimeout()/clearTimeout()&lt;/code&gt; and &lt;code&gt;setInterval()/clearInterval()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://web.dev/appcache-beginner/&quot;&gt;Application Cache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Importing external scripts using the &lt;code&gt;importScripts()&lt;/code&gt; method&lt;/li&gt;
&lt;li&gt;Spawning other web workers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Workers do NOT have access to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The DOM (it&#39;s not thread-safe)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;window&lt;/code&gt; object&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;document&lt;/code&gt; object&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;parent&lt;/code&gt; object&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;loading-external-scripts&quot;&gt;Loading external scripts &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#loading-external-scripts&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You can load external script files or libraries into a worker with the &lt;code&gt;importScripts()&lt;/code&gt; function. The method
takes zero or more strings representing the filenames for the resources to import.&lt;/p&gt;
&lt;p&gt;This example loads &lt;code&gt;script1.js&lt;/code&gt; and &lt;code&gt;script2.js&lt;/code&gt; into the worker:&lt;/p&gt;
&lt;p&gt;worker.js:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;importScripts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;script1.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;importScripts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;script2.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Which can also be written as a single import statement:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;importScripts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;script1.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;script2.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;subworkers&quot;&gt;Subworkers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#subworkers&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Workers have the ability to spawn child workers. This is great for further breaking up large
tasks at runtime. However, subworkers come with a few caveats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subworkers must be hosted within the same origin as the parent page.&lt;/li&gt;
&lt;li&gt;URIs within subworkers are resolved relative to their parent worker&#39;s location (as opposed to the main page).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Keep in mind most browsers spawn separate processes for each worker. Before you go spawning a worker
farm, be cautious about hogging too many of the user&#39;s system resources. One reason for this is that messages
passed between main pages and workers are copied, not shared. See Communicating with a Worker via Message Passing.&lt;/p&gt;
&lt;p&gt;For an sample of how to spawn a subworker, see &lt;a href=&quot;http://www.whatwg.org/specs/web-workers/current-work/#delegation&quot; rel=&quot;noopener&quot;&gt;the example&lt;/a&gt;
in the specification.&lt;/p&gt;
&lt;h2 id=&quot;inline-workers&quot;&gt;Inline workers &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#inline-workers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What if you want to create your worker script on the fly, or create a self-contained
page without having to create separate worker files? With &lt;code&gt;Blob()&lt;/code&gt;,
you can &amp;quot;inline&amp;quot; your worker in the same HTML file as your main logic by creating
a URL handle to the worker code as a string:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; blob &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Blob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token string&quot;&gt;&quot;onmessage = function(e) { postMessage(&#39;msg from worker&#39;); }&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Obtain a blob URL reference to our worker &#39;file&#39;.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; blobURL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blobURL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// e.data == &#39;msg from worker&#39;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Start the worker.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h3 id=&quot;blob-urls&quot;&gt;Blob URLs &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#blob-urls&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The magic comes with the call to &lt;a href=&quot;http://dev.w3.org/2006/webapi/FileAPI/#dfn-createObjectURL&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;window.URL.createObjectURL()&lt;/code&gt;&lt;/a&gt;.
This method creates a simple URL string which can be used to reference data stored in a
DOM &lt;code&gt;File&lt;/code&gt; or &lt;code&gt;Blob&lt;/code&gt; object. For example:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;blob&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;http&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;localhost&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;c745ef73&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ece9&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;46da&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;8f66&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;ebes574789b1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Blob URLs are unique and last for the lifetime of your application (e.g. until the &lt;code&gt;document&lt;/code&gt;
is unloaded). If you&#39;re creating many Blob URLs, it&#39;s a good idea to release references that are
no longer needed. You can explicitly release a Blob URLs by passing it to&lt;a href=&quot;http://dev.w3.org/2006/webapi/FileAPI/#dfn-revokeObjectURL&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;window.URL.revokeObjectURL()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;revokeObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blobURL&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In Chrome, there&#39;s a nice page to view all of the created blob URLs: &lt;code&gt;chrome://blob-internals/&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;full-example&quot;&gt;Full example &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#full-example&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Taking this one step further, we can get clever with how the worker&#39;s JS
code is inlined in our page. This technique uses a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag
to define the worker:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;meta&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;utf-8&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;worker1&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;javascript/worker&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// This script won&#39;t be parsed by JS engines&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// because its type is javascript/worker.&lt;/span&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;msg from worker&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token comment&quot;&gt;// Rest of your worker code goes here.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token comment&quot;&gt;// Use a fragment: browser will only render/reflow once.&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; fragment &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createDocumentFragment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    fragment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createTextNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;    fragment&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;br&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;#log&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fragment&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; blob &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Blob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;#worker1&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Received: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Start the worker.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In my opinion, this new approach is a bit cleaner and more legible.
It defines a script tag with &lt;code&gt;id=&amp;quot;worker1&amp;quot;&lt;/code&gt; and
&lt;code&gt;type=&#39;javascript/worker&#39;&lt;/code&gt; (so the browser doesn&#39;t parse the JS). That code is extracted as a
string using &lt;code&gt;document.querySelector(&#39;#worker1&#39;).textContent&lt;/code&gt; and passed to
&lt;code&gt;Blob()&lt;/code&gt; to create the file.&lt;/p&gt;
&lt;h3 id=&quot;loading-external-scripts-2&quot;&gt;Loading external scripts &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#loading-external-scripts-2&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When using these techniques to inline your worker code,
&lt;code&gt;importScripts()&lt;/code&gt; will only work if you supply an absolute URI. If
you attempt to pass a relative URI, the browser will complain with a security
error. The reason being: the worker (now created from a blob URL) will be resolved with a
&lt;code&gt;blob:&lt;/code&gt; prefix, while your app will be running from a different (presumably &lt;code&gt;http://&lt;/code&gt;)
scheme. Hence, the failure will be due to cross origin restrictions.&lt;/p&gt;
&lt;p&gt;One way to utilize &lt;code&gt;importScripts()&lt;/code&gt; in an inline worker is to
&amp;quot;inject&amp;quot; the current url of your main script is running from by passing it
to the inline worker and constructing the absolute URL manually. This
will insure the external script is imported from the same origin. Assuming your
main app is running from &lt;code&gt;http://example.com/index.html&lt;/code&gt;:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;...&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;worker2&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;javascript/worker&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; data &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;href&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;index.html&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;index &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;importScripts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;engine.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;window&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;bb&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getBlob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;b&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;handling-errors&quot;&gt;handling errors &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#handling-errors&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As with any JavaScript logic, you&#39;ll want to handle any errors that are thrown in your web workers.
If an error occurs while a worker is executing, the an &lt;code&gt;ErrorEvent&lt;/code&gt; is fired. The interface contains three useful properties for figuring out what went wrong: &lt;code&gt;filename&lt;/code&gt; - the name of the worker script
that caused the error, &lt;code&gt;lineno&lt;/code&gt; - the line number where the error occurred, and &lt;code&gt;message&lt;/code&gt; - a meaningful
description of the error. Here is an example of setting up an &lt;code&gt;onerror&lt;/code&gt; event handler to print the properties of the error:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;output&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token special-attr&quot;&gt;&lt;span class=&quot;token attr-name&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token value css language-css&quot;&gt;&lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; red&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;output&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;output&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;result&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;output&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;error&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token string&quot;&gt;&#39;ERROR: Line &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lineno&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39; in &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;message&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;onMsg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;result&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;textContent &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; worker &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Worker&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;workerWithError.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onMsg&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;error&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onError&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;worker&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Start worker without a message.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: workerWithError.js tries to perform 1/x, where x is undefined.&lt;/p&gt;
&lt;div class=&quot;example&quot;&gt;
&lt;button onclick=&quot;startErrorWorker()&quot;&gt;Run it&lt;/button&gt;
&lt;output id=&quot;error&quot; style=&quot;color:red;&quot;&gt;&lt;/output&gt;
&lt;output id=&quot;result2&quot;&gt;&lt;/output&gt;
&lt;/div&gt;
&lt;p&gt;workerWithError.js:&lt;/p&gt;
&lt;div&gt;&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;message&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token function&quot;&gt;postMessage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Intentional error.&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;&lt;h2 id=&quot;a-word-on-security&quot;&gt;A word on security &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#a-word-on-security&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;restrictions-with-local-access&quot;&gt;Restrictions with local access &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#restrictions-with-local-access&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Due to Google Chrome&#39;s security restrictions, workers will not run locally (e.g. from &lt;code&gt;file://&lt;/code&gt;) in the latest
versions of the browser. Instead, they fail silently!  To run your app from the &lt;code&gt;file://&lt;/code&gt; scheme, run Chrome with the
&lt;code&gt;--allow-file-access-from-files&lt;/code&gt; flag set.&lt;/p&gt;
&lt;aside class=&quot;aside flow bg-state-info-bg color-state-info-text&quot;&gt;&lt;div class=&quot; flow&quot;&gt; It is not recommended to run your primary browser with this flag set. It should only be used for testing purposes and not regular browsing. &lt;/div&gt;&lt;/aside&gt;
&lt;p&gt;Other browsers do not impose the same restriction.&lt;/p&gt;
&lt;h3 id=&quot;same-origin-considerations&quot;&gt;Same-origin considerations &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#same-origin-considerations&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Worker scripts must be external files with the same scheme as their calling page. Thus,
you cannot load a script from a &lt;code&gt;data:&lt;/code&gt; URL or &lt;code&gt;javascript:&lt;/code&gt; URL, and an &lt;code&gt;https:&lt;/code&gt;
page cannot start worker scripts that begin with &lt;code&gt;http:&lt;/code&gt; URLs.&lt;/p&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use cases &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#use-cases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So what kind app would utilize web workers? Here are a few more ideas to get your brain churning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prefetching and/or caching data for later use.&lt;/li&gt;
&lt;li&gt;Code syntax highlighting or other real-time text formatting.&lt;/li&gt;
&lt;li&gt;Spell checker.&lt;/li&gt;
&lt;li&gt;Analyzing video or audio data.&lt;/li&gt;
&lt;li&gt;Background I/O or polling of webservices.&lt;/li&gt;
&lt;li&gt;Processing large arrays or humungous JSON responses.&lt;/li&gt;
&lt;li&gt;Image filtering in &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Updating many rows of a local web database.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more information about use cases involving the Web Workers API, visit &lt;a href=&quot;https://web.dev/workers-overview/#use-cases&quot;&gt;Workers Overview&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;demos&quot;&gt;Demos &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#demos&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://html5demos.com/worker&quot; rel=&quot;noopener&quot;&gt;HTML5demos sample&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;references&quot;&gt;References &lt;a class=&quot;headline-link&quot; href=&quot;https://web.dev/workers-basics/#references&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://html.spec.whatwg.org/multipage/workers.html&quot; rel=&quot;noopener&quot;&gt;Web Workers&lt;/a&gt; specification&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/Web_Workers_API/Using_web_workers&quot; rel=&quot;noopener&quot;&gt;&amp;quot;Using web workers&amp;quot;&lt;/a&gt; from the Mozilla Developer Network Web Docs.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://dev.opera.com/articles/view/web-workers-rise-up/&quot; rel=&quot;noopener&quot;&gt;&amp;quot;Web Workers rise up!&amp;quot;&lt;/a&gt; from Dev.Opera&lt;/li&gt;
&lt;/ul&gt;
</content>
    <author>
      <name>Malte Ubl</name>
    </author><author>
      <name>Eiji Kitamura</name>
    </author>
  </entry>
</feed>
