DEV Community

Gil Fink
Gil Fink

Posted on • Originally published at gilfink.Medium on

Adding Authentication to a Qwik App

Authentication is a basic feature that is implemented in most of the apps and websites. Today there are many ways to authenticate users and the most popular front-end library for authentication is probably auth.js.

But how can you use the library in your Qwik app?

This post will explain how to integrate qwik-auth package into your Qwik app.

Note: The qwik-auth package is still experimental and some of the shown code might change in the future.

Setting the qwik-auth Package

The first thing to do when you want to use qwik-auth is to install it. Since auth.js is a peer dependency, you will have to install it as well. Run the following command to install the libraries:

pnpm i "@builder.io/qwik-auth" "@auth/core"
Enter fullscreen mode Exit fullscreen mode

Once the installation finishes, you will need to update the vite.config.js and include the @auth/core library to the optimizeDeps config:

import { defineConfig } from 'vite';
import { qwikVite } from '@builder.io/qwik/optimizer';
import { qwikCity } from '@builder.io/qwik-city/vite';
import tsconfigPaths from 'vite-tsconfig-paths';

export default defineConfig(() => {
  return {
    optimizeDeps: {
      include: ['@auth/core'],
    },
    plugins: [qwikCity(), qwikVite(), tsconfigPaths()],
    preview: {
      headers: {
        'Cache-Control': 'public, max-age=600',
      },
    },
  };
});
Enter fullscreen mode Exit fullscreen mode

Note: This is a workaround to a bug that is currently exists in qwik-auth which is SyntaxError: The requested module '/node_modules/.pnpm/cookie@0.5.0/node_modules/cookie/index.js?v=849ea94b' does not provide an export named 'parse'

Once you updated the vite.config.js you will have to add a secret string for your app. The place to put it is in the app .env file. In my demo app I called the variable VITE_AUTH_SECRET , but you can put any name that you like as long as you will use that name in the relevant place.

Generating the qwik-auth Actions and Loaders

Everything is set up and now you can go and use qwik-auth in your app. qwik-auth exposes a serverAuth$ generator function that will generate all the actions and loaders you need for login, logout or getting the current session. Once you give it a callback that returns a configuration object with all the authentication providers, it will generate the following:

  • useAuthSignin  — action that can be used to run the login process
  • useAuthSignout  — action that can be used to run the logout process
  • useAuthSession  — loader to get the current session

You can use any of the authentication providers that auth.js exposes. The following code shows you how I used the credentials provider:

import type { Provider } from '@auth/core/providers';
import CredentialsProvider from '@auth/core/providers/credentials';
import { serverAuth$ } from '@builder.io/qwik-auth';
import { users } from '~/data/users';

export const { useAuthSignin, useAuthSignout, useAuthSession, onRequest } = serverAuth$(
  () => {
    return ({
      secret: import.meta.env.VITE_AUTH_SECRET,
      trustHost: true,
      providers: [
        CredentialsProvider({
          name: 'Login',
          authorize: (credentials) => {
            if (credentials) {
              const user = users.get(credentials.username as string);
              if (user) {
                if (user.password === credentials.password) {
                  return { id: user.username, name: user.username, email: `${@gmail.com">user.username}@gmail.com`};
                }
              }
            }
            return null;
          },
          credentials: {
            username: { label: 'Username', type: 'text' },
            password: { label: 'Password', type: 'password' },
          },
        }),
      ] as Provider[],
    })});
Enter fullscreen mode Exit fullscreen mode

In the credentials provider, I plug into the authorize function and check the existence of a user inside an in-memory map object. In real-world, you will check that against a database but I wanted a simplified example.

Pay attention that the place to put the code I showed is inside the app _routes _ folder.

Using The Generated qwik-auth Actions and Loaders

Once you generated the qwik-auth actions and loaders instances, you can use them in your app. To run the login process, you will first have to run the useAuthSignin action:

const loginAction = useAuthSignin();
Enter fullscreen mode Exit fullscreen mode

Then you can wire it to a trigger button inside a *Form * element:

<Form action={loginAction}>
  <div class="container">
    <input
      type="hidden"
      name="provider"
      value="credentials"
    />
    <div class="login">
      <button>Login</button>
    </div>
  </div>
</Form>
Enter fullscreen mode Exit fullscreen mode

Pay attention to the hidden input with the provider name. This input holds the requested provider and you need to put it inside the form.

To run the logout process you will do the same as with the login but this time with the useAuthSignout action. If you want to use the current session you will use the useAuthSession loader and in it’s value property you will find the current user.

In my example, I used the session in the main layout and passed a loggedIn Boolean to the header component, which is later used to show/hide the logout button:

export default component$(() => {
  const serverTime = useServerTimeLoader();
  const userSignal = useAuthSession();

  return (
    <>
      <main>
        <Header loggedIn={userSignal.value?.user !== undefined} />
        <section>
          <Slot />
        </section>
      </main>
      <footer>
        <a href="https://www.builder.io/" target="_blank">
          Made with ♡ by Builder.io
          <div>{serverTime.value.date}</div>
        </a>
      </footer>
    </>
  );
});
Enter fullscreen mode Exit fullscreen mode

If you want to look at the full example, you can find it online.

Summary

In the post I showed how you can install and then use the qwik-auth package. This package is part of Qwik and is currently experimenatal. There is no documentation for the package yet, so I hope that this post will help you get started with it if you want to use it today.

Top comments (1)

Collapse
 
piwizard3852 profile image
Owen Wood

How can I create a custom login page? Is there a built in function to authenticate with my own form?