keel-auth-with-nextjs
Authentication with Keel

To authenticate with Keel, we need to call the authenticate endpoint, pass in our username and password and tell the application what to do when authentication is successful.

For every authentication request, Keel returns a JWT (JSON Web Token). This token will act as a security mechanism to call other endpoints in our API. Let’s implement this.

Add the following to your page.tsx file:

'use client';
import { useState } from 'react';
import { useKeel } from '@/utils/keelContext';
import styled, { keyframes } from 'styled-components';
 
function HomePage() {
 
// initialize keel client
const keel = useKeel();
 
// Form state
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [message, setMessage] = useState('');
const [isLoggedIn, setIsLoggedIn] = useState(false);
 
// handle user login
const handleLogin = async (e: { preventDefault: () => void }) => {
    e.preventDefault();
    try {
	// Call the Keel authenticate function
      const response = await keel.api.mutations.authenticate({
        emailPassword: {
          email,
          password,
        },
        createIfNotExists: true,
      });
 
      if (response && response.data && response.data.token) {
	 // Set the Keel client token
        keel.client.setToken(response.data.token);
        setIsLoggedIn(true);
        setMessage('Logged in successfully!');
      } else {
        setMessage('Failed to log in' + response.error?.message);
      }
    } catch (error) {
      setMessage('Login error');
    }
  };
 
  return (
    <div>
        <Container>
          <form onSubmit={handleLogin}>
            <H2>Sign Up</H2>
            <div>
              <Input
                type="email"
                value={email}
                placeholder="Email"
                onChange={(e) => setEmail(e.target.value)}
                required
              />
            </div>
            <div>
              <Input
                type="password"
                value={password}
                placeholder="Password"
                required
                onChange={(e) => setPassword(e.target.value)}
              />
            </div>
            <div>
              <Button type="submit">Sign Up</Button>
            </div>
          </form>
        </Container>
        </div>
  );
}
 
// existing CSS
 
export default HomePage;

In this snippet, we've initialized the Keel client with useKeel(), created state objects to manipulate our form state and finally created a handleLogin function to help us with authentication. The most important aspect of the handleLogin function is:

const response = await keel.api.mutations.authenticate({
        emailPassword: {
          email: email,
          password: password,
        },
        createIfNotExists: true,
 });

To authenticate with Keel, use the built-in authenticate function, passing in an emailPassword object containing your email and password. Utilize the createIfNotExists option: if set to true, it will authenticate a non-existing user as a new one; if false, it will deny login access to users not in the database. Essentially, this mechanism enables you to implement both sign-up and log-in features with a single option.

setIsLoggedIn(true);

We added a state object called isLoggedIn that helps us check if a user is logged in or not. This will help control what part of our page is shown when a user is logged in or not

keel.client.setToken(response.data.token);

Here, we are setting a bearer token for the rest of our application with the token that is returned when authentication is successful. We need this token to perform API calls to the rest of our endpoints.

The next thing we need to do is to create the UI that allows us to create a new user, assign a role to that user and see it reflected in the database. We need to also make sure that you can only see this UI when you’re logged in.