UNPKG

@builder.io/qwik-auth

Version:

Qwik Auth is powered by Auth.js, a battle tested library for authentication with 3rd party providers

345 lines (344 loc) 11.5 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const qwikCity = require("@builder.io/qwik-city"); const qwik = require("@builder.io/qwik"); const core = require("@auth/core"); const build = require("@builder.io/qwik/build"); var setCookie = { exports: {} }; var defaultParseOptions = { decodeValues: true, map: false, silent: false }; function isNonEmptyString(str) { return typeof str === "string" && !!str.trim(); } function parseString(setCookieValue, options) { var parts = setCookieValue.split(";").filter(isNonEmptyString); var nameValuePairStr = parts.shift(); var parsed = parseNameValuePair(nameValuePairStr); var name = parsed.name; var value = parsed.value; options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; try { value = options.decodeValues ? decodeURIComponent(value) : value; } catch (e) { console.error( "set-cookie-parser encountered an error while decoding a cookie with value '" + value + "'. Set options.decodeValues to false to disable this feature.", e ); } var cookie = { name, value }; parts.forEach(function(part) { var sides = part.split("="); var key = sides.shift().trimLeft().toLowerCase(); var value2 = sides.join("="); if (key === "expires") { cookie.expires = new Date(value2); } else if (key === "max-age") { cookie.maxAge = parseInt(value2, 10); } else if (key === "secure") { cookie.secure = true; } else if (key === "httponly") { cookie.httpOnly = true; } else if (key === "samesite") { cookie.sameSite = value2; } else { cookie[key] = value2; } }); return cookie; } function parseNameValuePair(nameValuePairStr) { var name = ""; var value = ""; var nameValueArr = nameValuePairStr.split("="); if (nameValueArr.length > 1) { name = nameValueArr.shift(); value = nameValueArr.join("="); } else { value = nameValuePairStr; } return { name, value }; } function parse(input, options) { options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; if (!input) { if (!options.map) { return []; } else { return {}; } } if (input.headers) { if (typeof input.headers.getSetCookie === "function") { input = input.headers.getSetCookie(); } else if (input.headers["set-cookie"]) { input = input.headers["set-cookie"]; } else { var sch = input.headers[Object.keys(input.headers).find(function(key) { return key.toLowerCase() === "set-cookie"; })]; if (!sch && input.headers.cookie && !options.silent) { console.warn( "Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning." ); } input = sch; } } if (!Array.isArray(input)) { input = [input]; } options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions; if (!options.map) { return input.filter(isNonEmptyString).map(function(str) { return parseString(str, options); }); } else { var cookies = {}; return input.filter(isNonEmptyString).reduce(function(cookies2, str) { var cookie = parseString(str, options); cookies2[cookie.name] = cookie; return cookies2; }, cookies); } } function splitCookiesString(cookiesString) { if (Array.isArray(cookiesString)) { return cookiesString; } if (typeof cookiesString !== "string") { return []; } var cookiesStrings = []; var pos = 0; var start; var ch; var lastComma; var nextStart; var cookiesSeparatorFound; function skipWhitespace() { while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) { pos += 1; } return pos < cookiesString.length; } function notSpecialChar() { ch = cookiesString.charAt(pos); return ch !== "=" && ch !== ";" && ch !== ","; } while (pos < cookiesString.length) { start = pos; cookiesSeparatorFound = false; while (skipWhitespace()) { ch = cookiesString.charAt(pos); if (ch === ",") { lastComma = pos; pos += 1; skipWhitespace(); nextStart = pos; while (pos < cookiesString.length && notSpecialChar()) { pos += 1; } if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") { cookiesSeparatorFound = true; pos = nextStart; cookiesStrings.push(cookiesString.substring(start, lastComma)); start = pos; } else { pos = lastComma + 1; } } else { pos += 1; } } if (!cookiesSeparatorFound || pos >= cookiesString.length) { cookiesStrings.push(cookiesString.substring(start, cookiesString.length)); } } return cookiesStrings; } setCookie.exports = parse; setCookie.exports.parse = parse; var parseString_1 = setCookie.exports.parseString = parseString; var splitCookiesString_1 = setCookie.exports.splitCookiesString = splitCookiesString; const actions = [ "providers", "session", "csrf", "signin", "signout", "callback", "verify-request", "error" ]; function serverAuthQrl(authOptions) { const useAuthSignin = qwikCity.globalActionQrl(/* @__PURE__ */ qwik.inlinedQrl(async ({ providerId, callbackUrl: deprecated, options, authorizationParams }, req) => { const [authOptions2] = qwik.useLexicalScope(); if (deprecated) console.warn("\x1B[33mWARNING: callbackUrl is deprecated - use options.callbackUrl instead\x1B[0m"); const { callbackUrl = deprecated ?? defaultCallbackURL(req), ...rest } = options ?? {}; const isCredentials = providerId === "credentials"; const auth = await patchAuthOptions(authOptions2, req); const body = new URLSearchParams({ callbackUrl }); Object.entries(rest).forEach(([key, value]) => { body.set(key, String(value)); }); const baseSignInUrl = `/api/auth/${isCredentials ? "callback" : "signin"}${providerId ? `/${providerId}` : ""}`; const signInUrl = `${baseSignInUrl}?${new URLSearchParams(authorizationParams)}`; const data = await authAction(body, req, signInUrl, auth); req.cookie.set("authjs.callback-url", callbackUrl, { path: "/" }); if (data.url) throw req.redirect(301, data.url); }, "serverAuthQrl_useAuthSignin_globalAction_0BV7Pjvi9oE", [ authOptions ]), qwikCity.zodQrl(/* @__PURE__ */ qwik.inlinedQrl({ providerId: qwikCity.z.string().optional(), callbackUrl: qwikCity.z.string().optional(), options: qwikCity.z.object({ callbackUrl: qwikCity.z.string() }).passthrough().partial().optional(), authorizationParams: qwikCity.z.union([ qwikCity.z.string(), qwikCity.z.custom(), qwikCity.z.record(qwikCity.z.string()) ]).optional() }, "serverAuthQrl_useAuthSignin_globalAction_zod_Ng7oD9cW2Ss"))); const useAuthSignout = qwikCity.globalActionQrl(/* @__PURE__ */ qwik.inlinedQrl(async ({ callbackUrl }, req) => { const [authOptions2] = qwik.useLexicalScope(); callbackUrl ?? (callbackUrl = defaultCallbackURL(req)); const auth = await patchAuthOptions(authOptions2, req); const body = new URLSearchParams({ callbackUrl }); await authAction(body, req, `/api/auth/signout`, auth); }, "serverAuthQrl_useAuthSignout_globalAction_DcikjRBIaDE", [ authOptions ]), qwikCity.zodQrl(/* @__PURE__ */ qwik.inlinedQrl({ callbackUrl: qwikCity.z.string().optional() }, "serverAuthQrl_useAuthSignout_globalAction_zod_0HkNvbn18P4"))); const useAuthSession = qwikCity.routeLoaderQrl(/* @__PURE__ */ qwik.inlinedQrl((req) => { return req.sharedMap.get("session"); }, "serverAuthQrl_useAuthSession_routeLoader_g8XUlGCLMBQ")); const onRequest = async (req) => { if (build.isServer) { const prefix = "/api/auth"; const action = req.url.pathname.slice(prefix.length + 1).split("/")[0]; const auth = await patchAuthOptions(authOptions, req); if (actions.includes(action) && req.url.pathname.startsWith(prefix + "/")) { const res = await core.Auth(req.request, auth); const cookie = res.headers.get("set-cookie"); if (cookie) { req.headers.set("set-cookie", cookie); res.headers.delete("set-cookie"); fixCookies(req); } throw req.send(res); } else { const { data, cookie } = await getSessionData(req.request, auth); req.sharedMap.set("session", data); if (cookie) { req.headers.set("set-cookie", cookie); fixCookies(req); } } } }; return { useAuthSignin, useAuthSignout, useAuthSession, onRequest }; } const serverAuth$ = /* @__PURE__ */ qwik.implicit$FirstArg(serverAuthQrl); async function authAction(body, req, path, authOptions) { const request = new Request(new URL(path, req.request.url), { method: req.request.method, headers: req.request.headers, body }); request.headers.set("content-type", "application/x-www-form-urlencoded"); const res = await core.Auth(request, { ...authOptions, skipCSRFCheck: core.skipCSRFCheck }); const cookies = []; res.headers.forEach((value, key) => { if (key === "set-cookie") cookies.push(value); else if (!req.headers.has(key)) req.headers.set(key, value); }); if (cookies.length > 0) req.headers.set("set-cookie", cookies.join(", ")); fixCookies(req); try { return await res.json(); } catch (error) { return await res.text(); } } const fixCookies = (req) => { req.headers.set("set-cookie", req.headers.get("set-cookie") || ""); const cookie = req.headers.get("set-cookie"); if (cookie) { req.headers.delete("set-cookie"); splitCookiesString_1(cookie).forEach((cookie2) => { const { name, value, ...rest } = parseString_1(cookie2); req.cookie.set(name, value, rest); }); } }; const ensureAuthMiddleware = (req) => { const isLoggedIn = req.sharedMap.has("session"); if (!isLoggedIn) throw req.error(403, "sfs"); }; const defaultCallbackURL = (req) => { req.url.searchParams.delete("qaction"); return req.url.href; }; async function getSessionData(req, options) { options.secret ?? (options.secret = process.env.AUTH_SECRET); options.trustHost ?? (options.trustHost = true); const url = new URL("/api/auth/session", req.url); const response = await core.Auth(new Request(url, { headers: req.headers }), options); const { status = 200 } = response; const data = await response.json(); const cookie = response.headers.get("set-cookie"); if (!data || !Object.keys(data).length) return { data: null, cookie }; if (status === 200) return { data, cookie }; throw new Error(data.message); } const patchAuthOptions = async (authOptions, req) => { const options = await authOptions(req); return { ...options, basePath: "/api/auth" }; }; exports._auto_authAction = authAction; exports._auto_defaultCallbackURL = defaultCallbackURL; exports._auto_patchAuthOptions = patchAuthOptions; exports.ensureAuthMiddleware = ensureAuthMiddleware; exports.serverAuth$ = serverAuth$; exports.serverAuthQrl = serverAuthQrl;