Cognito Authentication for your SvelteKit app
Tags: svelte, sveltekit, cognito, oauth2
Published: 2021-07-25 23:52:17

---
title: Cognito Authentication for your SvelteKit app
published: true
date: 2021-07-24 22:00:00 UTC
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z30jwuwacfenboybvh4g.jpg
tags: Svelte, SvelteKit, Cognito, OAuth2
canonical_url: https://robertohuertas.com/2021/07/25/sveltekit-cognito-authentication/
---

Manage your users in your [SvelteKit](https://kit.svelte.dev/) app with [AWS Cognito](https://aws.amazon.com/cognito/).

## Why Cognito?

To be honest, in my case, it’s just because we’re using [AWS](https://aws.amazon.com/) at [Koa Health](https://koahealth.com/) and it was the natural choice. I have many things to say about [AWS Cognito](https://aws.amazon.com/cognito/), both good and bad, but this won’t be the article covering that :wink:.

Well, hopefully, chances are that you may be already using [AWS](https://aws.amazon.com/) as your main cloud provider and this post can help you to integrate [AWS Cognito](https://aws.amazon.com/cognito/) in you [SvelteKit](https://kit.svelte.dev/) app.

## Disclaimer

I’m starting with [Svelte](https://svelte.dev/) so if you have any suggestions to improve what I’ll show here, you’re more than welcome to write a comment or contact me.

Alternatively, feel free to take a look at the [GitHub repository hosting the final project](https://github.com/robertohuertasm/sveltekit-cognito-auth) and open an issue there if you prefer.

## Setting up the SvelteKit app

We’re just going to use SvelteKit to build a simple app that will authenticate users, so let’s start with with some simple commands to create the project:

```sh
npm init svelte@next sveltekit-cognito-auth
# I'm choosing the Skeleton project,
# opting out of TypeScript for this tutorial
# and using ESlint and Prettier support
cd sveltekit-cogniton-auth
npm install

```

You can find [here](https://kit.svelte.dev/docs) more details about how to [get started with SvelteKit](https://kit.svelte.dev/docs) in case you want to learn more about it.

For now, let’s open the `src/index.svelte` file, delete its content and build this spartan UI:

```html
<script>
    // we'll edit this later
    let user;
</script>

<svelte:head>
	<title>SvelteKit - Cognito</title>
</svelte:head>

{#if !user}
    <button>Log In with Cognito</button>
{:else}
    <button>Log Out</button>
{/if}

```

The idea here is to have a button that will trigger the **Cognito authentication flow** and another one that will **log out** the user. As simple as that!

For the moment, we’re going to skip all the logic to show one button or the other but we will come back to it later.

Let’s check that our app is working:

```sh
npm run dev -- --open

```

Hopefully, you should see a page with a button that says `Log In with Cognito`.

## Setting up Cognito

Let’s **create and configure** our Cognito User Pool now.

First of all, let’s introduce the pool name: `sveltekit-pool`.

![Cognito Pool Name](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/01-create-cognito-pool.png)

For this example, we’re going to use these simple settings.

Remember to tick the **email** checkbox in the `Attributes section`.

![Cognito Pool Attributes](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/02-create-cognito-pool.png)

We’ll also relax the **Password Policy** to allow users to choose their own passwords without many hassles, so **uncheck all the checkboxes** related to the password strength.

![Cognito Pool Policy](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/03-create-cognito-pool.png)

Let’ press the `Next Step` button until we arrive to the `App Clients` section and let’s **add one app client**.

Leave it everything as it is and set the name that you want. For this example, I’m using `sveltekit`. Fairly original, isn’t it? :wink:

![Cognito Pool App Client](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/04-create-cognito-pool.png)

## Setting up the App Client

There are still a couple of things to do in our Cognito Pool. Ideally, we’d like to use the [Cognito Hosted UI](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html) which will simplify a lot the Sign Up and Sign In flows.

For the moment, bear with me, fill the `App Client settings` with the following values and just click `Save`:

![Customizing the App Client](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/05-create-cognito-pool.png)

A couple of things to note here:

- The callback url will be a backend endpoint we’ll be exposing in our app.
- The Sign Out url is the final url to be redirected to once we’ve signed out from Cognito

Finally, for the [Cognito Hosted UI](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html) to work, we need to set up a **domain**. Note that the domain you choose is subjected to availability.

![Setting up the domain](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/06-create-cognito-pool.png)

Let’s move away from Cognito for the moment and let’s focus again on our `Svelte` app.

## Leveraging SvelteKit Auth library

Luckily for us, [RaviAnand Mohabir](https://ravianand.web.app/) has created a super cool library called [SvelteKit Auth](https://github.com/Dan6erbond/sk-auth), based on [NextAuth.js](https://next-auth.js.org/), which will allow us to use some of the most popular identity providers, such as Google, Twitch, Facebook, Twitter and Reddit.

But not only that, it also provides a **generic OAuth2 provider** that we will leverage to authenticate our users with Cognito.

The library handles all the OAuth2 flow for you, including the redirects, the token exchange and the user profile retrieval.

Let’s add the dependency to our app before we continue:

```sh
npm i sk-auth --save

```

### Creating our Cognito Provider

Let’s create a new file called `src/lib/auth.js` and paste the following code:

```js
import { SvelteKitAuth, Providers } from 'sk-auth';

// this is the domain we set up in our Cognito Pool
const DOMAIN = 'sveltekit.auth.eu-west-1.amazoncognito.com';

// these are the configuration seetings for our OAUTH2 provider
const config = {
	accessTokenUrl: `https://${DOMAIN}/oauth2/token`,
	profileUrl: `https://${DOMAIN}/oauth2/userInfo`,
	authorizationUrl: `https://${DOMAIN}/oauth2/authorize`,
	redirect: 'https://robertohuertas.com',
	clientId: import.meta.env.VITE_CLIENT_ID,
	clientSecret: import.meta.env.VITE_CLIENT_SECRET,
	scope: ['openid', 'email'],
	id: 'cognito', // IMPORTANT: this is the id that we'll use to identify our provider
	contentType: 'application/x-www-form-urlencoded'
};

const oauthProvider = new Providers.OAuth2Provider(config);

// exposing our auth object
export const appAuth = new SvelteKitAuth({
	providers: [oauthProvider]
});

```

Probably, if it’s the first time you’ve seen something like `import.meta.env.VITE_whatever`, you’ll be wondering what the hell is that.

Basically, it’s the way to get some environment variables from an `.env` file in your root.

You can find more info about it [in the SvelteKit FAQs](https://kit.svelte.dev/faq#how-do-i-use-environment-variables).

So make sure to add the following to your `.env` file:

```sh
VITE_CLIENT_ID=<your_client_id>
VITE_CLIENT_SECRET=<your_client_secret>

```

### Exposing the Auth object endpoints

Now, let’s create a new file called `src/routes/api/auth/[...auth].js`.

If that felt strange to you, you have to know that this kind of naming is a [routing convention from SvelteKit](https://kit.svelte.dev/docs#routing-advanced).

You can use this piece of code to expose the auth endpoint:

```js
// we're importing our auth object here
import { appAuth } from '$lib/auth';
// and exposing the get and post method handlers
export const { get, post } = appAuth;

```

### Using the Auth object getSession method

The Auth object exposes a [getSession method](https://kit.svelte.dev/docs#hooks-getsession) that we can use in our `hooks.js` file in order to return a session that it’s accessible on the client.

As we have used the _Skeleton_ project, we don’t have any `hooks.js` file yet. Let’s create one in the `src` folder and add this code:

```js
import { appAuth } from '$lib/auth';
export const { getSession } = appAuth;

```

With this, the claims of the access token will be available on the _session_ store.

## Adding some interaction in the UI

We’re going to add now some actions to the buttons in our UI, so let’s open our `src/index.svelte` file and edit it:

```html
<script>
    import { signOut as authSignOut } from 'sk-auth/client';
	import { session } from '$app/stores';

    // getting the user from the session store
    $: user = $session.user;

    function signIn() {
        location.assign('/api/auth/signin/cognito?redirect=/');
    }

    function signOut() {
        authSignOut().then(session.set);
    }
</script>

<svelte:head>
	<title>SvelteKit - Cognito</title>
</svelte:head>

{#if !user}
    <button on:click="{signIn}">Log In with Cognito</button>
{:else}
    <h2>Welcome {user.email}!</h2>
	<p>Your username is {user.username} and your email has been verified: {user.email_verified}</p>
    <button on:click={signOut}>Log Out</button>
{/if}

```

Notice that we’ve added some actions to the buttons which are fairly self-explanatory.

The `signIn` action will redirect the user to our `api/auth` endpoint (the one we set up in the previous step) with `signin` and `cognito` as parameters (remember that we set the id of our provider to `cognito`).

Finally, the `redirect` querystring parameter will tell the endpoint to redirect the user to our `/` route once the user is authenticated.

Let’s run the app and click over the `Log In with Cognito` button. You should see the [Cognito Hosted UI](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html):

![Cognito Hosted UI Sign In](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/07-sign-in.png)

As we don’t have any account yet, let’s click over the `Sign Up` link and create a test user.

![Cognito Hosted UI Sign Up](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/08-sign-up.png)

Use a **real email address** as Cognito will send you a **verification email** with a code you’ll need to enter in the UI.

![Cognito Hosted UI Confirm email](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/09-confirm-email.png)

Once you’ve confirmed your email, you’ll be redirected to the `/` route but, this time, you should see something like this:

![Logged In](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/10-logged-in.png)

If you check your Cognito pool, you should be able to see the user you just created.

![User created in the pool](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/11-user-created.png)

Note that [SvelteKit Auth](https://github.com/Dan6erbond/sk-auth) will set an `HttpOnly` cookie in order to manage the session for you.

![Cookie](https://robertohuertas.com/assets/images/sveltekit-cognito-authentication/12-cookie.png)

## Conclusion

As you can see, setting up an OAuth2 provider is pretty easy with [SvelteKit Auth](https://github.com/Dan6erbond/sk-auth). If you need further adjustments, check out the repository. If you take a look at the example app, you’ll see plenty of ways to adjust your flow.

As a final note, I would like to mention that our `Log Out` button is not really logging out our user from Cognito as we’re only removing the cookie from our browser. So if you try to log in again, you’ll probably be logged in without having to introduce any credentials.

As a way to mitigate this, you can clear the Cognito Hosted UI domain cookies or you just can extend the log out functionality by calling the [logout endpoint from AWS Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html). Give it a try!

--
Originally published at [robertohuertas.com](https://robertohuertas.com/2021/07/25/sveltekit-cognito-authentication/) on Jul 25, 2021.