Svelte Login Form Example: Best Practices
Tags: svelte, javascript, webdev
Published: 2023-06-12 12:30:50

---
title: "Svelte Login Form Example: Best Practices"
published: "true"
description: "Svelte login form example 📝 signup and login forms for your Svelte app with password strength meter 🔐 and strong password auto generation."
tags: "svelte, javascript, webdev"
canonical_url: "https://rodneylab.com/svelte-login-form-example/"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcfcx02kn2i5fzaqyng5.png"
---

## 📝 Signup Form Best Practices

In this post, we look at a Svelte login form example and see some security and user experience (**UX**) best practices.  Clearly, good accessibility and overall UX help **improve conversion rates**.  It is important, though, to stress the economic benefits of helping users implement good security before moving on.

In 2022 a **credential stuffing** attack on DraftKings, a US sports betting site, led to <a href="https://www.theregister.com/2022/11/22/draftkings_credential_stuffing_attack/">USD 300,000 being stolen from user accounts</a>.  Reports suggest there was no breach of DraftKings systems.  Instead, the attacker is understood to have taken a list of user credentials leaked from other sites and tried them on DraftKings, in the hope users had recycled passwords.  This is credential stuffing: trying to again access to a service using **leaked or stolen passwords** from another service.

This kind of attack is difficult for services to prevent.  We focus on implementing some best practices to promote users improving their security in  post, using a Svelte code examples.
</div>

## Multifactor authentication

User best practices involve creating **strong and unique passwords** for each new account and setting up Multifactor Authentication where offered.  Here <a href="https://rodneylab.com/sveltekit-fido-u2f-login/">FIDO U2F keys are the gold standard</a>, with OTP apps like Authy and Google Authenticator offering a secure alternative.  <a href="https://newsletter.rodneylab.com/issue/2023-05-27?s=capsize#loudspeaker-fun-finds">Passkeys, using the new WebAuthn standard</a> might be a common, secure choice going forward.  Passkeys will work with mobile devices, and you can enforce that the user authenticates using device biometrics (like a fingerprint check) for extra security.

## 🧑🏽 User Experience Recommendations

To help keep forms accessible, test them with tools like Lighthouse and Axe.  Also try opening up the Issues tab in Chrome Dev tool as new Autofill and general form debugging features are rolling out in Chrome from May 2023.  These will help with more general UX issues, as well as accessibility (making sure label elements have a `for` attribute matching an input, and so on).

For more general UX, remember to **allow users to paste in passwords**.  Blocking pasting can be frustrating for password manager users.  Finally, using autofill fields correctly can help users who store their passwords in-browser. Note, storing passwords in browser in not advised by some privacy advocates.  See a longer <a href="https://web.dev/sign-up-form-best-practices/#checklist">checklist of sign-up best practices on web.dev</a>.

## 🔐 OWASP recommendations
Ideally, your site will offer MFA and <a href="https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html"> the Open Web Application Security Project (**OWASP**) has some recommendations, which also cover single factor authentication</a>.  These include:

- enforcing a minimum and maximum password lengths
- adding a password strength meter to encourage more complex passwords
- blocking common and previously breached passwords

 The minimum password length should be eight or more characters, and the maximum, long enough for users <a href="https://www.eff.org/dice">creating passphrases using diceware</a> and other techniques.  Enforcing a maximum length helps protect against some DoS attacks.  We see a library below which can helps in adding a strength meter and spotting common passwords.

## 🧱 Svelte Login From: What we're Building

I put together a full demo implementing some of the best practices just mentioned.  The demo includes an SQLite database, so you can spin it up, and test and tweak the techniques we discuss. We just look at the most important front end snippets here, and you can find the link to view the full repo further down.

## 🖋️ Signup Form

Let&rsquo;s look at some code, staring with form elements on the new user signup form.

### Username Input Field

```svelte
<label for="email">Email</label>
<input
	id="email"
	aria-invalid={emailError}
	aria-describedby={emailError ? "email-error" : undefined}
	type="email"
	required
	name="email"
	autocomplete="username"
	value={email}
	placeholder="tillie@example.com"
/>
{#if errors?.email}
	<small id="email-error" class="error-text">{errors.email}</small>
{/if}
```

Important points here for accessibility are:
- the `for` attribute on the `label` element matches the `input` element `id` (both set to `email`)
- the input uses `aria-invalid` and `aria-describedby` to provide feedback for screen reader users
- the label is displayed here, if you want to hide it visually, keep it in the DOM but add a screen reader only class

Some browsers will use the `type` and `required` attributes to offer hints or even intercept submission when inputs are invalid.  Remember, these are front end validations, and **additional back end validations are important** as a naughty user can easily bypass the front end checks we have above!

Finally, we use the `value` attribute here, to repopulate the field if, for example, the user submits an invalid password.  A small UX tweak.

## 🤖 Strong Password Auto Generation

Some modern browsers will offer to generate and store a strong password for users.  To enable this, be sure to set `autocomplete="new-password"` on the password field.  Also include this same attribute on any password confirmation field.

![Svelte Login Form Example: Screen capture shows a login form with an  added drop down in the password field and an offer to generate and sore a strong password.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngtqqs0po0m813wvz0hz.png)

Here is a snippet in which we set `autocomplete="new-password"`:

```svelte
      <label for="password">Password</label>
      <input
        bind:value={password}
        on:keydown={() => {
          passwordTouched = true;
        }}
        id="password"
        aria-invalid={passwordError}
        aria-describedby={passwordError ? "password-error" : undefined}
        type="password"
        required
        name="password"
        autocomplete="new-password"
        placeholder="P@s$w0rd"
      />
      {#if errors?.password}
        <small id="password-error" class="error-text">{errors.password}</small>
      {/if}
```

## 💪🏽 Password Strength Meter

We mentioned above that OWASP suggest adding a password strength meter.  This can help users generate stronger passwords.  <a href="https://zxcvbn-ts.github.io/zxcvbn/guide/getting-started/">`zxcvbn` is a fantastic library for helping here</a>.  I guess the name comes from a sequence of keys typically used on English keyboards.  As well as measuring password strength, `zxcvbn` will offer an explanation on why it considers a password to be weak and hints on strengthening it.  This is ideal for helping users generate strong passwords.

![Svelte Login Form Example: Screen capture shows a login form with a warning that the entered password is similar to a commonly used password and three hints for improvements.  The second hint is to capitalize more that the first letter.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7i9b1zuewv12vl2c1wf.png)

In this project code, we just look at using `zxcvbn` in the frontend.  For a production project, it is worth considering running it on the backend too for password verification.  You might also consider <a href="https://haveibeenpwned.com/API/v3">running checks using the Have I Been Pwned API</a>, which is a library of known leaked credentials.

### Svelte Login Form: Strength Meter Code

First, add some `zxcvbn` project dependencies:

```shell
pnpm add @zxcvbn-ts/core @zxcvbn-ts/language-common \\
  @zxcvbn-ts/language-en
```

There are other language dictionaries worth considering.  Anyway, this is the front end code:

```svelte
<script lang="ts">
  import { zxcvbn, zxcvbnOptions, type Score } from "@zxcvbn-ts/core";
  import * as zxcvbnCommonPackage from "@zxcvbn-ts/language-common";
  import * as zxcvbnEnPackage from "@zxcvbn-ts/language-en";

  let password = "";
  let passwordTouched = false;

  const { translations } = zxcvbnEnPackage;
  const { adjacencyGraphs: graphs, dictionary: commonDictionary } =
    zxcvbnCommonPackage;
  const { dictionary: englishDictionary } = zxcvbnEnPackage;

  const options = {
    translations,
    graphs,
    dictionary: { ...commonDictionary, ...englishDictionary },
  };
  zxcvbnOptions.setOptions(options);

  $: ({
    score,
    feedback: { warning, suggestions },
  } = zxcvbn(password));

  let strengthDescription = "Low";
  $: switch (score) {
    case 3:
      strengthDescription = "OK";
      break;
    case 4:
      strengthDescription = "Good";
      break;
    case 0:
    case 1:
    case 2:
    default:
      strengthDescription = "Low";
  }
</script>
```

The `password` variable is bound to the password input, and in lines `21-24` we use `zxcvbn` to recompute a score reactively, when `password` changes.  <a href="https://zxcvbn-ts.github.io/zxcvbn/guide/examples/#debounce">`zxcvbn` includes a debounce function</a> to make your code more efficient, though we keep things simple here.

The score takes values between `0` and `4`, where `3` and `4` indicate unguessable passwords.  Notice, the `zxcvbn` call also yields the warnings and suggestions mentioned above.

While you can use a Svelte `each` loop to display the suggestions, you might consider an HTML `meter` element to display the strength meter (thanks to Paweł Błaszczyk for this tip):


```svelte
<label for="password-strength">Password strength: {strengthDescription}</label>
<meter id="password-strength" value={score} low="1.9" high="2.9" optimum="4" max="4" />
{#if warning}
	<span class="warning"> {warning}</span>
	<ul>
		{#each suggestions as suggestion}
			<li class="alert">{suggestion}</li>
		{/each}
	</ul>{/if}
```

![Svelte Login Form Example: Screen capture shows a login form with a password strength meter reading 75% and text saying the strength is OK.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aup4pxgj6xg2u9p9v77y.png)

## 💯 Svelte Login Form Example: Testing it Out

To see the code in action, clone the repo and install packages.  It uses Prisma with an on-disk SQLite database.  To get going:

```shell
git clone https://github.com/rodneylab/svelte-login-form.git
cd svelte-login-form
pnpm install
cp .env.example .env
pnpm dev
```

The final, additional step is to send feedback!

## 🙌🏽 Svelte Login Form Example: Wrapping Up

In this post, we had a look at a Svelte Login form example.  More specifically, we saw:

- why **login and signup form UX and security matter**;
- some **form UX and security best practices**; and
- how you might add a **password strength meter** to a Svelte signup form.

Please <a aria-label="Open the Rodney Lab Git Hub repo" href="https://github.com/rodneylab/svelte-login-form">see the full repo code on the Rodney Lab GitHub repo</a>. For more <a href="https://evilmartians.com/chronicles/html-best-practices-for-login-and-signup-forms">HTML login form best practices, also see the recent Evil Martians post</a>. I do hope you have found this post useful and can use the code in your own Svelte app.  Let me know if you have any suggestions for improvements to the post.  Also reach out with ideas on new posts in this area. Drop a comment below or <a href="https://rodneylab.com/contact/">reach out on other channels</a>.

## 🙏🏽 Svelte Login Form Example: Feedback

If you have found this post useful, see links below for further related content on this site. I do hope you learned one new thing from the video. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on Twitter, giving me a mention, so I can see what you did. Finally, be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please <a aria-label="Support Rodney Lab via Buy me a Coffee" href="https://rodneylab.com/giving/">consider supporting me through Buy me a Coffee</a>.

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via <a aria-label="@ask Rodney" href="https://twitter.com/messages/compose?recipient_id=1323579817258831875">@askRodney</a> on Twitter and also <a aria-label="Contact Rodney Lab via Telegram" href="https://t.me/askRodney">askRodney on Telegram</a>. Also, see <a aria-label="Get in touch with Rodney Lab" href="https://rodneylab.com/contact/">further ways to get in touch with Rodney Lab</a>. I post regularly on <a aria-label="See posts on svelte kit" href="https://rodneylab.com/tags/sveltekit/">SvelteKit</a> as well as <a href="https://rodneylab.com/tags/seo/" aria-label="See posts on search engine optimisation">Search Engine Optimization</a> among other topics. Also, <a aria-label="Subscribe to the   Rodney Lab newsletter" href="https://newsletter.rodneylab.com/issue/latest-issue">subscribe to the newsletter to keep up-to-date</a> with our latest projects.