README.md

# WebauthnComponents

Passkey authentication for Phoenix LiveView applications.

- [WebauthnComponents](#webauthncomponents)
    - [Project Status](#project-status)
  - [Roadmap](#roadmap)
  - [Quick Start](#quick-start)
  - [Installation Details](#installation-details)
    - [Create a new Phoenix Project](#create-a-new-phoenix-project)
    - [Add the Dependency](#add-the-dependency)
    - [Generate and Modify Code](#generate-and-modify-code)
  - [Webauthn Flows](#webauthn-flows)
  - [WebAuthn and Passkeys](#webauthn-and-passkeys)
    - [Benefits](#benefits)
    - [Cross-Device Authentication](#cross-device-authentication)
      - [Example](#example)
    - [Known Issues](#known-issues)
  - [Browser Support](#browser-support)
  - [Additional Resources](#additional-resources)


### Project Status

- This package is a **work in progress**, and it is in early **beta** status.
- Please **do not use WebauthnComponents in a production environment** until it has completed _beta_ testing.
- Feel free to experiment with this package and contribute feedback in [Elixir Forum](https://elixirforum.com/t/webauthnlivecomponent-passwordless-auth-for-liveview-apps/49941).

## Roadmap

View the planned work for this repo in the public [WebauthnComponents v1](https://github.com/orgs/liveshowy/projects/3/views/1) project on GitHub.

## Quick Start

**WebauthnComponents** includes a Mix Task for scaffolding the files needed to implement Passkey support.

1. Add the dependency in `mix.exs` (`{:webauthn_components, "~> 0.6"}`).
2. Run `mix deps.get` to install WebauthnComponents.
3. Run `mix wac.install` to scaffold the files.
4. Run `mix ecto.migrate` to create the `users`, `user_keys`, and `user_tokens` tables.
5. Review the code generated by `wac.install`.

## Installation Details

> 👉 The `wac.install` task is currently designed for Phoenix apps with no existing authentication.
>
> If your application has existing authentication, you may manually add or modify the modules required by `WebauthnComponents`.

### Create a new Phoenix Project

```bash
mix phx.new my_app
cd my_app
```

### Add the Dependency

```elixir
# my_app/mix.exs
def deps do
  [
    {:webauthn_components, "~> 0.5"}
  ]
end
```

### Generate and Modify Code

WebauthnComponents comes with a `wac.install` Mix Task to generate and modify modules required to support Passkeys in a LiveView application.

| 💾             | 💾                | 💾        |
| ------------- | ---------------- | -------- |
| Schemas       | Migrations       | Context  |
| GenServer     | Tests            | Fixtures |
| Components    | Controllers      | LiveView |
| Session Hooks | Javascript Hooks | Router   |

From the project directory, run `mix wac.install` to generate the required code:

```bash
mix wac.install
==> webauthn_components
Compiling 2 files (.ex)
Generated webauthn_components app
==> my_app
* creating lib/my_app/identity.ex
* creating lib/my_app/user_token_cleaner.ex
* creating lib/my_app/identity/user.ex
* creating lib/my_app/identity/user_key.ex
* creating lib/my_app/identity/user_token.ex
* creating priv/repo/migrations/20230917174312_users.exs
* creating priv/repo/migrations/20230917174313_user_keys.exs
* creating priv/repo/migrations/20230917174314_user_tokens.exs
* creating test/my_app/identity_test.exs
* creating test/my_app_web/live/authentication_live_test.exs
* creating test/support/identity_fixtures.ex
* creating lib/my_app_web/controllers/session.ex
* creating lib/my_app_web/live/authentication_live.ex
* creating lib/my_app_web/live/authentication_live.html.heex
* creating lib/my_app_web/session_hooks/assign_user.ex
* creating lib/my_app_web/session_hooks/require_user.ex
* creating lib/my_app_web/components/navigation_components.ex
* creating lib/my_app_web/components/navigation/navbar.html.heex
* creating lib/my_app_web/components/navigation/nav_link.html.heex
* updating assets/js/app.js
* updating lib/my_app_web/router.ex

✅ Successfully scaffolded WebauthnComponents for MyApp

📚 Resources

- Repo: https://github.com/liveshowy/webauthn_components
- Hex:  https://hex.pm/packages/webauthn_components
- Docs: https://hexdocs.pm/webauthn_components/readme.html

```

## Webauthn Flows

Documentation and illustrations for WebauthnComponent flows can be found in [Webauthn Flows](./webauthn_flows.md).

## WebAuthn and Passkeys

What is the difference between "WebAuthn" and "Passkeys"? The first is an API available in modern browsers, and the second is an implementation where public key credentials created by the WebAuthn API can be saved to the client device and/or a cloud provider.

The following quotes were chosen for their brevity and clarity.

From MDN:

> The Web Authentication API is an extension of the Credential Management API that enables strong authentication with public key cryptography, enabling passwordless authentication and/or secure second-factor authentication without SMS texts.
>
> https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API

From Google:

> A passkey is a FIDO login credential, tied to an origin (website or application) and a physical device. Passkeys allow users to authenticate without having to enter a username, password, or provide any additional authentication factor. This technology aims to replace passwords as the primary authentication mechanism.
>
> https://developers.google.com/identity/fido

\* While a user may *technically* be registered without a username or email, this is often a practical requirement for both a business and its users. By requiring an email, WebauthnComponents ensures each registered Passkey can be identified by the user when reviewing their collection of credentials. Email is often a required identifier for a business, especially when it needs to communicate with its users outside of its applications.

### Benefits

There are many benefits to users and application maintainers when passwords are decommissioned.

- Eliminates password reuse by users.
- Mitigates credential stuffing attacks by hackers.
- Eliminates phishing attacks by hackers.

For users on a device with Passkey support, WebAuthn credentials may be stored in the cloud. This allows the user to authenticate from other cloud-connected devices without registering each device individually.

### Cross-Device Authentication

Passkeys may be synchronized across mutliple devices connected to a user's cloud account, where credentials are managed.

- [iCloud Keychain on MacOS](https://developer.apple.com/passkeys/)
- [Android & Chrome](https://developers.google.com/identity/passkeys/supported-environments)
- [1Password](https://1password.com/product/passkeys)

When a user attempts to authenticate on a device where their Passkey is **not** synchronized, they may scan a QR code to use a Passkey stored on the registered device. The browser will detect that no Passkey is registered for the site and render the QR code to be scanned by the device where the Passkey can be accessed.

#### Example

Imagine a user, Amal, registers a Passkey for example.com on their iPhone and it's stored in iCloud. When they attempt to sign into example.com on a non-Apple device or any browser which cannot access their OS keychain, they may choose to scan a QR code using their iPhone. Assuming the prompts on the iPhone are successful, the other device will be authenticated using the same web account which was initially registered on the iPhone.

While this example refers to Apple's Passkey implementation, the process on other platforms may vary. Cross-device credential managers like 1Password may provide a more seamless flow for users who are not constrained to one OS or browser.

### Known Issues

While WebAuthn provides an API for improved authentication security, there are a few limitations to consider before adopting this component.

- As of 2023, Passkeys are not universally supported.
- Microsoft is testing Passkeys in Windows as of 6/29/2023 ([article](https://www.windowscentral.com/software-apps/browsing/microsoft-marches-toward-a-passwordless-future-with-passkey-features-on-windows-11)).
- Cloud-synced credentials are only accessible to devices authenticated to the cloud account.
  - For example, a credential saved to iCloud Keychain will not be synced automatically to Android's credential manager.
  - 1Password has released Passkey support out of beta as of 9/2023.
  - Services like 1Password synchronize these credentials across platforms, but often require a subscription.
- If a user registers or authenticates on a device without Passkey support, the generated key pair will only function on the device where it was registered. Each device must be registered in order to access an account.

## Browser Support

The WebAuthn API has broad support across the most common modern browsers.

https://caniuse.com/?search=webauthn

## Additional Resources

- [Webauthn Guide](https://webauthn.guide/)
- MDN: [Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)
- FIDO: [FIDO2: Web Authentication (WebAuthn)](https://fidoalliance.org/fido2-2/fido2-web-authentication-webauthn/)
- W3: [Web Authentication: An API for accessing Public Key Credentials Level 2](https://www.w3.org/TR/webauthn-2/)
- Apple: [Passkeys Overview](https://developer.apple.com/passkeys/)