Passwordless authentication for your website in 5 minutes!
Tags: authentication, webdev, tutorial, javascript
Published: 2023-01-13 10:14:17


![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673520949822/ffe4e78d-4b66-41cb-ac5c-fbba9d13572f.png)

Passwordless authentication using your phone's fingerprint sensor, or face recognition using your webcam is now possible in the browser thanks to the WebAuthn protocol. It is not only more comfortable for users but also more secure since it is two-factor authentication in a single step.

In this demo, we will use the free [Passwordless.ID](https://passwordless.id) API. This is a *public identity provider*, and it will take care of the heavy lifting for us. It's free and you don't even need to register an account or download anything to use it.

The following picture describes what we are about to do.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673520332515/a8d89dc2-df1f-4a73-bdc4-70adf9f3ea4c.png)

Our demo website will simply redirect to *passwordless.id* to authenticate "passwordlessly" (no e-mail required either) and authorize reading the profile, then return to the original demo page.

Thanks to it, we will obtain the user's avatar for that demo and display it, that's it! What is also obtained, besides the user's profile, is a signed Json Web Token. This token can later be sent to your APIs as proof of the user's identity. More on that later.

---

## Live Demo

<mark>Please note that the authentication will be blocked within the IFrame for security reasons, click on the upper right to open the CodeSandbox in its own tab!</mark>

{% embed https://codesandbox.io/embed/zealous-mountain-ej6q48?fontsize=14&theme=dark %}

If somehow the CodeSandbox is not shown properly or does not work, you can also see the live demo [here](https://passwordless-id.github.io/demo/) and the source code [here](https://github.com/passwordless-id/demo).

The Passwordless.ID API follows the OAuth2 / OpenID standards, just like google or facebook logins. It is nevertheless simpler and easier to integrate with since it is a *public* API, not requiring any kind of special authorization.

---

# Step by step tutorial

Although it is compatible with most other "Sign in with..." client libraries as a generic OpenID provider, the easiest way to integrate with it though is to use the [@passwordless-id/connect](https://github.com/passwordless-id/connect) library.

Let us go through the code, starting with the "Sign In" button.

```xml
<button id="sign-in" hidden class="btn btn-light" onclick="app.signIn()">Sign In</button>
```

Now, this is very basic, and depending on the frontend framework you use it will look different, but this is the gist of it.

The `app.signIn()` looks as follows.

```javascript
import passwordless from 'https://unpkg.com/@passwordless-id/connect'

function signIn() {
    // redirects to the authentication/authorization page and back
    passwordless.auth({scope: 'openid avatar email'})
}

// a global `app` object just for the purpose of the demo
window.app = {
    signIn
}
```

Once the `passwordless.auth()` method is called, the user will be redirected to the Passwordless.ID UI which will prompt it to create an account or sign in and then to authorize your app to read the `openid`, `avatar` and `email` of your profile. In case the user is already signed in and has granted access, the redirect would come back directly to the app.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673556587525/7f3d2d75-6aa5-4778-b361-72bc26e520be.png)

When redirecting back, it will append the `id_token` to the URL hash value (`https://example.com/mypage#id_token=...`) . The profile can then be extracted from the URL using the following piece of code.

```javascript
const user = await passwordless.id({scope: 'openid avatar email'})
if(user.signedIn && user.scopeGranted) {
    // great, user.profile contains the information
    // and user.id_token can be sent to APIs
}
    // the user is not signed in or has refused
    // to grant authorization
}
```

This chuck of code is typically executed when loading the page. The `id()` function will first look at the current URL and try to parse the `id_token` in the hash if present. Otherwise, a request will directly be sent to the Passwordless.ID API to obtain it (if the user is signed in and has previously granted the scope of course).

The function *always* returns. If the user is signed in and has granted the scope, the resulting `user` would look as follows.

```javascript
{
 "signedIn": true,
 "scopeGranted": true,
 "id_token": "eyJ0eXAiOiJK...",
 "profile": {
  "nickname": "Johny",
  "picture": "https://ui.passwordless.id/avatars/sam.svg",
  "preferred_username": "johndoe",
  "...": "...more attributes depending on requested scope"
 }
}
```

That's it! You have signed in a user and read its profile!

![](https://media.giphy.com/media/lOPJZITKZYLiU3cfGl/giphy.gif)

What you might also need is a way to sign out the user. Since Passwordless.ID is a centralized authentication system, being signed in or out affects all websites using it. As such, you cannot forcibly sign out users. You can ask them nicely "do you want to sign out?" using the following line.

```javascript
// redirects the user to the sign out page
passwordless.logout()
```

This will redirect the user to a sign out page, and once done (or not), back to the current URL.

Everything is now there to sign in, sign out and retrieve the user. Congrats! For the sake of brevity, we will skip the part of displaying the profile and other UI interactions. That is up to you to freely customize according to your website's style.

---

# What about the servers?

The example before shows browser side interaction, with the profile information being directly available. But how could you trust that information server side? That's what the `id_token` in the response is for! It is a "[Json Web Token](https://jwt.io)" (JWT), a signed proof of the user's identity.

The `id_token` is signed usings Passwordless.ID's secret private key and can be verified using its [public key](https://api.passwordless.id/openid/publickey).

There are two ways to validate the token:

1. Locally, by using one of the many JWT libraries available.
    
2. By calling [/openid/validate](https://api.passwordless.id/#get-/openid/validate)
    

That way, your servers and APIs can be sure of the user's identity. Each `id_token` will also possess a `sub` field according to the OpenID standard, which is a unique user identifier. You may also request the `email` as scope, but please be aware that an email is optional in Passwordless.ID, so you might not always obtain one even if you request it.

---

# It's only an "Alpha Version"!

Passwordless.ID is not yet fully ready. It's at a proof-of-concept stage. Although it can already be used for testing and integration purposes, it is not yet quite ready for production.

If you think this is a meaningful public service and if you liked the tutorial, please like it and share it! The best way to make it succeed is to spread the word and encourage us. I hope you enjoyed it, I would be glad to hear your feedback!

![](https://media4.giphy.com/media/L4fB9di7ekn3F5PXaW/giphy.gif?cid=ecf05e47447rfpemkli55zttugylznxlti2nh3nf194777gu&rid=giphy.gif&ct=g)