@light-auth/nuxt
Version:
light auth framework for nuxt, using arctic
277 lines (269 loc) • 12.3 kB
JavaScript
/*! @light-auth/nuxt v0.3.1 2025-06-13 */
;
import { resolveBasePath, createSetUserServerFunction, createFetchUserServerFunction, createFetchSessionServerFunction, createSignoutServerFunction, createSigninServerFunction, createHttpHandlerFunction, buildFullUrl, encryptJwt, buildSecret, DEFAULT_SESSION_NAME, decryptJwt } from '@light-auth/core';
import { getHeaders, parseCookies, setCookie, sendRedirect, deleteCookie, getCookie } from 'h3';
/**
* createNextJsLightAuthSessionFunction is a function that creates a light session function for Next.js.
* It takes the LightAuth createLightAuthSessionFunction base function and returns a user friendly function by
* removing the req and res parameters, that are not needed in the Next.js context.
*/
const createGetAuthSession = (config) => {
const getAuthSession = createFetchSessionServerFunction(config);
return async (event) => await getAuthSession({ event });
};
const createSetAuthSession = (config) => {
const setAuthSession = createFetchSessionServerFunction(config);
return async (event, session) => await setAuthSession({ event, session });
};
/**
* createNextJsLightAuthUserFunction is a function that creates a light user function for Next.js.
* It takes the LightAuth createLightAuthUserFunction base function and returns a user friendly function by
* removing the req and res parameters, that are not needed in the Next.js context.
*/
const createGetAuthUser = (config) => {
const lightAuthUser = createFetchUserServerFunction(config);
return async (event, providerUserId) => await lightAuthUser({ event, providerUserId });
};
const createSetAuthUser = (config) => {
const setUser = createSetUserServerFunction(config);
return async (event, user) => await setUser({ event, user });
};
/**
* createNuxtJsSignIn is a function that creates a sign-in function for Nuxt.js.
* It takes the LightAuth createSigninFunction base function and returns a user friendly function by
* removing the req and res parameters, that are not needed in the Nuxt.js context.
*/
const createSignIn = (config) => {
const signIn = createSigninServerFunction(config);
return async (event, providerName, callbackUrl = "/") => {
await signIn({ providerName, callbackUrl, event });
};
};
/**
* createNuxtJsSignOut is a function that creates a sign-out function for Nuxt.js.
* It takes the LightAuth createSignoutFunction base function and returns a user friendly function by
* removing the req and res parameters, that are not needed in the Nuxt.js context.
*/
const createSignOut = (config) => {
const signOut = createSignoutServerFunction(config);
return async (event, revokeToken, callbackUrl = "/") => {
await signOut({ revokeToken, callbackUrl, event });
};
};
/**
* createNuxtJsLightAuthHandlerFunction is a function that creates the light auth handler for Nuxt.js.
* It takes the LightAuth createHttpHandlerFunction base function and returns a user friendly function by
* removing the req and res parameters, that are not needed in the Nuxt.js context.
*/
const createHandler = (config) => {
const lightAuthHandler = createHttpHandlerFunction(config);
const nuxtJsLightAuthHandler = async (event) => {
const response = await lightAuthHandler({ event: event });
return response;
};
return nuxtJsLightAuthHandler;
};
/**
* CreateLightAuth is a function that creates the LightAuth components for Nuxt.js.
* It takes a LightAuthConfig object as a parameter and returns a LightAuthNuxtJsComponents object.
* The function also sets default values for the userAdapter, router and cookieStore if they are not provided.
*/
function CreateLightAuth(config) {
// check if we are on the server side
const isServerSide = typeof window === "undefined";
if (!isServerSide)
throw new Error("light-auth-nextjs: DO NOT use this function [CreateLightAuth] on the client side as you may expose sensitive data to the client.");
if (!config.providers || config.providers.length === 0)
throw new Error("light-auth: At least one provider is required");
// lazy import the user adapter to avoid circular dependencies
if (!config.userAdapter && typeof window === "undefined") {
import('@light-auth/core/adapters').then((module) => {
config.userAdapter = module.createLightAuthUserAdapter({ base: "./users_db", isEncrypted: false });
});
}
if (!config.sessionStore && typeof window === "undefined") {
Promise.resolve().then(function () { return nuxtjsLightAuthSessionStore; }).then((module) => {
config.sessionStore = module.nuxtJsLightAuthSessionStore;
});
}
if (!config.router && typeof window === "undefined") {
Promise.resolve().then(function () { return nuxtjsLightAuthRouter; }).then((module) => {
config.router = module.nuxtJsLightAuthRouter;
});
}
config.env = config.env || process.env;
config.basePath = resolveBasePath(config.basePath, config.env);
if (!config.env["LIGHT_AUTH_SECRET_VALUE"])
throw new Error("LIGHT_AUTH_SECRET_VALUE is required in environment variables");
return {
providers: config.providers,
handlers: createHandler(config),
basePath: config.basePath,
signIn: createSignIn(config),
signOut: createSignOut(config),
getAuthSession: createGetAuthSession(config),
setAuthSession: createSetAuthSession(config),
getUser: createGetAuthUser(config),
setUser: createSetAuthUser(config),
};
}
/**
* A concrete CookieStore implementation for Node.js server-side,
* using the 'cookie' npm package and returning Response objects
* with appropriate Set-Cookie headers.
*/
const nuxtJsLightAuthRouter = {
async redirectTo({ url, event }) {
if (!event)
throw new Error("Event is required in redirectTo of nuxtJsLightAuthRouter.");
const headersData = getHeaders(event); // { "content-type": "application/json", "x-custom-header": "value" }
const incomingHeaders = new Headers();
if (headersData) {
// Iterate over the headers object and append them to the new Headers object
for (const key in headersData) {
const value = headersData[key];
if (value)
incomingHeaders.append(key, value);
}
}
const fullUrl = buildFullUrl({ url, incomingHeaders });
await sendRedirect(event, fullUrl.toString());
},
async setCookies({ cookies, event }) {
if (!event)
throw new Error("Event is required in redirectTo of nuxtJsLightAuthRouter.");
if (!cookies || cookies.length === 0)
return;
for (const cookie of cookies) {
setCookie(event, cookie.name, cookie.value, {
path: cookie.path,
httpOnly: cookie.httpOnly,
secure: cookie.secure,
sameSite: cookie.sameSite,
maxAge: cookie.maxAge,
});
}
},
async getCookies({ search, event }) {
if (!event)
throw new Error("Event is required in getCookies of nuxtJsLightAuthRouter.");
const lightAuthCookies = [];
// Convert search to RegExp if it's a string
const regex = typeof search === "string" ? new RegExp(search) : search;
const cookies = parseCookies(event);
for (const [requestCookieKey, requestCookieValue] of Object.entries(cookies)) {
if (!search || !regex || regex.test(requestCookieKey))
lightAuthCookies.push({ name: requestCookieKey, value: requestCookieValue });
}
return lightAuthCookies;
},
async getUrl({ endpoint, event }) {
const url = endpoint ?? event?.node.req?.url;
if (!url)
throw new Error("light-auth: No url provided and no request object available in getUrl of nuxtJsLightAuthRouter.");
if (url.startsWith("http"))
return url;
if (!event)
return url;
const headersData = getHeaders(event);
const incomingHeaders = new Headers();
for (const [key, value] of Object.entries(headersData))
if (value)
incomingHeaders.append(key, value);
const fullUrl = buildFullUrl({ url, incomingHeaders });
return fullUrl.toString();
},
async getHeaders({ search, event }) {
if (!event)
return new Headers();
const headersData = getHeaders(event);
// Convert search to RegExp if it's a string
const regex = typeof search === "string" ? new RegExp(search) : search;
// Create a new Headers object to hold filtered headers
const filteredHeaders = new Headers();
// Iterate and filter headers whose names match the regex
for (const [key, value] of Object.entries(headersData)) {
if (!search || !regex || regex.test(key))
if (value)
filteredHeaders.append(key, value);
}
return filteredHeaders;
},
async getRequest({ env, basePath, event }) {
if (!event)
throw new Error("Event is required in getRequest of nuxtJsLightAuthRouter.");
try {
const url = await this.getUrl({ env, basePath, event });
const headers = await this.getHeaders({ env, basePath, event });
return new Request(url, { method: event.node.req.method, headers: headers });
}
catch (error) {
throw new Error(`light-auth: Error creating request object in getRequest of nuxtJsLightAuthRouter: ${error}`);
}
},
returnJson({ data, event, init }) {
return Response.json(data, {
...(init ?? {}),
status: init?.status ?? 200,
});
},
};
var nuxtjsLightAuthRouter = /*#__PURE__*/Object.freeze({
__proto__: null,
nuxtJsLightAuthRouter: nuxtJsLightAuthRouter
});
/**
* A concrete CookieStore implementation for Node.js server-side,
* using the 'cookie' npm package and returning Response objects
* with appropriate Set-Cookie headers.
*/
const nuxtJsLightAuthSessionStore = {
async getSession({ env, event, }) {
if (!event)
throw new Error("Event is required to get the session in nuxtJsLightAuthSessionStore.");
const requestCookie = getCookie(event, DEFAULT_SESSION_NAME);
if (!requestCookie)
return null;
try {
const decryptedSession = await decryptJwt(requestCookie, buildSecret(env));
return decryptedSession;
}
catch (error) {
console.error("Failed to decrypt session cookie:", error);
return null;
}
},
async deleteSession({ event, }) {
if (!event)
throw new Error("Event is required to get the session in nuxtJsLightAuthSessionStore.");
deleteCookie(event, DEFAULT_SESSION_NAME);
},
async setSession({ env, session, event, }) {
if (!event)
throw new Error("Event is required to set the session in nuxtJsLightAuthSessionStore.");
const value = await encryptJwt(session, buildSecret(env));
// Check the size of the cookie value in bytes
const encoder = new TextEncoder();
const valueBytes = encoder.encode(value);
if (valueBytes.length > 4096)
throw new Error("light-auth: Cookie value exceeds 4096 bytes, which may not be supported by your browser.");
// maxAge: Specifies the number (in seconds) to be the value for the `Max-Age`
setCookie(event, DEFAULT_SESSION_NAME, value, {
httpOnly: true,
secure: true,
sameSite: "lax",
path: "/",
expires: new Date(session.expiresAt),
});
return session;
},
generateSessionId() {
return Math.random().toString(36).slice(2);
},
};
var nuxtjsLightAuthSessionStore = /*#__PURE__*/Object.freeze({
__proto__: null,
nuxtJsLightAuthSessionStore: nuxtJsLightAuthSessionStore
});
export { CreateLightAuth, nuxtJsLightAuthRouter, nuxtJsLightAuthSessionStore };
//# sourceMappingURL=index.mjs.map