 My name is Sabine Borsé. I'm the product manager on the Chrome password manager team. Mike, Alexi, and I are here today to talk about making the sign-in experience easier and more secure for your users. Now, let's see. How many of you have ever had to use the Forgot password link on any website before? Sure, fans. OK, that's really a lot of people. Now, let's turn it around for a moment. How many of you have never had to use the Forgot password link? OK, no one. I totally understand. I think we've all been there. We've all needed to reset our passwords at some point. And this is what most sign-in screens look like. And when users land on these sign-in screens, they often don't remember which email address they used, which password they used, or if they used one of those buttons. And that's a lot of cognitive load for a task that could actually be quite simple, like signing into a website. And a Bloomberg study shows that 30% of help desk calls are password-related. And this is how it looks like when most people type in their credentials on their mobile phones. What do you think this number is? Yeah, it's the most popular password in 2015. And what do you think this is? Correct. This is the second most popular password in 2015. But the complexity to remember passwords does not only lead users to use weak passwords, such as password, or 123456. It also leads users to reuse the same password across lots of different sites. And that's, of course, a significant security risk. In fact, a study conducted by Verizon shows that 76% of account vulnerabilities were due to weak or stoned credentials. That means current ways to sign in are neither user-friendly nor really secure. But out of complexity comes opportunity. And that's what we want to focus on this talk today. We are going to talk about three solutions to help assist your users getting authenticated to your site. First, we'll start off with password autofill and how you can annotate your forms. There's just a few lines of code to really guarantee that your password forms are treated properly by password managers. And then Mike is going to show you how you can layer the Credential Management API on top of your existing sign-in system to allow your users to sign in with just one tap. And then Alexi is going to show you how you can use security keys as a second factor and additional layer of security for your alt system. OK. We have seen that current alt flows are broken for users. And password managers can actually be of great help here. They can remember all your passwords for you. And they also take out the need for you to type them, like we saw earlier. So that's great. And this is how it looks. When a user signs into a website, Chrome uses a bunch of heuristics to automatically detect a successful sign-in event. And then, as you could see here, prompts the user to save the password. And then when the user returns to the site, there is no need to remember or type anything anymore. The Credentials are just auto-filled, and the user can go straight to content. And this also works across your devices as long as you are signed in with the same Google account. And the best is it does not only work in Chrome across your devices, but also with your Android native apps. That means passwords that you have saved for a website in Chrome can be used to help you sign in to the respective Android native app and vice versa. And in order to enable this cross-platform experience for your users, you can use the Smart Lock for Passwords APIs for your Android native app. And then you can also do the mapping between your app and your website. OK, so Chrome is already doing a fantastic job today by helping users sign in more easily by assisting 8 billion successful sign-ins a month. And that's really great. And to a large extent, it should work without any extra work required from your site. But the system cannot be perfect. And every single time the system fails is a time that someone has to type their Credentials. But you can fix that by giving password managers hints to really ensure that your forms work properly. And these hints should also work across all modern browsers and password managers. Now, the system that's built into Chrome and most password managers is heuristics-based. And one thing that password managers care about is understanding what are and what are not the username and password fields on your forms. You basically look at the form, parse it, and try to extract meaning from it. And sometimes this is very straightforward. But sometimes this is rather difficult. And this form here is an example of a rather difficult case. We just don't know which of these text fields represents the username. That means we'll simply guess, and there is a decent chance that we'll guess incorrectly. But again, here, you can solve the problem by explicitly declaring your intent in the forms markup. And you can do that by adding autocomplete attributes to your forms to explaining the purpose of each field to password managers. And in this case, since we are talking about sign up forms here, you should also mark up your password field with autocomplete equals new password to prevent password managers from auto-filling previously saved credentials into your sign up form. Now, after your user is signed up, they also will sign in at some point, hopefully. And then you should again mark up your username field with autocomplete equals username, very straightforward. And then for the password field, you should use autocomplete equals current password. Now, from time to time, your users might want to change their password. And change password forms can contain both, the old and the new password. So here, you should use autocomplete equals current password and new password. Here, it's also important to include the user's username. You can do that, for example, in the hidden text field just to make sure that the correct username is being captured for the update. And when you mark up your forms like this, Chrome is also significantly more likely to auto-generate a new password for your users during account creation, which then hopefully keeps them at some point from using 1, 2, 3, 4, 5, 6. In fact, we've been experimenting with this feature for a while in our Canary, Dev, and Beta channels. OK, we have gone through this all pretty fast. But if you want to come back to it later, just check out these links. There are a lot of example forms using these autocomplete attributes. And then also check out the Smart Lock for passwords APIs for your Android native app. OK, to wrap this up, as you've seen, Autofill is really great. With just a few lines of simple code, you can fix so many of these issues for your users across the board. And that's really the foundation. But what about eliminating the sign-in screen altogether? That's where the Credential Management API comes in. And with that, I'm handing over to Mike who's now going to tell you more about that. Thank you. Thanks, Sabine. My name is Mike West. I am a software engineer on Chrome's security team. And I'm responsible in large part for the implementation of the API that we're going to talk about in just a moment. So if you have questions afterwards, I'm a good guy to catch. As you just heard, password managers today are grub goldbergian piles of heuristics. They certainly get to the right result, but they do it in a way that isn't quite as explicit as it could be. So in this image that you see to the side, if any of those strings break, or if that bird decides it doesn't actually want a cracker today, then you're not going to get your mouth wiped with this automatic napkin. And that would be quite sad. Password managers are quite similar. They piece together a picture of what's happening on a particular page by parsing through the markup, trying to assign meaning to all of the things on the page based on attributes that you've just heard about, but also based on their position, whether they're inside of a form, or not inside of a form. They then try to model user behavior by hooking into things like form submissions, and XHR, or fetch, in order to determine what the user is actually doing on the page, and how the browser or the password manager can assist the user. Now we do pretty well all things considered, but let's be clear, we are guessing, and sometimes we'll guessing correctly. Now of course, we guess more correctly more often when we have more information. So you should absolutely use the autocomplete attributes that Spina was just talking about. But wouldn't it be nice if we could avoid guessing entirely? If we could avoid all of the complexity around here and focus very simply on the thing that actually matters, that is the user's intention. The Credential Management API gives you, as a developer, the ability to integrate more deeply with the user's credential manager. You, as the developer of a website, understand how a user is actually using your site. You understand their intention, because you have a deep understanding of the meaning of everything on your page. You know whether they're signing in with the username and password. You know whether that sign-in was successful. More to the point, you know whether they're doing some sort of federated sign-in using Google, or Twitter, or Facebook, or any other identity provider. Password managers today simply have no understanding of these mechanisms. The browser sees a navigation, but has absolutely no understanding that that navigation is actually a sign-in event. In short, you can avoid the kind of fragile machinery that we've just talked about. You can pick up the napkin, and you can wipe your own mouth, creating a seamless experience for your users, getting them signed into your websites. Now, this quote from Kayak shows, I think, a good understanding of what users want and what developers want. Giving users a simple sign-in experience that is secure and seamless is incredibly important. No one likes typing passwords. No one likes sign-in forms. If we can get rid of them, or at least show them to users less often, I think pretty much everyone's going to be happy. Now, on the screen beside me, you'll see a list of companies who have already taken the napkin into their own hands by deploying bits and pieces of the Credential Management API into production. I'll show you some examples of the UX improvements that they've achieved as we walk through the nuts and the bolts of the API over the next few minutes, but don't take my word for it. You can actually experiment with this API today on your own websites. It's enabled by default in Chrome Canary, Dev, and Beta, and we plan to ship it to stable along with Chrome 51, which should be coming out later this year. It's a, I'm sorry, later this month. It's a really good time for you to start experimenting with this because it's still early days in the API, and since not many people are using it, it's a really good time for you to give feedback to us so that we understand your needs and we can ensure that the API is actually meeting those needs. So let's talk about the flows that folks generally have on their websites and how the Credential Management API can layer on top of those flows in order to give your users a better experience. Now, most developers that I've talked to have started with very simple and straightforward sign-in flows. The user types in a username and password, or the password manager fills it for them. They click Submit, and the form is posted as a top-level navigation to some landing page. The response sets a session cookie and boom, the user is signed in just the way that you're doing it today. Now, this is indeed quite simple, and it does work, but it has some drawbacks. The biggest, of course, is that navigating via a form submission means throwing away the current page entirely, redownloading the new page, the response, potentially redownloading new resources for that page, parsing through all of them, rendering, building a layout tree, and then painting. Now, it updates the entire page. It's slow, it can be janky and jarring for your users. You can create a significantly better sign-in experience if you start moving towards a more asynchronous mechanism that has the potential to improve the user's experience. So the notion of a progressive web app, for instance, is something you've probably heard a lot about at this conference. What I would suggest is that it's a good idea to build an application shell that renders some sort of loading graphic, while checking locally to determine whether or not the user can be signed in, whether credentials are available. If those credentials are available, then they can be posted to the back end using Fetch in order to sign the user in asynchronously without actually navigating them for one page to the other. Now, the response might contain a JSON blob filled with some useful information in order to render the rest of the page to give the user that signed-in experience, give them access to their data, and give them exactly what they want when going to your website. And they can do that without jarring the user through a janky full-page navigation. Now, the Credential Management API is tuned towards this kind of sign-in flow, but it can be layered fairly easily on top of a navigation-based flow as well, and we'll talk about that in just a moment. AliExpress is a great example of the kinds of flows that this API enables. It's a shopping application, so, of course, it's important for users to actually be signed in, because when they're signed in, they have access to their shopping cart, they can look at things that they've tried to purchase in the past, and most importantly, the purchase flow will actually work because all of the user's information is already there. They can buy the things that they want to buy and get on with their lives without actually going through the frustration of trying to sign into an application on their phone. Now, here, the user has added the application to their home screen. When it's tapped, it loads up an application shell, populates that with information from the server, and during this flow, AliExpress will ask the browser for the user's credentials. The browser is able to provide them in this case because the user is chosen to be in that state, and AliExpress can seamlessly sign the user in using the mechanisms that we've just talked about. You'll see at the bottom that it pops up a little toast to the user informing that they've been signed in. Of course, we're not gonna hand over credentials without actually telling the user what's going on. We wanna make sure that they're involved to the greatest extent possible. The code for the flow that we've just seen is quite straightforward. There's a credentials object hanging off of the navigator object in the DOM. This has a git method. That method takes a dictionary of options as its only argument, and it returns a promise which either resolves with a credential object, if it's able to provide a credential object, or with undefined, if either no credential object is available or the user chooses not to provide that credential. Here, we're looking for a username password pair, so we set password to true because that's the kind of credential that we're looking for. Further, we'd like to ensure that the user isn't prompted, that we only sign the user in if they're in a state where we can automatically sign them in. So we set unmediated to true. That is, the user will not be involved in this conversation. If they're in a state where they can automatically sign in, great, we get a credential. If not, the user isn't bothered with any sort of choices or any sort of decisions. We can ask them later, and I'll show you that in just a moment. So this code is safe to put on pretty much every page of your site. If you need users to be logged in in order to have a reasonable experience on your site, you can put this code into place. If the user can automatically sign into your website, they will. This will give you that credential, and you can use it to sign them in. If they can't automatically sign into your site, they won't be bothered, and you can choose to sign them in or to help them sign in a little bit later on. Signing in, of course, is a little bit more application-specific. So we'll walk through it in kind of broad strokes, but it's going to be specific to your application. So once you have a credential object, you'll do something useful with it. And in this case, the something useful is going to be using the Fetch API in order to send it to your backend in order to actually sign the user in. You'll send it to a sign-in endpoint. You'll use post as your method, and you'll pass that credential object in as the credentials attribute in these options and the request-in-it options for Fetch. Then, when it resolves, you'll get a response object back, and you need to examine that response to determine whether or not the sign-in was actually successful. Some applications will return a status code of 200. Others will return information in the JSON blob. You'll need to do this for your own application to determine what makes sense for you. But once you figure out what makes sense, you can either render an amazing sign-in experience for the user if you're in this kind of asynchronous flow where you're able to update your site asynchronously. If you're not in that kind of flow yet, if you still need to navigate them to a landing page, then you can do so quite trivially by setting window.location. We've seen a number of the websites that I showed earlier on are doing exactly this right now, layering it directly on top of their existing sign-in system, and then thinking about this kind of asynchronous model as a future step. Now, I talked a little bit about automatic sign-in, and this, of course, is new for the web, and we're just starting out with this concept, so the initial implementation that we're shipping is going to be relatively conservative. There are some privacy and security considerations here, so we want to make sure that we're doing the right thing. Now, the browser will hand over credentials automatically only if the automatic sign-in feature is actually enabled, that is, the user is chosen to be in an automatic sign-in state, and if the user is saved only one credential for your website. If there's any ambiguity, if they have multiple credentials for your site, we punt and let the user decide later on. We won't automatically sign them in. When automatic sign-in isn't possible, the credential manager API can still offer a one-tap sign-in via a chooser dialog. Now, Freeletics is a fitness and exercise application, which is a good example of the kind of general flow that we're looking at. Here, the user expresses an intent to sign-in by tapping on that button, Login. Based on that intent, Chrome presents an account chooser dialog, and in this dialog, the user is presented with the credentials that they've saved for this origin. If they save multiple credentials, they're able to choose from those credentials, pick the one that they want to use to sign-in, and then continue the flow. Now, if you're experiencing a Keanu moment of deja vu here, it's okay. This is almost exactly the same code that you saw before. The only difference is that we've removed the unmediated attribute from the options that we've passed into Git. That is, in this case, we accept user mediation. We'll get an automatic credential if we can, but if we can't, then the browser knows that it's allowed to pop something up to the user, to ask them to involve themselves in this flow. Now, you'll want to execute something like this snippet when you recognize a user's express intent to sign-in. Now, if the user clicks on a button named Login, that seems like a really good time to pop something like this up. So, getting credentials is great, but they have to be stored in the credential manager first, and this is where our heuristics often go awry. It's simply the case that we sometimes misparse the sign-up form. Don't get the right information, and at that point, the user's in a bad state. So, as you see here, the credential management API, offers developers the ability to choose when the save your password prompt is actually triggered, and to ensure that the correct information is passed in, so that Chrome doesn't miss a thing. Now, since the user has just entered their credentials into a form, the best way to store them into the credential manager is actually to use that form to create a password credential object. So, as you see here, you'll use the password credential constructor. You'll grab a reference to the form, you'll pass that form in, Chrome will parse through the form, find all of the bits and pieces that you've marked up using this autocomplete attributes that we talked about a moment ago, and populate the password credential with that information. It'll have a username, it'll have a password, and if there's any extra, well, we'll talk about that in a moment. You'll then call navigator.credentials.store, you'll pass it in, and it's really quite straightforward. Now, getting credentials is great, but the, sorry, so with Kayak, we just talked about usernames and passwords and figuring out how to make sure that we get the right information. But I mentioned earlier that federation is something that we have no understanding of today. The credential manager API, of course, gives you the ability to inform the browser about those federations. So, if you're Kayak, for instance, and you want to let users sign in with either Facebook or with Google, the credential manager API allows you to save that information so that when the user comes back next time, they don't have to choose which thing they used last time. I know that for things like Stack Overflow, I've personally created at least three accounts because I happen to have multiple things that I could use. Is it Twitter, is it Facebook, is it Google? Who knows. Here, we'll create a federated credential object and because there's no form that's actually used, we need to pass in all of this information ourselves. So we create a federated credential object, we pass in an ID, and we pass in a provider. And the provider is a serialized origin of the federation that we use, in order, the federation that the user used. We then store that in the exact same way that we just saw. Navigator decredentials that store and we pass in that decredential. That will pop something up to the user, the user can choose to store it and you can move on with whatever part of the flow you find yourself in. The last step, of course, is to ensure that when a user chooses to sign out of your application, that they're able to do so. We don't want to automatically sign them into their application if they've just clicked the log out button. This is a relatively straightforward API. You simply say that user mediation is required in order to sign the user in. So you call navigator.credentials.requireUserMediation. That will go through all the credentials that are stored for your origin and they'll ensure that those credentials cannot be used for automatic sign in until the user explicitly chooses to sign in via the account chooser that we saw earlier. Now there are some interesting considerations here. We've talked a little bit about the UX improvements that you can create and there are good, good reasons for you to use this API just in terms of making the actual experience better. But there are also really good security reasons to use this API. First of all, navigator.credentials is locked down to secure contexts. This is basically in line with the Chrome team's general notion that powerful features should only be delivered over TLS. We simply do not trust plain text websites and we're ratcheting down on those websites over time. In this case, we don't want to give those kinds of websites the ability to interact deeply with a password manager. Especially something like automatic sign in would be pretty bad if we exposed it over plain text where anyone between you and the server you're talking to can both read those credentials but also manipulate the JavaScript that's on the page. Secondly, the passwords are not directly exposed to JavaScript. I talked about using fetch here and fetch is actually the only mechanism that allows exposure of those passwords. So if your website has some sort of cross-site scripting bug where someone is able to inject code, they won't be able to access passwords even if the user is in an automatic sign-in state because the password is only sent to the backend server. That is, you authenticate to your backend by using the fetch API. At the point that we touch the network, we serialize that credential information and send it out to the network but not to JavaScript on the page. And finally, we further limit that by saying that fetch can only send credential information to same-site origins. That is, example.com can send something to admin.example.com, but it can't send it to evil.com. So even if there's a cross-site scripting bug on your site, even if they're able to grab credential objects, they can't actually exfiltrate them to third-party origins. So we've gone through that pretty fast as well. There's a whole lot of detail that I skipped over and I think it'd be really good for you to skim through the spec. There are a ton of examples at the top that show you how you might start using this API in a number of different situations that are fairly common for websites like the ones you probably run today. Those examples, I think, are really interesting to read, but those are kind of spec examples and they don't really reflect the real world in the same way that actual code does. Happily enough, the Guardian's implementation is open source, which means you can actually go out to the GitHub commit that they use in order to implement this API on their website and see the exact code that they use on their website and start using similar code on your own websites. Finally, my colleague EG, who's sitting over there, has put together an amazing code lab that will walk you through step-by-step usage of the API, layering it on top of the existing login system and turning it into a much more functional system that is easier for users to use and doesn't actually show them sign-in screens when they don't need to see them. So that's the credential management API. It has some real advantages over the status quo and in some flows, it allows you to sign a user in without ever showing them a sign-in screen, which I think is great for you as developers but also great for your users. That said, it's still based on passwords. Passwords, of course, are at the core of it and passwords themselves are a little bit of a risk. They're probably the most common form of authentication we see and we need to support them, but it would be excellent if we could layer something on top of passwords in order to give us better guarantees about the authentication. So I'd like to invite my colleague Alexi up now to talk about mitigation strategies that we at Google think are really important. Thank you, Mike. Hi, everybody. My name is Alexi and I'm a secure and ear on the identity team. And I'm going to tell you about security keys. So Sabine told us at the beginning that passwords are often reused by users across websites because of the cognitive load that it takes to have lots of different passwords. And of course, this is a security threat because that means no matter how much you lock down your website, it's only as secure as the weakest website with which the user has reused the same password. We know that once attackers break into one website, they take the passwords from that website and reuse them on other websites. And that's really frustrating. But we also know that passwords can be stolen by adversaries in other ways. For example, they can be plucked out of network traffic if that traffic is not encrypted. And some adversaries are so powerful that they can look at network traffic and sometimes find a cryptographic fault and maybe are able even to decrypt it later on. But it turns out that the attacker's job is even easier than that. They can often just ask users for their passwords and the users will just happily give them up. This, of course, is called phishing. So this is where the security key fits in. It's an additional layer of protection that you can give your users in addition to their password to guard access to their account data. OK, you might be asking yourself, is phishing effective? Is it something that I actually need to care about? Well, in a recent study conducted by Google, we found that phishing was effective almost half of the time against users. So that means half of the users will get tricked by good phishing pages. And even if the attackers don't take a lot of effort in making a phishing page, if they just simply say, give me your username, give me your password, it will still capture 3% of users. With a lot of users, that is quite a bad figure. OK, so what does a security key do? Well, it's based on a public standard called the FIDO Universal Second Factor Standard, U2F. It's safe, so it protects users against phishing. It also protects them against man-in-the-middle attacks, so network adversaries. It's easy to use. So you take it, you stick it into your USB drive if it's a USB form factor, and you just press a button and that's it. And it's compact. It's one small device that you can use with many different services on the web. So I've been talking a little bit, but let me show you how it actually works in real life. There we go. So I'm going to demonstrate sending into my personal Google account, which is protected by a security key. So here, my browser happily remembered my username through a password manager. And it happily also remembered my password. But now, it's going to ask me to insert and use my security key. So if you were up here with me, and it's a good thing that not all of you are up here with me. But later, I can show you that there's a security key already stuck into the USB drive here, and it's blinking furiously at me. I really want to touch it, so I'm going to go ahead and do that. There we go. I touched it. And voila, I'm signed in. That was fast. That was easy. And it was resistant against phishing, and then the middle attacks. So what just happened? Well, my browser sent a password along to the server, just as it had before. And this was vulnerable in all those different ways that we have mentioned. But it also sent something else. It sent a proof that a user was there. And this proof had a couple things in it. First, it said that it was issued as a result of a direct user action. That means that I actually touched the security key. It wasn't issued by malware. It says something about the freshness of this proof. It can't be something that's captured and then reused. So it has a server challenge. It mentions an origin for which this proof was issued. So you can see that it was issued for Google. And had I accidentally pressed the security key and given this to fissure.com or bad.com, it would have been mentioned right there. And that website could not take this proof and then reuse it against Google or your website in order to confuse that website and let the attacker in. And finally, it mentions something about the TLS connection. So it mentions properties of the TLS connection that a man in the middle could not fake, and then therefore this also thwarts interception. And of course, this is signed and sealed with a private key that resides on the security key whose public key the server knows. All right. So maybe that sounds interesting to you and you want to try using it. So let me show you how you can do this through a browser API. There are two API calls. One has to do with registration. This is the operation that you undertake the first time that you want to associate a security key with the user's account. And then for all subsequent times, you use authentication. So this is what you do every single time that the user wants to actually sign in. Each of them have three steps. So first, your web page is loaded from the server just as it is today. Then you decide that you want to authenticate the user. So you call the API. This causes the browser to then take your request and send it on to the security key, which processes the request. Blinks an LED, for example, gets the user's touch and then replies. And then the browser takes this, gives it to you through a call back to your code and you can send it on to your server for verification. This was shipped in Chrome 41. And if you're curious, you're all probably using Chrome 50. So you've had it for a while. And it will soon ship in Firefox as well. It's shipped as a component extension, which means that it's there. You just don't see it. And in fact, if you launch Chrome with a special flag, the dash show component extensions flag, you'll see it. It's called the CryptoTecan extension. And you can walk right through it if you actually want to debug the code. So you can talk to this extension directly through the message port API or use a little wrapper that we wrote to have a more handy API experience. OK. So remember registration, that's the first thing that you want to do. This is when you want to associate the security key with the user. So this is what the API looks like. It's pretty simple. You stick in a version. It's a set string right now. We're at U2F V2. So that's what you put in. Then there's a challenge. So here you can put in whatever you want to as the server. Maybe you want to encode the user's session, whatever. You want it to be a fresh nonce. And then you provide an app ID. I'm not going to go into details about what this is, but it's basically a little file that you host that maps various properties of your online presence. So it talks about maybe what origins you own, but also, for example, if you have an Android app, you can do that association in that file. You can go to the specs and then read more about it there. And finally, you provide a callback. Remember, this is what will be called by the browser once it gets a reply from the security key. In the callback, you get two things. You get client data and registration data. Client data is what the browser actually packages together and sent on to the security key. And this is what actually got signed. So it mentions that it's a register request. It has the challenge that you told it to have. And it has a couple more things that the browser puts in for the user's protection. For example, it has the origin that the browser saw. Then it also has properties of a TLS connection. That's the CID public key. If you're curious about what that is, you can come find me later and I can tell you how you can verify one of those things. All right. The other thing that you get back from the callback is you get a registration data. This is what the security key produced. There's a couple of things here you don't need to understand all of them. But it's basically a structured byte array that has the public key that the token generated. It has an attestation certificate that lets you reason about what kind of token this is. Who made it? Do you want to trust it? Do you not want to trust it? We know that some enterprises really care about procurement. So how the user actually got this token and which exact token it is. So this attestation certificate allows you to reason about those kind of things. It has a key handle. And then it has a signature over all those things that the token produces. So you take that and you send it on to your server for verification. The sign API, remember this is what you call every single time that the user wants to log in. It has a lot of the same things, but now it has a key handle. And for the crypto nerds in the audience, what this allows you to do is it actually allows you to build really, really neat tokens, really small ones that don't have any storage on them. Because this key handle is a mechanism that allows a server to remind the token of which key it can use. Again, if you're curious, come find me later. I can tell you all the gory, cool details. We can talk about a little bit curve. It's going to be awesome. All right. And finally, the callback. Now your callback has the same client data. Remember, that's what was sent down. It looks the same, except now it says authenticate, because the browser knows that this is an authenticate call. It has the challenge that you put in, properties of the TLS connection so you can thwart those man in the middle attackers, and the origin, which protects you against phishing. And it has a signature. Now it's a lot smaller. There's a counter that, again, lets you capture very strong attackers that may have cloned tokens. So for example, if there's an attacker that is able to get their hands on one of these, melt it down, examine it with an electron microscope, and make a copy, you can catch it right there through a counter. And then, of course, the signature. You also get a key handle so that if the user has multiple security keys, as a lot of users actually do, then you'll know which security key was actually used to create the signature. All right. So we know that this is more secure. We know that it's less error problem, because you just touch it. There's really no error you can make there. We know it's more user friendly. Users really love this. But we also found that it's very fast. So in fact, this is at least twice as fast as any other second factor mechanism that we know about. So hopefully, that sounds interesting to you. And if it does, then you can go read the full specs at the FIDO Alliance. Make sure you click on the U2F specs. That's what they're called. You can get the code. We've open sourced a bunch of the code. For example, the extension that lives in the browser, the sample server, which is live at that app spot site, but whose source is also there in the GitHub repo. You can get a device on Amazon. There are multiple vendors who make it. If you do, make sure you smile at amazon.com, because then a little bit of your money gets donated to charity. That's pretty awesome. And then if you do get one, don't forget to actually protect yourself and your Google account. You can go to accounts.google.com to security, to set verification, and click on security keys. And it's important if you think about it, because you guys all are developers. And if an attacker gets into your account, they could then use that to perhaps make your users vulnerable. So it's really important that you protect yourselves. All right. So today, Sabine started out and told us about Password Autofill, which allows you to use just a couple lines of code to enable something really powerful on your website to allow password managers to help users remember their usernames and passwords and then automatically stick it in the forums. Then Mike came up and told us how for some flows, you're able to get rid of login forms altogether. And then I told you about security keys, an extra level of protection that you can add to your sign-in flows to protect your users from phishing and mandolin attacks. I think that's it. Thank you very much. And have a great rest of IO.