User management

Understanding how user information is handled by light-auth.

User Object Overview

The user object is a core component of Light-Auth that stores complete user information retrieved from authentication providers.
It extends the session object, inheriting its essential authentication properties while adding additional metadata from the JWT token.

Inheritance Structure

Session Object
User Object

Properties

Inherited from Session

  • userIdUser's unique identifier
  • nameUser's display name
  • emailUser's email address
  • providerNameName of the authentication provider

User-specific Properties

The properties below are specific to the User object and are not inherited from the Session object. They contain additional metadata and information about the user.

Be careful, these properties depends on the authentication provider used. For example, the picture property may not be available for all providers.

refreshToken is only retrieved if the provider supports it, and is configured for offline access. If not, it will be undefined.

  • pictureURL to user's profile picture
  • accessTokenOAuth access token for API calls
  • accessTokenExpiresAtExpiration timestamp for access token
  • refreshTokenToken used to refresh the access token

NOT Inherited from Session

Certain session-specific properties, such as id and expiresAt, exist only for the duration of the session and are not passed on to the User object:

  • idSession Id
  • expiresAtSession expiration timestamp

User Object Example

{
  // Inherited from Session
  "userId": "user_123456",
  "name": "John Doe",
  "email": "john.doe@example.com",
  "providerName": "google",
  
  // User-specific properties
  "picture": "https://example.com/profile.jpg",
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "accessTokenExpiresAt": "2023-06-30T23:59:59Z",
  "refreshToken": "rt_abcdefghijklmnopqrstuvwxyz",
  
  // Provider-specific data
  "firstName": "John",
  "lastName": "Doe",
  "locale": "en-US"
}
The User object can contain additional provider-specific properties that vary depending on the authentication provider used (Google, GitHub, Microsoft, etc.).

Configuration

Add the user adapter to your config and retrieve it from your page.

Add User Adapter to your configuration

This example demonstrates how to assign a user adapter using the userAdapter property in your configuration.
While the code is redundant—since this behavior occurs by default—it is included to highlight how to explicitly set a user adapter.
./src/auth.ts
export const { providers, handlers, signIn, signOut, getAuthSession, getUser } =
  CreateLightAuth({
    providers: [googleProvider, microsoftProvider],
    userAdapter: createLightAuthUserAdapter({ base: "./users_db", isEncrypted: false })
  })

Retrieving the user object from your web application

Like the session object, the user object is easily accessible using the getUser() method.

./src/app/home.tsx
import { getAuthSession, getUser } from "@/lib/auth";
import { Avatar, AvatarImage } from "./ui/avatar";

export default async function Home() {
  const session = await getAuthSession();
  const user = await getUser();

  return (
    <div>
      {session != null ? (
        <div>
          <p>✅ You are logged in!</p>
          {user != null && (
            <Avatar className="h-8 w-8">
              <AvatarImage src={user.picture} alt={user.name} />
            </Avatar>
            )}        
        </div>
      ) : (
        <div>
          <p>⚠️ You are not logged in</p>
          <a href="/login"> Go to Login Page </a>
        </div>
      )}
    </div>
  );
}

Add custom User properties

You can add custom properties to the User object by:

  • 1
    Extending the User object with a custom interface
  • 2
    Using the onUserSaving function in the configuration.

Here is an example where we get additional properties from the id token and add them to the user object.

Add some custom properties to the user object by extending the user interface:

src/app/auth.ts
import { LightAuthSession, LightAuthUser } from "@light-auth/core";

export type MyLightAuthUser = LightAuthUser<LightAuthSession> & {
  // Add any additional properties you want to include in your custom user type
  email_verified?: boolean;
  iss?: string;
  sub?: string;
};

Get custom properties from the authentication providers:

Add the custom properties values to the user object by using the onUserSaving function in the configuration:

src/app/auth.ts
export const { providers, handlers, signIn, signOut, getAuthSession, getUser } =
  CreateLightAuth<LightAuthSession, MyLightAuthUser>({
    providers: [googleProvider, microsoftProvider],

  onUserSaving: async (user, tokens) => {
    if (!tokens) return user;
    if (!tokens.idToken()) return user;

    // optional: Add custom claims to the user
    const idToken = JSON.parse(Buffer.from(tokens.idToken().split(".")[1], "base64").toString());

    if ("iss" in idToken && typeof idToken.iss === "string") user.iss = idToken.iss;
    if ("email_verified" in idToken && typeof idToken.email_verified === "boolean") user.email_verified = idToken.email_verified;
    if ("sub" in idToken && typeof idToken.sub === "string") user.sub = idToken.sub;

    return user;
  },    
  });

The UserAdapter

The UserAdapter is an abstract class that defines how User objects are stored and retrieved in Light-Auth. It provides a consistent interface for different storage backends, allowing you to choose the most appropriate storage solution for your application.

Built-in Adapters

FileUserAdapter

Stores user data in JSON files on the server's file system.

  • Simple setup with no additional dependencies
  • Good for development or small applications
  • Not suitable for distributed environments

DatabaseUserAdapter

Stores user data in a database through a configurable database connector.

  • Scalable and suitable for production
  • Works with various database backends
  • Supports distributed environments

UserAdapter Interface

The UserAdapter abstract class defines the following methods that must be implemented by any concrete adapter:

export interface LightAuthUserAdapter {
  getUser: (args: { config: LightAuthConfig; userId: string; [key: string]: unknown }) => LightAuthUser | null | Promise<LightAuthUser | null>;
  setUser: (args: { config: LightAuthConfig; user: LightAuthUser; [key: string]: unknown }) => Promise<void>;
  deleteUser: (args: { config: LightAuthConfig; user: LightAuthUser; [key: string]: unknown }) => Promise<void>;
}