Authentication (Svelte path)

In this section, you will learn how to do user authentication from your client application.

Adding Styles [Optional]

Add some basic styling to your application. You can add UIKit library for styling. Make the following changes to your src/app.html file. Feel free to use a CSS library of your choice or write your own CSS.

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="description" content="" />
		<link rel="icon" href="%svelte.assets%/favicon.png" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		%svelte.head%
		<!-- UIkit CSS -->
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.10.1/dist/css/uikit.min.css" />

		<!-- UIkit JS -->
		<script src="https://cdn.jsdelivr.net/npm/uikit@3.10.1/dist/js/uikit.min.js"></script>
		<script src="https://cdn.jsdelivr.net/npm/uikit@3.10.1/dist/js/uikit-icons.min.js"></script>
	</head>
	<body>
		<div id="svelte">%svelte.body%</div>
	</body>
</html>

User Signup

You need a page where users can signup as store owners in your application. Create a new file src/routes/signup.svelte and add the following code.

<script lang="js">
  import { setClient, mutation } from '@urql/svelte';
  import client from '../client'
  import { goto } from '$app/navigation';

  setClient(client);

  const registerMutation = mutation({
    query: `
      mutation ($name: String!, $email: String!, $password: String!) {
        registerOwner(name: $name, email: $email, password: $password) {
          email
          _id
        }
      }
    `,
  });

  async function onSubmit(e) {
    const formData = new FormData(e.target);

    const data = {};
    for (let field of formData) {
      const [key, value] = field;
      data[key] = value;
    }
    const { name, email, password } = data;
    const resp = await registerMutation({ name, email, password })
    if (resp.data?.registerOwner) {
      goto('/');
    } 
    if(resp.error) {
      alert(resp.error.message);
      console.log(resp.error);
    }
  }
</script>


<div class="wrap">
  <div>
    <div class="uk-card uk-card-default uk-card-body">
      <h3 class="uk-card-title">Sign up</h3>
        <form on:submit|preventDefault={onSubmit}>
          <div class="uk-margin">
            <input 
                class="uk-input" 
                type="text"
                placeholder="Username" 
                name="name" 
                autoComplete="off"
            />
          </div>
          <div class="uk-margin">
            <input 
                class="uk-input" 
                type="text" 
                placeholder="Email" 
                name="email"
            />
          </div>
          <div class="uk-margin">
            <input 
                class="uk-input" 
                type="password" 
                placeholder="Password" 
                name="password"
            />
          </div>
          <div class="uk-margin">
            <input class="uk-input" type="submit" />
          </div>
        </form>
    </div>
  </div>
</div>

<style>
  .wrap {
    margin: 10% 40%;
    min-width: 300px;
  }
</style>

In the previous code snippet, you have a simple form. When a user submits the form the registerOwner mutation is fired and a new owner is registered.

Visit localhost:3000/signup and try to register a owner.

Navigate to Collections in your Fauna dashboard and review the Owner collection. Your newly registered users will appear in this collection.

Newly registered user

User Login

Next, create a new page for users to log in to the application. Create a new file src/routes/login.svelte and add the following code.

<script>
  import { setClient, mutation } from '@urql/svelte';
  import client from '../client';
  import { goto } from '$app/navigation';

  setClient(client);

  let error;

  const loginMutation = mutation({
    query: `
      mutation OwnerLogin($email: String!, $password: String!) {
        login(email: $email, password: $password) {
          secret
          ttl
        }
      }
    `,
  });
  async function onSubmit(e) {
    const formData = new FormData(e.target);

    const data = {};
    for (let field of formData) {
      const [key, value] = field;
      data[key] = value;
    }
    const { email, password } = data;
    const resp = await loginMutation({ email, password })
    
    console.log('resp', resp)

    if(resp.data?.login) {
      alert('Login Successful');
      goto('/')
    }
    if(resp.error) {
      error = resp.error?.message;
    }
  }
</script>

<div class="wrap">
  <div class="uk-card uk-card-default uk-card-body">
    <h3 class="uk-card-title">Login</h3>
    {#if error}
      <div class="uk-alert-danger" uk-alert style={{ maxWidth: '300px', padding: '10px'}}>
        {error}
      </div>
    {/if}
    <form on:submit|preventDefault={onSubmit} >
      <div class="uk-margin">
        <input 
          class="uk-input" 
          type="text" 
          placeholder="Email" 
          name="email"
        />
      </div>
        <div class="uk-margin">
          <input 
            class="uk-input" 
            type="password" 
            placeholder="Password" 
            name="password"
          />
        </div>
        <div class="uk-margin">
          <input class="uk-input" type="submit" />
        </div>
    </form>
  </div>
</div>

<style>
  .wrap {
    margin: 10% 40%;
    min-width: 300px;
  }
</style>

To ensure everything is working as intended, run the application with npm run dev command, and visit localhost:3000/login. Verify the login function is working. Log in with a user you have registered before. Inspect the GraphQL response in the Network->XHR tab in your browser’s developer tools.

User login view
Login response

If you are getting a secret back from your GraphQL request, that means everything is working as intended. You can now use this secret to interact with other resources in Fauna.

In the next section, you learn how to manage your user sessions in the client application.

Complete Code

📙 Get the final code for this section here