Build a serverless chat app with Svelte and Firebase (PART 2)
Tags: svelte, webdev, tutorial, javascript
Published: 2020-11-06 15:50:54

In the last part, we initialised our application. In this part, we'll look at authentication using Firebase.

> Make sure you've gone through the [first part](https://dev.to/arnu515/serverless-is-it-worth-it-build-a-serverless-chat-webapp-with-svelte-and-firebase-1ffc) before continuing!

> The github code for this project is available [here](https://github.com/arnu515/serverless-chat)

We've already setup authentication on firebase, so let's do the setup on our app!

## Email and password authentication

We'll mostly be focusing on one file, `src/components/Auth.svelte`. 

### Register

Let's first add register functionality! We'll only need to update the `register()` function.

```html
<!-- src/components/Auth.svelte -->

<script lang="ts">
    // ...
    import {auth} from "../services/firebase";
    import {createEventDispatcher} from "svelte";

    const d = createEventDispatcher();

    // ...

    function register() {
        // if you're using js, remove the "as HTMLInputElement" for each of them
        const email = (document.getElementById("r-email") as HTMLInputElement).value
        const password = (document.getElementById("r-password") as HTMLInputElement).value
        const cpassword = (document.getElementById("r-cpassword") as HTMLInputElement).value

        // form validation
        if (!email || !password || !cpassword) {
            err = "Fill out all fields!"
            return;
        }
        if (password !== cpassword) {
            err = "Passwords don't match!"
            return;
        }
        err = "";

        // creating the user
        auth.createUserWithEmailAndPassword(email, password).then(() => {d("done"); d("auth")}).catch(e => {
            err = `(${e.code}) ${e.message}`
        })
    }

    // ...
</script>

<!-- ... -->
```

Time to test it out! Run your app and open <http://localhost:3000>. Now, you can register an account and you should see that account appear in the [firebase auth page on the firebase console](https://console.firebase.google.com)

![Firebase auth page](https://dev-to-uploads.s3.amazonaws.com/i/kblevokjoj549el13sh8.png)

### Login

Now for login! Just like register, we only have to edit the `login()` function.

```html
<!-- src/components/Auth.svelte -->

<script lang="ts">
    // ...

    function login() {
        // again, remove "as HTMLInputElement" if using js
        const email = (document.getElementById("l-email") as HTMLInputElement).value
        const password = (document.getElementById("l-password") as HTMLInputElement).value

        // basic form validation
        if (!email || !password) {
            err = "Fill out all fields!"
            return;
        }
        err = "";

        // sign in using firebase
        auth.signInWithEmailAndPassword(email, password).then(() => {d("done"); d("auth")}).catch(e => {
            err = `(${e.code}) ${e.message}`
        })
    }

    // ...
</script>

<!-- ... -->
```

Now, once we test that, you should *hopefully* see a green checkmark! Yay! We can now login and register with an email and a password.

## Google signin

Now, let's address the *easier* one, signing in with Google. Firebase makes it as easy as *one method*!

```html
<!-- src/components/Auth.svelte -->

<script lang="ts">
    // ...

    function google() {
        auth.signInWithPopup(googleAuth).then(() => {
            d("auth");
            d("done");
        }).catch(e => {
            err = `(${e.code}) ${e.message}`
        })
    }

    // ...
</script>

<!-- ... -->
```

Now, when you click the signin with Google button, it should allow you to sign in! Hurrah

## Logout

Let's also add functionality to the logout button. Again, we only need to change the `logout()` method, and again, firebase makes it super easy!

```html
<!-- src/components/Auth.svelte -->

<script lang="ts">
    // ...

    function logout() {
        if (auth.currentUser) {
            auth.signOut().then(() => {d("done"); d("logout")}).catch(e => {
                throw new Error(e)
            });
        }
    }

    // ...
</script>

<!-- ... -->
```

Now you may wonder why I'm dispatching events left and right everywhere. This is because we can use this Auth component in web pages and get to know when the person logs in. One such implementation is the `index.svelte` route:

```html
<!-- src/routes/index.svelte -->
<script lang="ts">
    import Auth from "../components/Auth.svelte";
</script>

<h1 class="w3-jumbo w3-center">Serverless Chat</h1>
<p class="w3-large w3-center">Please log in</p>

<Auth on:auth={() => window.location.href = "/chat"} />
```

I also created an `auth.svelte` route, so that users can directly login, but, this time, we can specify which action we want to do, instead of register at first, and also where to go next after we've logged in.

```html
<!-- src/routes/auth.svelte -->

<script lang="ts">
    import Auth from "../components/Auth.svelte";

    export let qs;

    qs.action = qs.action || "register"
    if (!["login", "register"].includes(qs.action)) qs.action = "register"
</script>

<h1 class="w3-center w3-jumbo">Authenticate to Serverless Chat</h1>
<Auth authMode={qs.action} on:auth={() => window.location.href=qs.next || "/"} />
```

Let's add a route to this page in `App.svelte`. While we're there, let's also add a 404 route.
```html
<!-- src/App.svelte -->
<script lang="ts">
    import router from "page";
    import Auth from "./routes/auth.svelte";
    import Index from "./routes/index.svelte";
    import NotFound from "./routes/notfound.svelte";
    import { queryString } from "./services/util";

    let page;
    let params = {};
    let qs = {};

    router("/", () => page = Index)
    router("/404/:msg", (ctx: {params: {}, querystring: string}, next) => {
        params = ctx.params;
        next();
    }, () => page = NotFound)
    router("/auth", (ctx, next) => {
        qs = queryString(ctx.querystring)
        next();
    }, () => page = Auth)
    router("/login", () => router.redirect("/auth"))
    router("/register", () => router.redirect("/auth"))

    router("/*", () => page = NotFound)
    router.start();
</script>

<svelte:component this={page} {params} {qs} />
```

`src/services/util.ts`:
```
<!-- src/services/util.ts -->

export function queryString(unparsed: string): {} {
    const separated = unparsed.replace("?", "").split("&");
    if (!separated) return {};
    const query = {};
    for (let item of separated) {
        const x = item.split("=");
        query[x[0]] = x[1];
    }
    return query;
}
```

`src/routes/notfound.svelte`
```
<!-- src/routes/notfound.svelte -->

<script lang="ts">
    export let params = {msg: ""}
</script>

<h1 class="w3-jumbo w3-center">404</h1>
<p class="w3-large w3-center">Not found</p>
<p class="w3-center w3-text-gray">{params.msg || "The page you were looking for was not found."}<br> <a href="/">Home</a></p>
```

And there! That wraps up the authentication part! Stay tuned for the next part, which is the chat functionality itself! The link to the 3rd part is [here](https://dev.to/arnu515/build-a-serverless-chat-app-with-svelte-and-firebase-1899)