DEV Community

Cover image for Integrate an Audit Trail for NextAuth.js in a few lines of code
Pranav Shikarpur for Pangea

Posted on • Originally published at pangea.cloud

Integrate an Audit Trail for NextAuth.js in a few lines of code

In the world where hackers are trying to brute force user accounts (23andMe breach 2023) and session tokens are being stolen (OKTA breach 2023) to impersonate authenticated users and run critical user actions, it is highly important for developers to maintain a tamper-proof audit log of all authentication events to keep their apps secure.

An audit log is a log service that’s used to keep track of all critical and sensitive user actions that take place across your applications. Events being logged could include sensitive file access, user logins, deleting or updating database records, etc.

What are the Advantages of an Tamperproof Audit Log?

  • Identify Risk of Exposure
    A robust tamperproof audit log can help quickly assess the risk of exposure after a data breach since you have logs of all user events and critical user actions that occurred in our app.

  • Can’t be Tampered with
    Since message hashes of Pangea Audit Logs have been designed to be stored in a cryptographically secure hash-tree called “Merkle Trees”, the logs are tamperproof and cryptographically verifiable. Thus Pangea Audit Logs can neither be changed nor destroyed once created.

  • Asynchronous Logging
    Since Pangea Audit Logs can be implemented asynchronously with our authentication system and APIs, it doesn’t affect the performance of our web apps.

Adding the Audit Trail to Our NextAuth.js App

In this tutorial, I will demonstrate how easy it is to add a tamper-proof audit log to an authentication setup. For the purposes of this tutorial, I’m going to use NextAuth.js - a popular JavaScript authentication library - to demonstrate how we can add secure audit logging to our JavaScript apps in just a few lines of code.

To follow along, head over to next-auth.js.org and follow the “Getting Started” tutorial. Once we’ve setup our Next.js app with NextAuth, we’re going to update the [...next-auth].ts file to include an events code block that will send data to the Pangea Audit Log API asynchronously on every signIn and signOut event.

import NextAuth from "next-auth"
import { User } from "next-auth"

// Imports to add
import { JWT } from "next-auth/jwt";
import auditLogToPangea from "@/utils/auditLog";

export const authOptions = {
 // Configure one or more authentication providers
 providers: [
   // List all your providers here
// ...
 ],

 // events code block to add
 events: {
   async signIn({ user, isNewUser }: { user: User, isNewUser?: boolean | undefined }) {
       const auditLogData = {
           email: user.email as string,
           name: user.name as string,
           message: isNewUser ? "User signed up" : "User logged in",
           event: isNewUser ? "signup" : "login",
       }

    // Call pangea secure audit log on sign in
       await auditLogToPangea(auditLogData);
   },
    async signOut({token}: {token: JWT}) {
        const auditLogData = {
            email: token.email as string,
            name: token.name as string,
            message: "User logged out",
            event: "logout",
            }

        // Call pangea secure audit log on sign out
        await auditLogToPangea(auditLogData);
       }
   }
// end events code block
}

export default NextAuth(authOptions)
Enter fullscreen mode Exit fullscreen mode

Now that we’ve added code to make an audit log happen on every signIn and signOut event, let’s create the auditLogToPangea function in the src/utils folder that uses the pangea-node-sdk to send log data to the Pangea secure audit log API.

Create the file auditLog.ts

import { PangeaConfig, AuditService, PangeaErrors } from "pangea-node-sdk";

const auditLogToPangea = async (logData: any) => {
   const token = process.env.PANGEA_TOKEN as string;
   const config = new PangeaConfig({ domain: process.env.PANGEA_DOMAIN });
   const audit = new AuditService(token, config);

   const data = {
       "message": logData.message,
       "action": logData.event,
       "email": logData.email,
       "name": logData.name,
       "target": logData.target ? logData.target : "",
   }

   try {
       console.log("Logging: %s", data);
       const logResponse = await audit.log(data as any, { verbose: true });
       console.log("Response: %s", logResponse.result);

       return true;
     } catch (err) {
       if (err instanceof PangeaErrors.APIError) {
         console.log(err.summary, err.pangeaResponse);
         return false;
       } else {
         throw err;
       }
   }
}
export default auditLogToPangea;
Enter fullscreen mode Exit fullscreen mode

You’re all set 🎉, now every time any user logs into our Next.js app using next-auth authentication setup, the user information along with the event is automatically audit logged and if we go to View Logs section in the Pangea User Console, we should see something like the following:

Image description

Further Steps:

Now that we’ve seen how easy it is to add an audit log to our authentication setup, we can go ahead and add audit logging to all the APIs used to perform critical user actions such as fetching PII, updating sensitive user fields, billing transactions, etc. We could either add this directly for each API in the app or run it as middleware to be able to log all user information going in and out of the applications APIs.

Top comments (0)