Using OTP Verification in Makerkit

Learn how to implement OTP verification in Makerkit to add extra security to your application.

In version 2.4.0, we've added support for OTP verification in Makerkit. This feature allows you to easily add two-factor authentication (2FA) to your application, providing an extra layer of security for sensitive operations.

While MFA was always possible to do thanks to Supabase Auth - we refer to OTP verification for different types of operations, such as:

  • deleting a user's account, a team, or transferring ownership of a team
  • super admin operations
  • any other operation that requires extra security

OTP Verification in Makerkit

The package @kit/otp provides a simple interface for managing OTP verification in your application.

We export three main parts from the package:

  1. <VerifyOtpForm />: A reusable form component for dispatching and verifying OTP codes
  2. createOtpApi(client): An API for verifying OTP codes

The VerifyOtpForm Component

The <VerifyOtpForm /> component is a reusable form component that handles the OTP verification process. It's designed to be used in conjunction with the createOtpApi function, which we'll cover next.

Here's an example of how to use the component:

import { VerifyOtpForm } from '@kit/otp';
import { useState } from 'react';
const MyForm = () => {
const [otp, setOtp] = useState('');
if (otp) {
// render an action button that dispatches the OTP code
return <FormActionConfirmation otp={otp} />;
}
return (
<VerifyOtpForm
purpose="delete-account"
onSubmit={setOtp}
email="user@example.com"
/>
);
};
function FormActionConfirmation({ otp }) {
return (
<button onClick={() => dispatchOtpAction(otp)}>
Confirm Action
</button>
);
}

The FormActionConfirmation component is an example of how you might use the OTP code to dispatch an action. In this case, we're confirming the deletion of a user's account:

Now, let's call the createOtpApi function to create an API for dispatching and verifying OTP codes:

'use server';
import { createOtpApi } from '@kit/otp';
import { getServerSupabaseClient } from '@kit/supabase/server-client';
import { enhanceAction } from '@kit/next/actions';
import { z } from 'zod';
export const dispatchOtpAction = enhanceAction(async ({ user, data }) => {
const supabase = getServerSupabaseClient();
const otpApi = createOtpApi(supabase);
// retrieve the OTP code from the request
const otpResult = await otpApi.verifyToken({
token: data.otp,
userId: user.id,
purpose: 'delete-personal-account',
});
// token, userID and purpose must match
// otherwise, the OTP code is invalid
if (!otpResult.valid) {
throw new Error('Invalid OTP');
}
// OTP is valid, proceed with the operation
}, {
auth: true,
schema: z.object({
otp: z.string().min(1),
}),
});

The above is a fairly simple example, but it demonstrates the basic idea.

  1. Dispatching an OTP code: The VerifyOtpForm component is used to render the OTP form, and will automatically handle sending an OTP code to the user's email address.
  2. Verifying an OTP Code: The createOtpApi function takes a Supabase client instance. We then call the verifyToken method on the API, passing in the OTP code and the user ID. The method returns a result object that indicates whether the OTP code is valid or not.

A few things to note:

  1. The purpose parameter is used to identify the type of operation being performed. This ensures that the OTP code is only valid for the intended purpose.
  2. The userId parameter is used to associate the OTP code with a specific user. This ensures that the OTP code is only valid for the user who requested it.

If these parameters don't match, the OTP code is considered invalid, so it's important to ensure that they are correctly set.

Examples of OTP Verification: deleting a user's account

Deleting a user's account is a sensitive operation that requires extra security - therefore we made the decision to implement OTP verification for it.

The below video demonstrates how to delete a user's account using OTP verification:

Loading video...

Conclusion

OTP verification is a simple yet effective way to add extra security to your application. By implementing OTP verification for sensitive operations, you can ensure that your users' data is protected and their accounts are secure.

For more information about the OTP API, please refer to the OTP API documentation.