 Hi, everyone. I'm Eiji. Welcome to the workshop, Learn How to Implement Passkeys with Form Auto Fill in a Web App. In this workshop, you will learn how to turn an existing website that has a password-based authentication mechanism into a passkey-based one. By the end of this workshop, you will learn how to create a passkey, how to authenticate a user with a passkey, and how to enable a form suggest a passkey as a sign-in option. If you are not familiar with passkeys yet, check out my session, Passkeys a Simpler and Safer Sign In. To get started with this workshop, please open the Code Lab page in the description. Check the What You Need section on the first page and confirm that your environment matches what is needed. To set up the environment, all you need is a browser. Click on the Project English link, then press the Remix button at the top right corner. Glitch is an online code editor where you will code. Nice thing about Glitch is that it automatically runs your code, so you can easily check if everything is working as intended. Let's look at the initial state of the web app in a preview window. You can enter a random username and a random password to sign in. All you have here is your name, an edit button, and a Sign Out button. Initially, the name is the same as your username, but by clicking on the Edit button, you can change it to whatever you want. This is just a display name, so changing the name doesn't affect your username. And let me show you what you will have by the end of this workshop. You sign into Passkeys Code Lab Glitch.me using your username and password. And you get the option to create a passkey here. Click it. Continue to create a passkey. Do a touch ID. And a new passkey is created. It's listed here. Let's sign out. On the Sign In form, you see the passkey is listed as part of the Autofill dialog. Click it. And you'll see the touch ID authenticate. And you are signed in with just a breeze. This is what you are going to build. If you're ready, let's dive in. On this page, you will add an ability to create a passkey by creating the register credential function. To create the function, you first add a placeholder. Copy the code and open public slash client.js in Glitch. Find the to do command where the page name and the section name matches. And paste the code onto Glitch. To create a passkey, we'll use an API called WebAuthn, namely Navigator Credentials Create. But before doing so, we'll obtain the challenge and other options from the server endpoint. Luckily, we already have the server side done. You can just fetch information from an endpoint. And the JSON object you receive from the server looks something like this. There's a lot of stuff in there. I will not go over all of them, but let me explain some important ones. User ID is a user's unique ID. This value must be an array buffer that doesn't include personal identifiable information, such as email addresses or usernames. RPID represents a relying party's ID, which is your website's domain. Exclude Credentials provides a list of already registered credential IDs to prevent registration of the same device twice. AuthenticatorSelection.authenticator attachment indicates that you want an authenticator that embedded in the platform device so the user won't be prompted to insert something like a USB security key. Set this to Platform. AuthenticatorSelection.requireResidentKey serves to make the passkey a discoverable credential. This makes the passkey compatible with Outfill. Set this to True. AuthenticatorSelection.userVerification indicates whether a user verification that uses the device's screen lock is required, preferred, or discouraged. Set this to Preferred or omit it because it's the default value. This requests user verification only when the device is capable. Having the options ready, let's create a credential. Before passing the options, you will need to make sure that encoded parameters are gracefully decoded to array buffer, namely user.id and challenge, and the IDs included in the Exclude Credentials array. You can do that with this code snippet. On the next line, set AuthenticatorSelection.authenticator attachment to Platform and AuthenticatorSelection.requireResidentKey to True. Call the NavigatorCredentials.create to invoke WebAuthn and wait for the user to interact with the screen lock to create a passkey. Note that the screen lock can use biometric authentication such as touching a fingerprint sensor or using facial recognition. But the biometric data stays on the device and is never transmitted anywhere. It's only used locally to verify the user. After the user verification, send the credential to the server endpoint to save the public key. The resulting credential should look something like this. The ID indicates the credential's ID. Use it as a key to manage credentials on the server. Don't forget to encode the array buffer parameters and construct an object. And send the JSON object to the server. You have now finished implementing the registered credential function. Moving on to the next page, you will build a UI to register and manage passkey credentials. As you can see from this screenshot, you will add a list of registered passkeys and a red create a passkey button. First, let's add placeholder HTML. Copy the HTML. Paste it to the section in views-home.hml in Grinch. The section tag is where your passkeys are displayed. The p tag is there to display a message when passkeys are not available on the browser. And the mwc-button tag is a web component that displays a create a passkey button. Next is feature detection, that is checking for passkey support. We will display the create a passkey button only when the device supports passkeys. To do so, we'll check three things. First is window.publickeycredential, to check if WebAuthn is supported. The second is publickeycredential, is user verifying platform authenticator available, which is to check whether the device supports creating a passkey. The third is publickeycredential, is conditional mediation available, to check whether the browser supports a feature called conditional UI. Conditional UI allows the browser to display passkeys in the autofill dialog. Check if all these objects are available in the browser. If they are, call them and check if they return true. In this case, they return a promise, so we will use promise all. Check if all the results return true. If true, display the create a passkey button. Otherwise, display a message saying that this device does not support passkeys. Now, we'll create the render credentials function to render registered passkeys in a list. Luckily, you already have a sober endpoint to fetch a list of credentials. Using that, we render the list. To render the HTML, we use libraries called lit and material web. As a bonus, this HTML comes with renaming and removing of the passkeys. All required code is already implemented. Please check them out if you are interested in learning how they work. Don't forget to call render credentials to render the list of passkeys on the initial page load. The next step is to create and register a passkey where we call the register credential function when the create a passkey button is pressed. Include the register credential in the import statement at the beginning of the script tag and load it. The register function is used to start and stop the loading UI while register credential function is in action. And finally, call the render credentials function to render the new list of credentials. The function throws a few different types of exceptions. If the name of the exception is an invalid state error, a passkey is already stored for this device. Tell the user that the device is already registered. If it's a not allowed error, the user has canceled the operation. You can gracefully ignore this exception. For other exceptions, examine the error type and show a user-friendly error message. Don't forget to add an event listener to the create a passkey button to invoke the register function. Okay, you have implemented all the required code for this page and you already have all the required code for passkey registration flow. Let's try it, open the preview window. We haven't implemented a signing flow yet. So just signing using your username and password. You see that create a passkey button. Click it to see a dialogue like this. Then a biometric authentication. And a new passkey is created and registered. If it doesn't work for you, please pause the video and go back to check what's missing. To authenticate with a passkey, we'll use the web authentication API navigator credentials get. Before doing so, we'll obtain the challenge and other options from the server endpoint, just like we did for creating a passkey. Again, we have the server side already implemented. Just fetch the information from the endpoint. And the JSON object you will receive looks something like this. Let me explain important parameters. Challenge is a server-generated array buffer that prevents replay attacks. In this code lab, you can expect to receive one from the previous fetch call. RPID is the domain of your website. It should match the one when the passkey is created. Allow credentials is used to find authenticators eligible for this authentication. Pass an empty array or leave it unspecified to let the browser show an account selector so that the user can pick an account. User verification is the same for a passkey creation. It indicates whether a user verification is required, preferred or discouraged. Set this to preferred or omit it as it's the default value. This request user verification only when the device is capable. Having the options ready, let's authenticate the user and get a credential. Before passing the options, you will need to make sure that encoded parameters are gracefully decoded to array buffer. In this case, challenge. And make sure that you pass an empty array to the allow credentials so that an account selector will be available. And call the navigator credentials get to invoke WebAuthn. The key here is that you add mediation conditional as an option. This option instructs the browser to suggest passkeys as part of the form autofill. This should be accompanied by an annotation in HTML. We'll get to it on the next page. Once the local user verification succeeds, you receive a credential. Send it to the server endpoint to verify the credential. The resulting credential should look something like this. Let me explain some of them. Client data JSON contains client information such as the challenge and the origin of the RP. Authenticator data contains authenticator information such as RPID. Signature is a signature the server should be able to verify using the saved public key. Don't forget to encode the array buffer parameters before creating an object. And finally, send it to the server. You have now finished implementing the authenticate function. At the final page, you will add passkeys to the browser autofill so users can sign in easily. By tapping on the username input field, an account selector will be displayed. Selecting an account will start an authentication. This feature is called the conditional UI, where passkeys are displayed as autofill items. This allows users to make a smooth transition from passwords to passkeys. To enable a conditional UI, add a WebAuthn token to an autocomplete attribute of the username input field. In combination with the option mediation conditional, you have added it to the navigator credentials get call. Copy this code snippet and override the HTML in views slash index HTML. Before calling the authenticate function, you need to import it. On authentication, we check public key credential and publickeycredential.e's conditional mediation available. When the feature detection is successful, call authenticate. This should happen as soon as the user lands so that the form autofill is displayed when the user taps on the username input field. When the user selects one of the accounts, the actual authentication flow starts. If the authentication is successful, the user is redirected to the home page and signed in. Now you have implemented a passkey authentication flow. Let's try it. As you have created a passkey earlier, you should be able to see it by tapping on the username input field. By tapping an account, an authentication dialog pops up, and you can sign in with biometric authentication. And you are signed in. Congratulations. You have finished implementing the entire flow of creating and authenticating with a passkey. I have gone through things quickly to show you how implementing passkeys works. But I encourage you to take your time to pause the video, inspect the code, and learn more in passkeys code lab. I'm looking forward to seeing your passkey implementation soon. Thank you for watching.