Session
Understanding how session is working.
Overview
Light-Auth implements a secure, modern authentication flow based on JWT tokens.
This page explains what is the session token and the difference between the session object, retrieved with getAuthSession() and the user object, retrieved with getUser().
Authentication flow
The authentication process in Light-Auth is designed to be simple and secure. It involves the following steps:
Session object
The session object represents the current user's session. It contains the minimal amount of information about the user's authentication status and session expiration.
The session object is filled with the information returned by the provider, contained in the JWT token.
It is important to note that the session object does not contain any sensitive information, such as the access token or refresh token or any other private data.
The session object is returned by the getAuthSession()
function. It contains the following fields:
"session": {
"id": "abc123",
"userId": "provider-user-id",
"email": "john.doe@contoso.com",
"name": "John Doe",
"providerName": "google",
"expiresAt": "2023-10-01T00:00:00Z"
}
By default, (you can change this in the configuration) the session object is stored in a crypted and secure cookie.
All the others information are stored in the user object, and the user object is not store in a cookie, but in a datastore (Redis, MongoDB, etc.).
The user object is returned by the getUser()
function. See documentation
Get the Session object
You can get the session object by using the getAuthSession()
function. This function is available in the auth
module.
import { getAuthSession } from "@/lib/auth";
export default async function Home() {
const session = await getAuthSession();
return (
<div>
{session != null ? (
<div>
<p>✅ You are logged in!</p>
<div>Session Id: {session.id}</div>
<div>Session Email: {session.email}</div>
<div>Session Name: {session.name}</div>
<div>Session Provider: {session.providerName}</div>
<div>Session UserId: {session.userId}</div>
<div>Session Expiration: {session.expiresAt.toString()}</div>
</div>
) : (
<div>
<p>⚠️ You are not logged in</p>
<a href="/login"> Go to Login Page </a>
</div>
)}
</div>
);
}
From the client side you can get the client session object by using the getAuthSession()
function from the client sdk, using the CreateLightAuthClient
function.
Here is an example of how to get the session object from the client side, using a react hook:
"use client";
import { CreateLightAuthClient } from "@light-auth/nextjs/client";
export const { getAuthSession, getUser } = CreateLightAuthClient();
export function useSession() {
const [session, setSession] = useState<Session | null>(null);
useEffect(() => {
async function fetchSession() {
const session = await getAuthSession();
setSession(session);
}
fetchSession();
}, []);
return session;
}
CreateLightAuthClient
function is used to create a client-side instance of Light-Auth. It provides the same functions as the server-side instance, but is designed to work in a client-side environment. You may probably create a
/app/auth-client.ts
file to export the client instance, and use it in your client components.Session vs User
- The session object is a lightweight representation of the user's session, while the user object contains more detailed information about the user.
- The session object is used to manage the user's session, while the user object is used to manage the user's profile and other related information.
- The session object is stored in a secure cookie, while the user object is stored in a datastore.
- The session object is returned by the
getAuthSession()
function, while the user object is returned by thegetUser()
function.
More information about the user object can be found in the User documentation.
Add custom Session and User properties
You can add custom properties to the Session (or User) object by:
- 1Extending the
Session
(or / and theUser
) object with a custom interface - 2Using the
onSessionSaving
(or / and theonUserSaving
) function in the configuration.
Here is an example where we get the given_name
and family_name
from the idToken
and add them to the session object.
Then we get others properties from the idToken and add them to the user object:
Add some custom properties to the session object by extending the session interface:
import { LightAuthSession, LightAuthUser } from "@light-auth/core";
export type MyLightAuthSession = LightAuthSession & {
// Add any additional properties you want to include in your custom session type
firstName?: string;
lastName?: string;
};
export type MyLightAuthUser = LightAuthUser<MyLightAuthSession> & {
// 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 session object by using the onSessionSaving
and to the user object using the onUserSaving
function in the configuration:
export const { providers, handlers, signIn, signOut, getAuthSession, getUser } =
CreateLightAuth<MyLightAuthSession, MyLightAuthUser>({
providers: [googleProvider, microsoftProvider],
onSessionSaving: async (session, tokens) => {
if (!tokens) return session;
if (!tokens.idToken()) return session;
// Add custom claims to the session
// This example adds the first and last name from the idToken to the session
const idToken = JSON.parse(
Buffer.from(tokens.idToken().split(".")[1], "base64").toString()
);
if ("given_name" in idToken && typeof idToken.given_name === "string")
session["firstName"] = idToken.given_name;
if ("family_name" in idToken && typeof idToken.family_name === "string")
session["lastName"] = idToken.family_name;
return session;
},
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;
},
});
Session Store
The session store is a secure cookie that contains the session object. The session store is used to manage the user's session and is automatically created when the user logs in.
You can change the default session store by modifying the configuration:
export const { providers, handlers, signIn, signOut, getAuthSession, getUser } =
CreateLightAuth({
providers: [googleProvider, microsoftProvider],
sessionStore: redisSessionStore,
});
The session store can be any object that implements the SessionStore
interface:
export interface LightAuthSessionStore {
getAuthSession: (args: { config: LightAuthConfig; [key: string]: unknown }) => Promise<LightAuthSession | null>;
setAuthSession: (args: { config: LightAuthConfig; session: LightAuthSession; [key: string]: unknown }) => Promise<BaseResponse>;
deleteAuthSession: (args: { config: LightAuthConfig; [key: string]: unknown }) => Promise<BaseResponse>;
generateSessionId: () => string;
}