UNPKG

@light-auth/nuxt

Version:

light auth framework for nuxt, using arctic

277 lines (269 loc) 12.3 kB
/*! @light-auth/nuxt v0.3.1 2025-06-13 */ 'use strict'; 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