@rpcbase/auth 0.100.0 → 0.102.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{handler-2sZNHSqb.js → handler-Bt53h0sk.js} +18 -6
- package/dist/{handler-2sZNHSqb.js.map → handler-Bt53h0sk.js.map} +1 -1
- package/dist/{handler-CXncjnG5.js → handler-Ck7oLQ_R.js} +34 -8
- package/dist/{handler-CXncjnG5.js.map → handler-Ck7oLQ_R.js.map} +1 -1
- package/dist/{handler-D9OypiUL.js → handler-CyP6R8FM.js} +4 -2
- package/dist/{handler-D9OypiUL.js.map → handler-CyP6R8FM.js.map} +1 -1
- package/dist/{handler-j0RdiReb.js → handler-D6zJn86A.js} +23 -7
- package/dist/{handler-j0RdiReb.js.map → handler-D6zJn86A.js.map} +1 -1
- package/dist/{handler-Db6lpg3J.js → handler-DfEsSB4T.js} +34 -9
- package/dist/{handler-Db6lpg3J.js.map → handler-DfEsSB4T.js.map} +1 -1
- package/dist/{handler--2n6PFBR.js → handler-xEpHnzkZ.js} +2 -2
- package/dist/{handler--2n6PFBR.js.map → handler-xEpHnzkZ.js.map} +1 -1
- package/dist/{index-BfZTJlGT.js → index-Bxz6YdiB.js} +4 -2
- package/dist/{index-BfZTJlGT.js.map → index-Bxz6YdiB.js.map} +1 -1
- package/dist/{index-DQy-Vgjt.js → index-C_uBu_fP.js} +4 -2
- package/dist/{index-DQy-Vgjt.js.map → index-C_uBu_fP.js.map} +1 -1
- package/dist/index.js +407 -194
- package/dist/index.js.map +1 -1
- package/dist/{middleware-HjIzPByj.js → middleware-5Zwy7HRL.js} +4 -2
- package/dist/{middleware-HjIzPByj.js.map → middleware-5Zwy7HRL.js.map} +1 -1
- package/dist/oauth/index.js +180 -41
- package/dist/oauth/index.js.map +1 -1
- package/dist/routes.js +1 -1
- package/dist/routes.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/components/AuthLayout/index.tsx","../src/components/AppleSignInButton/index.tsx","../src/components/EmailInput/index.tsx","../src/utils/sanitizeNextPath.ts","../src/components/SignInForm/index.tsx","../src/components/SignUpForm/index.tsx","../src/components/RememberMeCheckbox/index.tsx","../../../node_modules/lucide-react/dist/esm/shared/src/utils.js","../../../node_modules/lucide-react/dist/esm/defaultAttributes.js","../../../node_modules/lucide-react/dist/esm/Icon.js","../../../node_modules/lucide-react/dist/esm/createLucideIcon.js","../../../node_modules/lucide-react/dist/esm/icons/eye-off.js","../../../node_modules/lucide-react/dist/esm/icons/eye.js","../src/components/PasswordInput/index.tsx","../src/components/ResendCodeButton/index.tsx"],"sourcesContent":["import * as React from \"react\"\nimport {Link, useLocation } from \"@rpcbase/router\"\n\n\nconst LINKS_REDIRECTION_MAP = {\n \"/auth/sign-in\": {\n \"title\": \"Sign Up\",\n \"location\": \"/auth/sign-up\"\n },\n \"/auth/sign-up\": {\n \"title\": \"Sign In\",\n \"location\": \"/auth/sign-in\"\n },\n \"/auth/forgot-password\": {\n \"title\": \"Sign In\",\n \"location\": \"/auth/sign-in\"\n },\n \"/auth/logout-success\": {\n \"title\": \"Sign In\",\n \"location\": \"/auth/sign-in\"\n }\n}\n\ntype Pathname = keyof typeof LINKS_REDIRECTION_MAP\n\nexport const AuthLayout = ({\n sidePanel = null,\n children,\n}: {\n sidePanel: React.ReactElement | null\n children: React.ReactNode\n}) => {\n const location = useLocation()\n\n const linkTitle = LINKS_REDIRECTION_MAP[location.pathname as Pathname]?.title\n const linkLocation = LINKS_REDIRECTION_MAP[location.pathname as Pathname]?.location\n\n return (\n <div className=\"container relative hidden h-dvh flex-col items-center justify-center md:grid md:w-full lg:max-w-none lg:grid-cols-2 lg:px-0\">\n {/* Top-right redirection link */}\n {linkTitle && linkLocation ? (\n <Link\n className=\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-accent hover:text-accent-foreground h-9 px-4 py-2 absolute right-4 top-4 md:right-8 md:top-8\"\n to={linkLocation}\n >\n {linkTitle}\n </Link>\n ) : null}\n <div className=\"relative hidden h-full flex-col bg-muted p-10 text-white dark:border-r lg:flex\">\n {sidePanel}\n </div>\n <div className=\"mx-auto flex w-full flex-col justify-center gap-6 /*sm:w-[350px]*/\">\n {children}\n </div>\n </div>\n )\n}\n","import clsx from \"clsx\"\n\n\nexport const AppleSignInButton = ({\n onPress,\n className,\n}: {\n onPress: () => void;\n className?: string;\n}) => {\n\n return (\n <button\n onClick={onPress}\n className={clsx(`\n w-full\n bg-black text-white hover:bg-gray-800\n flex items-center justify-center\n px-6 py-2\n rounded-lg\n font-medium\n transition duration-150 ease-in-out\n focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black\n `, className)}\n >\n <svg\n className=\"w-5 h-5 mr-3\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"white\"\n >\n <path d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.539 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\" />\n </svg>\n <span>Continue with Apple</span>\n </button>\n )\n}\n","import {useFormContext} from \"@rpcbase/form\"\n\n\nexport const EmailInput = ({\n id,\n className,\n placeholder,\n}: {\n id: string\n className?: string\n placeholder?: string\n}) => {\n const {register, formState} = useFormContext()\n\n const error = formState.errors.email\n let errorMessage: string | undefined\n if (typeof error === \"string\") {\n errorMessage = error\n } else if (error && typeof error.message === \"string\") {\n errorMessage = error.message\n }\n\n return (\n <>\n <input\n id={id}\n type=\"email\"\n required\n autoComplete=\"email\"\n className={className}\n placeholder={placeholder}\n {...register(\"email\")}\n />\n {errorMessage ? (\n <p className=\"mt-1 -mb-2 text-sm/6 text-red-500\">{errorMessage}</p>\n ) : null}\n </>\n )\n}\n","const hasUnsafeNextPathChars = (value: string) => {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i)\n if (code === 92 || code <= 31 || code === 127) return true\n }\n return false\n}\n\nexport const sanitizeNextPath = (raw: string | null) => {\n if (!raw) return null\n\n const nextPath = raw.trim()\n if (!nextPath) return null\n\n if (!nextPath.startsWith(\"/\") || nextPath.startsWith(\"//\")) {\n return null\n }\n\n if (hasUnsafeNextPathChars(nextPath)) {\n return null\n }\n\n try {\n const base = new URL(\"http://localhost\")\n const url = new URL(nextPath, base)\n if (url.origin !== base.origin) {\n return null\n }\n return `${url.pathname}${url.search}${url.hash}`\n } catch {\n return null\n }\n}\n\n","import { ReactNode } from \"react\"\nimport { useNavigate, useSearchParams } from \"@rpcbase/router\"\nimport { useForm, FormProvider, zodResolver } from \"@rpcbase/form\"\nimport type { SubmitHandler } from \"@rpcbase/form\"\nimport { z } from \"zod\"\n\nimport {requestSchema} from \"../../api/sign-in\"\nimport { sanitizeNextPath } from \"../../utils/sanitizeNextPath\"\n\n\ntype SignInFormValues = z.input<typeof requestSchema>\n\nexport const SignInForm = ({\n children,\n className\n}: {\n children: ReactNode,\n className?: string\n}) => {\n const navigate = useNavigate()\n const [searchParams] = useSearchParams()\n\n const methods = useForm<SignInFormValues>({\n defaultValues: {\n email: \"\",\n password: \"\",\n rememberMe: true,\n },\n navigationGuard: false,\n resolver: zodResolver(requestSchema)\n })\n\n const onSubmit: SubmitHandler<SignInFormValues> = async (data) => {\n methods.clearErrors(\"root\")\n\n try {\n const res = await fetch(\"/api/rb/auth/sign-in\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(data),\n credentials: \"include\",\n })\n\n const json = await res.json().catch(() => null) as { success?: boolean; error?: string } | null\n\n if (!res.ok || !json?.success) {\n const message = json?.error === \"invalid_credentials\"\n ? \"Invalid email or password.\"\n : \"Sign-in failed. Please try again.\"\n methods.setError(\"root\", { type: \"server\", message })\n return\n }\n\n const nextPath = sanitizeNextPath(searchParams.get(\"next\")) ?? \"/\"\n navigate(nextPath, { replace: true })\n } catch (err) {\n methods.setError(\"root\", { type: \"server\", message: \"Network error. Please try again.\" })\n }\n }\n\n return (\n <FormProvider {...methods}>\n <form method=\"post\" noValidate className={className} onSubmit={methods.handleSubmit(onSubmit)}>\n {children}\n {methods.formState.errors.root?.message && (\n <p className=\"mt-2 text-sm text-red-600\" role=\"alert\">\n {methods.formState.errors.root.message}\n </p>\n )}\n </form>\n </FormProvider>\n )\n}\n","import {ReactNode, useState} from \"react\"\nimport { useNavigate } from \"@rpcbase/router\"\nimport { useForm, FormProvider, zodResolver } from \"@rpcbase/form\"\nimport type {SubmitHandler} from \"@rpcbase/form\"\nimport { z } from \"zod\"\n\nimport {requestSchema} from \"../../api/sign-up\"\n\n\ntype SignUpFormValues = z.input<typeof requestSchema>\n\n\nexport const SignUpForm = ({\n children,\n className,\n otpNextPath\n}: {\n children: ReactNode,\n className?: string\n otpNextPath?: string\n}) => {\n\n const navigate = useNavigate()\n\n const [serverMessage, setServerMessage] = useState<string | null>(null)\n const methods = useForm<SignUpFormValues>({\n defaultValues: {\n email: \"\",\n password: \"\",\n rememberMe: true,\n },\n navigationGuard: false,\n resolver: zodResolver(requestSchema)\n })\n\n const onSubmit: SubmitHandler<SignUpFormValues> = async (data) => {\n setServerMessage(null)\n methods.clearErrors(\"root\")\n\n try {\n const res = await fetch(\"/api/rb/auth/sign-up\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(data),\n credentials: \"include\",\n })\n\n const json = await res.json()\n\n if (!res.ok) {\n const message = json.error === \"user_exists\"\n ? \"An account already exists with this email.\"\n : \"Sign-up failed. Please try again.\"\n methods.setError(\"root\", { type: \"server\", message })\n return\n }\n\n if (!json.success) {\n methods.setError(\"root\", { type: \"server\", message: \"Sign-up failed. Please try again.\" })\n return\n }\n\n const search = new URLSearchParams({ email: data.email })\n if (otpNextPath) {\n search.set(\"next\", otpNextPath)\n }\n navigate(`/auth/sign-up-otp?${search.toString()}`)\n setServerMessage(\"Account created. Check your inbox to verify your email.\")\n } catch (err) {\n methods.setError(\"root\", { type: \"server\", message: \"Network error. Please try again.\" })\n }\n }\n\n return (\n <FormProvider {...methods}>\n <form method=\"post\" noValidate className={className} onSubmit={methods.handleSubmit(onSubmit)}>\n {children}\n {methods.formState.errors.root?.message && (\n <p className=\"mt-2 text-sm text-red-600\" role=\"alert\">\n {methods.formState.errors.root.message}\n </p>\n )}\n {serverMessage && (\n <p className=\"mt-2 text-sm text-green-700\" role=\"status\">\n {serverMessage}\n </p>\n )}\n </form>\n </FormProvider>\n )\n}\n","import type { ElementType } from \"react\"\nimport {useFormContext} from \"@rpcbase/form\"\n\n\nexport const RememberMeCheckbox = ({\n label,\n as: Component = \"input\"\n}: {\n label: string,\n as?: ElementType\n}) => {\n const {register} = useFormContext()\n\n return (\n <>\n <Component\n id=\"rememberMe\"\n {...register(\"rememberMe\")}\n />\n <label\n htmlFor={\"rememberMe\"}\n className=\"pl-2 block text-sm/6 text-gray-900\"\n >\n {label}\n </label>\n </>\n )\n}\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n};\n\nexport { hasA11yProp, mergeClasses, toCamelCase, toKebabCase, toPascalCase };\n//# sourceMappingURL=utils.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { mergeClasses, hasA11yProp } from './shared/src/utils.js';\n\nconst Icon = forwardRef(\n ({\n color = \"currentColor\",\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = \"\",\n children,\n iconNode,\n ...rest\n }, ref) => createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n className: mergeClasses(\"lucide\", className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n )\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses, toKebabCase, toPascalCase } from './shared/src/utils.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\",\n key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n d: \"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\",\n key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n];\nconst EyeOff = createLucideIcon(\"eye-off\", __iconNode);\n\nexport { __iconNode, EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n];\nconst Eye = createLucideIcon(\"eye\", __iconNode);\n\nexport { __iconNode, Eye as default };\n//# sourceMappingURL=eye.js.map\n","import { useState } from \"react\"\nimport { Eye, EyeOff } from \"lucide-react\"\nimport { useFormContext } from \"@rpcbase/form\"\n\n\ntype PasswordInputProps = {\n id: string\n name?: string\n className?: string\n placeholder?: string\n autoComplete?: string\n}\n\nexport const PasswordInput = ({\n id,\n name = \"password\",\n className,\n placeholder,\n autoComplete = \"current-password\",\n}: PasswordInputProps) => {\n const [showPassword, setShowPassword] = useState(false)\n const { register, formState } = useFormContext()\n\n const fieldError = formState.errors[name as keyof typeof formState.errors]\n const errorMessage =\n typeof fieldError === \"string\"\n ? fieldError\n : typeof fieldError?.message === \"string\"\n ? fieldError.message\n : undefined\n\n const inputClassName = className ? `${className} pr-11` : \"pr-11\"\n\n return (\n <>\n <div className=\"relative\">\n <input\n id={id}\n type={showPassword ? \"text\" : \"password\"}\n autoComplete={autoComplete}\n className={inputClassName}\n placeholder={placeholder}\n {...register(name as Parameters<typeof register>[0])}\n />\n <button\n type=\"button\"\n className=\"absolute inset-y-0 right-0 flex items-center pr-3 text-gray-500\"\n onClick={() => setShowPassword((prev) => !prev)}\n aria-label={showPassword ? \"Hide characters\" : \"Show characters\"}\n >\n {showPassword ? (\n <EyeOff className=\"h-5 w-5\" aria-hidden />\n ) : (\n <Eye className=\"h-5 w-5\" aria-hidden />\n )}\n </button>\n </div>\n {errorMessage ? (\n <p className=\"mt-1 -mb-2 text-sm/6 text-red-500\">{errorMessage}</p>\n ) : null}\n </>\n )\n}\n","import {useCallback, useEffect, useMemo, useState} from \"react\"\nimport clsx from \"clsx\"\n\n\nexport const useResendCountdown = (seconds = 60) => {\n const [remaining, setRemaining] = useState(seconds)\n const [isCountingDown, setIsCountingDown] = useState(true)\n\n useEffect(() => {\n if (!isCountingDown) return\n\n const timer = setInterval(() => {\n setRemaining((prev) => {\n if (prev <= 1) {\n setIsCountingDown(false)\n return seconds\n }\n return prev - 1\n })\n }, 1000)\n\n return () => clearInterval(timer)\n }, [isCountingDown, seconds])\n\n const restart = useCallback((nextSeconds?: number) => {\n const value = typeof nextSeconds === \"number\" ? nextSeconds : seconds\n setRemaining(value)\n setIsCountingDown(true)\n }, [seconds])\n\n const formatted = useMemo(() => {\n const minutes = Math.floor(remaining / 60)\n const secs = remaining % 60\n return `${minutes}:${secs.toString().padStart(2, \"0\")}`\n }, [remaining])\n\n const canResend = !isCountingDown\n\n return {remaining, formatted, isCountingDown, canResend, restart}\n}\n\n\nexport const ResendCodeButton = ({\n seconds = 60,\n onResend,\n className,\n disabled,\n}: {\n seconds?: number\n onResend?: () => Promise<void> | void\n className?: string\n disabled?: boolean\n}) => {\n const [isSending, setIsSending] = useState(false)\n const {formatted, isCountingDown, restart, canResend} = useResendCountdown(seconds)\n\n const handleClick = async () => {\n if (!canResend || isSending || disabled) return\n\n try {\n setIsSending(true)\n if (onResend) {\n await onResend()\n }\n } finally {\n restart()\n setIsSending(false)\n }\n }\n\n const isDisabled = disabled || isCountingDown || isSending\n const showCountdown = isDisabled && (isCountingDown || isSending)\n\n return (\n <span className=\"inline-flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isDisabled}\n aria-label=\"Resend code\"\n className={clsx(\n \"text-sm font-semibold text-sky-600 hover:underline disabled:cursor-not-allowed disabled:text-gray-400\",\n className\n )}\n >\n Resend code\n </button>\n {showCountdown ? (\n <span\n data-testid=\"resend-countdown\"\n className=\"text-sm text-gray-500\"\n aria-live=\"polite\"\n >\n ({formatted})\n </span>\n ) : null}\n </span>\n )\n}\n"],"names":["requestSchema","__iconNode"],"mappings":"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","x_google_ignoreList":[7,8,9,10,11,12]}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/components/AuthLayout/index.tsx","../src/components/AppleSignInButton/index.tsx","../src/components/EmailInput/index.tsx","../src/utils/sanitizeNextPath.ts","../src/components/SignInForm/index.tsx","../src/components/SignUpForm/index.tsx","../src/components/RememberMeCheckbox/index.tsx","../../../node_modules/lucide-react/dist/esm/shared/src/utils.js","../../../node_modules/lucide-react/dist/esm/defaultAttributes.js","../../../node_modules/lucide-react/dist/esm/Icon.js","../../../node_modules/lucide-react/dist/esm/createLucideIcon.js","../../../node_modules/lucide-react/dist/esm/icons/eye-off.js","../../../node_modules/lucide-react/dist/esm/icons/eye.js","../src/components/PasswordInput/index.tsx","../src/components/ResendCodeButton/index.tsx"],"sourcesContent":["import * as React from \"react\"\nimport {Link, useLocation } from \"@rpcbase/router\"\n\n\nconst LINKS_REDIRECTION_MAP = {\n \"/auth/sign-in\": {\n \"title\": \"Sign Up\",\n \"location\": \"/auth/sign-up\"\n },\n \"/auth/sign-up\": {\n \"title\": \"Sign In\",\n \"location\": \"/auth/sign-in\"\n },\n \"/auth/forgot-password\": {\n \"title\": \"Sign In\",\n \"location\": \"/auth/sign-in\"\n },\n \"/auth/logout-success\": {\n \"title\": \"Sign In\",\n \"location\": \"/auth/sign-in\"\n }\n}\n\ntype Pathname = keyof typeof LINKS_REDIRECTION_MAP\n\nexport const AuthLayout = ({\n sidePanel = null,\n children,\n}: {\n sidePanel: React.ReactElement | null\n children: React.ReactNode\n}) => {\n const location = useLocation()\n\n const linkTitle = LINKS_REDIRECTION_MAP[location.pathname as Pathname]?.title\n const linkLocation = LINKS_REDIRECTION_MAP[location.pathname as Pathname]?.location\n\n return (\n <div className=\"container relative hidden h-dvh flex-col items-center justify-center md:grid md:w-full lg:max-w-none lg:grid-cols-2 lg:px-0\">\n {/* Top-right redirection link */}\n {linkTitle && linkLocation ? (\n <Link\n className=\"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 hover:bg-accent hover:text-accent-foreground h-9 px-4 py-2 absolute right-4 top-4 md:right-8 md:top-8\"\n to={linkLocation}\n >\n {linkTitle}\n </Link>\n ) : null}\n <div className=\"relative hidden h-full flex-col bg-muted p-10 text-white dark:border-r lg:flex\">\n {sidePanel}\n </div>\n <div className=\"mx-auto flex w-full flex-col justify-center gap-6 /*sm:w-[350px]*/\">\n {children}\n </div>\n </div>\n )\n}\n","import clsx from \"clsx\"\n\n\nexport const AppleSignInButton = ({\n onPress,\n className,\n}: {\n onPress: () => void;\n className?: string;\n}) => {\n\n return (\n <button\n onClick={onPress}\n className={clsx(`\n w-full\n bg-black text-white hover:bg-gray-800\n flex items-center justify-center\n px-6 py-2\n rounded-lg\n font-medium\n transition duration-150 ease-in-out\n focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black\n `, className)}\n >\n <svg\n className=\"w-5 h-5 mr-3\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"white\"\n >\n <path d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.539 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\" />\n </svg>\n <span>Continue with Apple</span>\n </button>\n )\n}\n","import {useFormContext} from \"@rpcbase/form\"\n\n\nexport const EmailInput = ({\n id,\n className,\n placeholder,\n}: {\n id: string\n className?: string\n placeholder?: string\n}) => {\n const {register, formState} = useFormContext()\n\n const error = formState.errors.email\n let errorMessage: string | undefined\n if (typeof error === \"string\") {\n errorMessage = error\n } else if (error && typeof error.message === \"string\") {\n errorMessage = error.message\n }\n\n return (\n <>\n <input\n id={id}\n type=\"email\"\n required\n autoComplete=\"email\"\n className={className}\n placeholder={placeholder}\n {...register(\"email\")}\n />\n {errorMessage ? (\n <p className=\"mt-1 -mb-2 text-sm/6 text-red-500\">{errorMessage}</p>\n ) : null}\n </>\n )\n}\n","const hasUnsafeNextPathChars = (value: string) => {\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i)\n if (code === 92 || code <= 31 || code === 127) return true\n }\n return false\n}\n\nexport const sanitizeNextPath = (raw: string | null) => {\n if (!raw) return null\n\n const nextPath = raw.trim()\n if (!nextPath) return null\n\n if (!nextPath.startsWith(\"/\") || nextPath.startsWith(\"//\")) {\n return null\n }\n\n if (hasUnsafeNextPathChars(nextPath)) {\n return null\n }\n\n try {\n const base = new URL(\"http://localhost\")\n const url = new URL(nextPath, base)\n if (url.origin !== base.origin) {\n return null\n }\n return `${url.pathname}${url.search}${url.hash}`\n } catch {\n return null\n }\n}\n\n","import { ReactNode } from \"react\"\nimport { useNavigate, useSearchParams } from \"@rpcbase/router\"\nimport { useForm, FormProvider, zodResolver } from \"@rpcbase/form\"\nimport type { SubmitHandler } from \"@rpcbase/form\"\nimport { z } from \"zod\"\n\nimport {requestSchema} from \"../../api/sign-in\"\nimport { sanitizeNextPath } from \"../../utils/sanitizeNextPath\"\n\n\ntype SignInFormValues = z.input<typeof requestSchema>\n\nexport const SignInForm = ({\n children,\n className\n}: {\n children: ReactNode,\n className?: string\n}) => {\n const navigate = useNavigate()\n const [searchParams] = useSearchParams()\n\n const methods = useForm<SignInFormValues>({\n defaultValues: {\n email: \"\",\n password: \"\",\n rememberMe: true,\n },\n navigationGuard: false,\n resolver: zodResolver(requestSchema)\n })\n\n const onSubmit: SubmitHandler<SignInFormValues> = async (data) => {\n methods.clearErrors(\"root\")\n\n try {\n const res = await fetch(\"/api/rb/auth/sign-in\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(data),\n credentials: \"include\",\n })\n\n const json = await res.json().catch(() => null) as { success?: boolean; error?: string } | null\n\n if (!res.ok || !json?.success) {\n const message = json?.error === \"invalid_credentials\"\n ? \"Invalid email or password.\"\n : \"Sign-in failed. Please try again.\"\n methods.setError(\"root\", { type: \"server\", message })\n return\n }\n\n const nextPath = sanitizeNextPath(searchParams.get(\"next\")) ?? \"/\"\n navigate(nextPath, { replace: true })\n } catch (err) {\n methods.setError(\"root\", { type: \"server\", message: \"Network error. Please try again.\" })\n }\n }\n\n return (\n <FormProvider {...methods}>\n <form method=\"post\" noValidate className={className} onSubmit={methods.handleSubmit(onSubmit)}>\n {children}\n {methods.formState.errors.root?.message && (\n <p className=\"mt-2 text-sm text-red-600\" role=\"alert\">\n {methods.formState.errors.root.message}\n </p>\n )}\n </form>\n </FormProvider>\n )\n}\n","import {ReactNode, useState} from \"react\"\nimport { useNavigate } from \"@rpcbase/router\"\nimport { useForm, FormProvider, zodResolver } from \"@rpcbase/form\"\nimport type {SubmitHandler} from \"@rpcbase/form\"\nimport { z } from \"zod\"\n\nimport {requestSchema} from \"../../api/sign-up\"\n\n\ntype SignUpFormValues = z.input<typeof requestSchema>\n\n\nexport const SignUpForm = ({\n children,\n className,\n otpNextPath\n}: {\n children: ReactNode,\n className?: string\n otpNextPath?: string\n}) => {\n\n const navigate = useNavigate()\n\n const [serverMessage, setServerMessage] = useState<string | null>(null)\n const methods = useForm<SignUpFormValues>({\n defaultValues: {\n email: \"\",\n password: \"\",\n rememberMe: true,\n },\n navigationGuard: false,\n resolver: zodResolver(requestSchema)\n })\n\n const onSubmit: SubmitHandler<SignUpFormValues> = async (data) => {\n setServerMessage(null)\n methods.clearErrors(\"root\")\n\n try {\n const res = await fetch(\"/api/rb/auth/sign-up\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(data),\n credentials: \"include\",\n })\n\n const json = await res.json()\n\n if (!res.ok) {\n const message = json.error === \"user_exists\"\n ? \"An account already exists with this email.\"\n : \"Sign-up failed. Please try again.\"\n methods.setError(\"root\", { type: \"server\", message })\n return\n }\n\n if (!json.success) {\n methods.setError(\"root\", { type: \"server\", message: \"Sign-up failed. Please try again.\" })\n return\n }\n\n const search = new URLSearchParams({ email: data.email })\n if (otpNextPath) {\n search.set(\"next\", otpNextPath)\n }\n navigate(`/auth/sign-up-otp?${search.toString()}`)\n setServerMessage(\"Account created. Check your inbox to verify your email.\")\n } catch (err) {\n methods.setError(\"root\", { type: \"server\", message: \"Network error. Please try again.\" })\n }\n }\n\n return (\n <FormProvider {...methods}>\n <form method=\"post\" noValidate className={className} onSubmit={methods.handleSubmit(onSubmit)}>\n {children}\n {methods.formState.errors.root?.message && (\n <p className=\"mt-2 text-sm text-red-600\" role=\"alert\">\n {methods.formState.errors.root.message}\n </p>\n )}\n {serverMessage && (\n <p className=\"mt-2 text-sm text-green-700\" role=\"status\">\n {serverMessage}\n </p>\n )}\n </form>\n </FormProvider>\n )\n}\n","import type { ElementType } from \"react\"\nimport {useFormContext} from \"@rpcbase/form\"\n\n\nexport const RememberMeCheckbox = ({\n label,\n as: Component = \"input\"\n}: {\n label: string,\n as?: ElementType\n}) => {\n const {register} = useFormContext()\n\n return (\n <>\n <Component\n id=\"rememberMe\"\n {...register(\"rememberMe\")}\n />\n <label\n htmlFor={\"rememberMe\"}\n className=\"pl-2 block text-sm/6 text-gray-900\"\n >\n {label}\n </label>\n </>\n )\n}\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n};\n\nexport { hasA11yProp, mergeClasses, toCamelCase, toKebabCase, toPascalCase };\n//# sourceMappingURL=utils.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { mergeClasses, hasA11yProp } from './shared/src/utils.js';\n\nconst Icon = forwardRef(\n ({\n color = \"currentColor\",\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = \"\",\n children,\n iconNode,\n ...rest\n }, ref) => createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n className: mergeClasses(\"lucide\", className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n )\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses, toKebabCase, toPascalCase } from './shared/src/utils.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\",\n key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n d: \"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\",\n key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n];\nconst EyeOff = createLucideIcon(\"eye-off\", __iconNode);\n\nexport { __iconNode, EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","/**\n * @license lucide-react v0.562.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n];\nconst Eye = createLucideIcon(\"eye\", __iconNode);\n\nexport { __iconNode, Eye as default };\n//# sourceMappingURL=eye.js.map\n","import { useState } from \"react\"\nimport { Eye, EyeOff } from \"lucide-react\"\nimport { useFormContext } from \"@rpcbase/form\"\n\n\ntype PasswordInputProps = {\n id: string\n name?: string\n className?: string\n placeholder?: string\n autoComplete?: string\n}\n\nexport const PasswordInput = ({\n id,\n name = \"password\",\n className,\n placeholder,\n autoComplete = \"current-password\",\n}: PasswordInputProps) => {\n const [showPassword, setShowPassword] = useState(false)\n const { register, formState } = useFormContext()\n\n const fieldError = formState.errors[name as keyof typeof formState.errors]\n const errorMessage =\n typeof fieldError === \"string\"\n ? fieldError\n : typeof fieldError?.message === \"string\"\n ? fieldError.message\n : undefined\n\n const inputClassName = className ? `${className} pr-11` : \"pr-11\"\n\n return (\n <>\n <div className=\"relative\">\n <input\n id={id}\n type={showPassword ? \"text\" : \"password\"}\n autoComplete={autoComplete}\n className={inputClassName}\n placeholder={placeholder}\n {...register(name as Parameters<typeof register>[0])}\n />\n <button\n type=\"button\"\n className=\"absolute inset-y-0 right-0 flex items-center pr-3 text-gray-500\"\n onClick={() => setShowPassword((prev) => !prev)}\n aria-label={showPassword ? \"Hide characters\" : \"Show characters\"}\n >\n {showPassword ? (\n <EyeOff className=\"h-5 w-5\" aria-hidden />\n ) : (\n <Eye className=\"h-5 w-5\" aria-hidden />\n )}\n </button>\n </div>\n {errorMessage ? (\n <p className=\"mt-1 -mb-2 text-sm/6 text-red-500\">{errorMessage}</p>\n ) : null}\n </>\n )\n}\n","import {useCallback, useEffect, useMemo, useState} from \"react\"\nimport clsx from \"clsx\"\n\n\nexport const useResendCountdown = (seconds = 60) => {\n const [remaining, setRemaining] = useState(seconds)\n const [isCountingDown, setIsCountingDown] = useState(true)\n\n useEffect(() => {\n if (!isCountingDown) return\n\n const timer = setInterval(() => {\n setRemaining((prev) => {\n if (prev <= 1) {\n setIsCountingDown(false)\n return seconds\n }\n return prev - 1\n })\n }, 1000)\n\n return () => clearInterval(timer)\n }, [isCountingDown, seconds])\n\n const restart = useCallback((nextSeconds?: number) => {\n const value = typeof nextSeconds === \"number\" ? nextSeconds : seconds\n setRemaining(value)\n setIsCountingDown(true)\n }, [seconds])\n\n const formatted = useMemo(() => {\n const minutes = Math.floor(remaining / 60)\n const secs = remaining % 60\n return `${minutes}:${secs.toString().padStart(2, \"0\")}`\n }, [remaining])\n\n const canResend = !isCountingDown\n\n return {remaining, formatted, isCountingDown, canResend, restart}\n}\n\n\nexport const ResendCodeButton = ({\n seconds = 60,\n onResend,\n className,\n disabled,\n}: {\n seconds?: number\n onResend?: () => Promise<void> | void\n className?: string\n disabled?: boolean\n}) => {\n const [isSending, setIsSending] = useState(false)\n const {formatted, isCountingDown, restart, canResend} = useResendCountdown(seconds)\n\n const handleClick = async () => {\n if (!canResend || isSending || disabled) return\n\n try {\n setIsSending(true)\n if (onResend) {\n await onResend()\n }\n } finally {\n restart()\n setIsSending(false)\n }\n }\n\n const isDisabled = disabled || isCountingDown || isSending\n const showCountdown = isDisabled && (isCountingDown || isSending)\n\n return (\n <span className=\"inline-flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isDisabled}\n aria-label=\"Resend code\"\n className={clsx(\n \"text-sm font-semibold text-sky-600 hover:underline disabled:cursor-not-allowed disabled:text-gray-400\",\n className\n )}\n >\n Resend code\n </button>\n {showCountdown ? (\n <span\n data-testid=\"resend-countdown\"\n className=\"text-sm text-gray-500\"\n aria-live=\"polite\"\n >\n ({formatted})\n </span>\n ) : null}\n </span>\n )\n}\n"],"names":["LINKS_REDIRECTION_MAP","AuthLayout","t0","$","_c","sidePanel","t1","children","undefined","location","useLocation","linkTitle","pathname","title","linkLocation","t2","t3","t4","t5","AppleSignInButton","onPress","className","clsx","Symbol","for","EmailInput","id","placeholder","register","formState","useFormContext","error","errors","email","errorMessage","message","hasUnsafeNextPathChars","value","i","length","code","charCodeAt","sanitizeNextPath","raw","nextPath","trim","startsWith","base","URL","url","origin","search","hash","SignInForm","navigate","useNavigate","searchParams","useSearchParams","methods","useForm","defaultValues","password","rememberMe","navigationGuard","resolver","zodResolver","requestSchema","onSubmit","data","clearErrors","res","fetch","method","headers","body","JSON","stringify","credentials","json","catch","ok","success","setError","type","get","replace","err","handleSubmit","root","SignUpForm","otpNextPath","serverMessage","setServerMessage","useState","URLSearchParams","set","toString","RememberMeCheckbox","label","as","Component","__iconNode","PasswordInput","name","autoComplete","showPassword","setShowPassword","fieldError","inputClassName","t6","t7","_temp","t8","t9","t10","t11","t12","t13","prev","useResendCountdown","seconds","remaining","setRemaining","isCountingDown","setIsCountingDown","timer","setInterval","clearInterval","useEffect","nextSeconds","restart","minutes","Math","floor","secs","padStart","formatted","canResend","ResendCodeButton","onResend","disabled","isSending","setIsSending","handleClick","isDisabled","showCountdown"],"mappings":"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","x_google_ignoreList":[7,8,9,10,11,12]}
|
|
@@ -6,7 +6,9 @@ const restrictSessionMiddleware = (req, res, next) => {
|
|
|
6
6
|
if (isAuthenticated(req)) {
|
|
7
7
|
return next();
|
|
8
8
|
}
|
|
9
|
-
res.status(401).json({
|
|
9
|
+
res.status(401).json({
|
|
10
|
+
error: "unauthorized"
|
|
11
|
+
});
|
|
10
12
|
};
|
|
11
13
|
const requireSession = restrictSessionMiddleware;
|
|
12
14
|
const redirectAuthMiddleware = (req, res, next) => {
|
|
@@ -20,4 +22,4 @@ export {
|
|
|
20
22
|
redirectAuthMiddleware as b,
|
|
21
23
|
restrictSessionMiddleware as r
|
|
22
24
|
};
|
|
23
|
-
//# sourceMappingURL=middleware-
|
|
25
|
+
//# sourceMappingURL=middleware-5Zwy7HRL.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware-
|
|
1
|
+
{"version":3,"file":"middleware-5Zwy7HRL.js","sources":["../src/middleware.ts"],"sourcesContent":["import type { Middleware } from \"@rpcbase/api\"\n\nimport type { AuthSessionUser } from \"./types\"\n\n\nconst isAuthenticated = (req: Parameters<Middleware>[0]): req is Parameters<Middleware<AuthSessionUser>>[0] => {\n const sessionUser = req.session?.user as { id?: unknown } | undefined\n return Boolean(sessionUser?.id)\n}\n\nexport const restrictSessionMiddleware: Middleware<AuthSessionUser> = (req, res, next) => {\n if (isAuthenticated(req)) {\n return next()\n }\n\n res.status(401).json({ error: \"unauthorized\" })\n}\n\nexport const requireSession = restrictSessionMiddleware\n\nexport const redirectAuthMiddleware: Middleware<AuthSessionUser> = (req, res, next) => {\n if (req.path.startsWith(\"/app\") && !isAuthenticated(req)) {\n return res.redirect(\"/auth/sign-in\")\n }\n\n next()\n}\n"],"names":["isAuthenticated","req","sessionUser","session","user","Boolean","id","restrictSessionMiddleware","res","next","status","json","error","requireSession","redirectAuthMiddleware","path","startsWith","redirect"],"mappings":"AAKA,MAAMA,kBAAkBA,CAACC,QAAsF;AAC7G,QAAMC,cAAcD,IAAIE,SAASC;AACjC,SAAOC,QAAQH,aAAaI,EAAE;AAChC;AAEO,MAAMC,4BAAyDA,CAACN,KAAKO,KAAKC,SAAS;AACxF,MAAIT,gBAAgBC,GAAG,GAAG;AACxB,WAAOQ,KAAAA;AAAAA,EACT;AAEAD,MAAIE,OAAO,GAAG,EAAEC,KAAK;AAAA,IAAEC,OAAO;AAAA,EAAA,CAAgB;AAChD;AAEO,MAAMC,iBAAiBN;AAEvB,MAAMO,yBAAsDA,CAACb,KAAKO,KAAKC,SAAS;AACrF,MAAIR,IAAIc,KAAKC,WAAW,MAAM,KAAK,CAAChB,gBAAgBC,GAAG,GAAG;AACxD,WAAOO,IAAIS,SAAS,eAAe;AAAA,EACrC;AAEAR,OAAAA;AACF;"}
|
package/dist/oauth/index.js
CHANGED
|
@@ -8,7 +8,9 @@ const getStore = () => {
|
|
|
8
8
|
if (existing && typeof existing === "object" && existing.providers && typeof existing.providers === "object") {
|
|
9
9
|
return existing;
|
|
10
10
|
}
|
|
11
|
-
const created = {
|
|
11
|
+
const created = {
|
|
12
|
+
providers: {}
|
|
13
|
+
};
|
|
12
14
|
anyGlobal[STORE_KEY] = created;
|
|
13
15
|
return created;
|
|
14
16
|
};
|
|
@@ -45,7 +47,10 @@ const normalizeProviders = (providers) => {
|
|
|
45
47
|
const configureOAuthProviders = (providers) => {
|
|
46
48
|
const store = getStore();
|
|
47
49
|
const normalized = normalizeProviders(providers);
|
|
48
|
-
store.providers = {
|
|
50
|
+
store.providers = {
|
|
51
|
+
...store.providers,
|
|
52
|
+
...normalized
|
|
53
|
+
};
|
|
49
54
|
};
|
|
50
55
|
const setOAuthProviders = (providers) => {
|
|
51
56
|
const store = getStore();
|
|
@@ -84,7 +89,11 @@ const getOidcWellKnown = async (issuerRaw) => {
|
|
|
84
89
|
}
|
|
85
90
|
const loader = (async () => {
|
|
86
91
|
const url = new URL("/.well-known/openid-configuration", issuer);
|
|
87
|
-
const response = await fetch(url, {
|
|
92
|
+
const response = await fetch(url, {
|
|
93
|
+
headers: {
|
|
94
|
+
Accept: "application/json"
|
|
95
|
+
}
|
|
96
|
+
});
|
|
88
97
|
if (!response.ok) {
|
|
89
98
|
const body = await response.text().catch(() => "");
|
|
90
99
|
throw new Error(`Failed to fetch OIDC discovery document: ${response.status} ${body}`);
|
|
@@ -121,7 +130,10 @@ const base64UrlEncode$1 = (input) => input.toString("base64").replace(/\+/g, "-"
|
|
|
121
130
|
const generatePkcePair = () => {
|
|
122
131
|
const verifier = base64UrlEncode$1(crypto.randomBytes(32));
|
|
123
132
|
const challenge = base64UrlEncode$1(crypto.createHash("sha256").update(verifier).digest());
|
|
124
|
-
return {
|
|
133
|
+
return {
|
|
134
|
+
verifier,
|
|
135
|
+
challenge
|
|
136
|
+
};
|
|
125
137
|
};
|
|
126
138
|
const RESERVED_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
127
139
|
const isSafeOAuthProviderId = (value) => {
|
|
@@ -220,26 +232,49 @@ const getOAuthStartRedirectUrl = async ({
|
|
|
220
232
|
}) => {
|
|
221
233
|
const providerId = resolveProviderId(ctx, providerIdOverride);
|
|
222
234
|
if (!providerId) {
|
|
223
|
-
return {
|
|
235
|
+
return {
|
|
236
|
+
success: false,
|
|
237
|
+
error: "missing_provider",
|
|
238
|
+
statusCode: 400
|
|
239
|
+
};
|
|
224
240
|
}
|
|
225
241
|
if (!isSafeOAuthProviderId(providerId)) {
|
|
226
|
-
return {
|
|
242
|
+
return {
|
|
243
|
+
success: false,
|
|
244
|
+
error: "invalid_provider",
|
|
245
|
+
statusCode: 400
|
|
246
|
+
};
|
|
227
247
|
}
|
|
228
248
|
const provider = getOAuthProviderConfig(providerId);
|
|
229
249
|
if (!provider) {
|
|
230
|
-
return {
|
|
250
|
+
return {
|
|
251
|
+
success: false,
|
|
252
|
+
error: "unknown_provider",
|
|
253
|
+
statusCode: 404
|
|
254
|
+
};
|
|
231
255
|
}
|
|
232
256
|
const origin = getRequestOrigin(ctx);
|
|
233
257
|
if (!origin) {
|
|
234
|
-
return {
|
|
258
|
+
return {
|
|
259
|
+
success: false,
|
|
260
|
+
error: "origin_unavailable",
|
|
261
|
+
statusCode: 500
|
|
262
|
+
};
|
|
235
263
|
}
|
|
236
264
|
const isHttps = origin.startsWith("https://");
|
|
237
265
|
const callbackPath = resolveCallbackPath(provider.callbackPath);
|
|
238
266
|
if (!callbackPath) {
|
|
239
|
-
return {
|
|
267
|
+
return {
|
|
268
|
+
success: false,
|
|
269
|
+
error: "invalid_callback_path",
|
|
270
|
+
statusCode: 500
|
|
271
|
+
};
|
|
240
272
|
}
|
|
241
273
|
const state = crypto.randomBytes(16).toString("hex");
|
|
242
|
-
const {
|
|
274
|
+
const {
|
|
275
|
+
verifier,
|
|
276
|
+
challenge
|
|
277
|
+
} = generatePkcePair();
|
|
243
278
|
const safeReturnTo = typeof returnTo === "string" && isSafeRedirectPath(returnTo) ? returnTo : void 0;
|
|
244
279
|
try {
|
|
245
280
|
const OAuthRequest = await models.getGlobal("RBOAuthRequest", ctx);
|
|
@@ -254,7 +289,11 @@ const getOAuthStartRedirectUrl = async ({
|
|
|
254
289
|
});
|
|
255
290
|
} catch (err) {
|
|
256
291
|
console.warn("oauth::failed_to_store_request", err);
|
|
257
|
-
return {
|
|
292
|
+
return {
|
|
293
|
+
success: false,
|
|
294
|
+
error: "oauth_request_store_failed",
|
|
295
|
+
statusCode: 500
|
|
296
|
+
};
|
|
258
297
|
}
|
|
259
298
|
try {
|
|
260
299
|
ctx.res.cookie(OAUTH_STATE_COOKIE_NAME, `${providerId}:${state}`, {
|
|
@@ -266,7 +305,11 @@ const getOAuthStartRedirectUrl = async ({
|
|
|
266
305
|
});
|
|
267
306
|
} catch (err) {
|
|
268
307
|
console.warn("oauth::failed_to_set_state_cookie", err);
|
|
269
|
-
return {
|
|
308
|
+
return {
|
|
309
|
+
success: false,
|
|
310
|
+
error: "oauth_cookie_set_failed",
|
|
311
|
+
statusCode: 500
|
|
312
|
+
};
|
|
270
313
|
}
|
|
271
314
|
const oidc = await getOidcWellKnown(provider.issuer);
|
|
272
315
|
const redirectUri = `${origin}${callbackPath}`;
|
|
@@ -283,7 +326,10 @@ const getOAuthStartRedirectUrl = async ({
|
|
|
283
326
|
if (url.searchParams.has(key)) continue;
|
|
284
327
|
url.searchParams.set(key, value);
|
|
285
328
|
}
|
|
286
|
-
return {
|
|
329
|
+
return {
|
|
330
|
+
success: true,
|
|
331
|
+
redirectUrl: url.toString()
|
|
332
|
+
};
|
|
287
333
|
};
|
|
288
334
|
const OAUTH_SUCCESS_REDIRECT_PATH = "/onboarding";
|
|
289
335
|
const AUTH_ERROR_REDIRECT_BASE = "/auth/sign-in";
|
|
@@ -296,51 +342,104 @@ const processOAuthCallback = async ({
|
|
|
296
342
|
}) => {
|
|
297
343
|
const providerId = resolveProviderId(ctx, providerIdOverride);
|
|
298
344
|
if (!providerId) {
|
|
299
|
-
return {
|
|
345
|
+
return {
|
|
346
|
+
success: false,
|
|
347
|
+
type: "error",
|
|
348
|
+
error: "missing_provider",
|
|
349
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=missing_provider`
|
|
350
|
+
};
|
|
300
351
|
}
|
|
301
352
|
if (!isSafeOAuthProviderId(providerId)) {
|
|
302
|
-
return {
|
|
353
|
+
return {
|
|
354
|
+
success: false,
|
|
355
|
+
type: "error",
|
|
356
|
+
error: "invalid_provider",
|
|
357
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=invalid_provider`
|
|
358
|
+
};
|
|
303
359
|
}
|
|
304
360
|
const provider = getOAuthProviderConfig(providerId);
|
|
305
361
|
if (!provider) {
|
|
306
|
-
return {
|
|
362
|
+
return {
|
|
363
|
+
success: false,
|
|
364
|
+
type: "error",
|
|
365
|
+
error: "unknown_provider",
|
|
366
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=unknown_provider`
|
|
367
|
+
};
|
|
307
368
|
}
|
|
308
369
|
const origin = getRequestOrigin(ctx);
|
|
309
370
|
if (!origin) {
|
|
310
|
-
return {
|
|
371
|
+
return {
|
|
372
|
+
success: false,
|
|
373
|
+
type: "error",
|
|
374
|
+
error: "origin_unavailable",
|
|
375
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=origin_unavailable`
|
|
376
|
+
};
|
|
311
377
|
}
|
|
312
378
|
const isHttps = origin.startsWith("https://");
|
|
313
379
|
const callbackPath = resolveCallbackPath(provider.callbackPath);
|
|
314
380
|
if (!callbackPath) {
|
|
315
|
-
return {
|
|
381
|
+
return {
|
|
382
|
+
success: false,
|
|
383
|
+
type: "error",
|
|
384
|
+
error: "invalid_callback_path",
|
|
385
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=invalid_callback_path`
|
|
386
|
+
};
|
|
316
387
|
}
|
|
317
388
|
const bodyParams = await getFormPostParams(ctx);
|
|
318
389
|
const code = (getQueryString(bodyParams?.code) ?? getQueryString(ctx.req.query?.code))?.trim() ?? "";
|
|
319
390
|
const state = (getQueryString(bodyParams?.state) ?? getQueryString(ctx.req.query?.state))?.trim() ?? "";
|
|
320
391
|
const oauthUserRaw = (getQueryString(bodyParams?.user) ?? getQueryString(ctx.req.query?.user))?.trim() ?? "";
|
|
321
392
|
if (!code || !state) {
|
|
322
|
-
return {
|
|
393
|
+
return {
|
|
394
|
+
success: false,
|
|
395
|
+
type: "error",
|
|
396
|
+
error: "missing_code_or_state",
|
|
397
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=missing_code_or_state`
|
|
398
|
+
};
|
|
323
399
|
}
|
|
324
400
|
const stateCookieValue = getCookieValue(ctx, OAUTH_STATE_COOKIE_NAME);
|
|
325
401
|
if (stateCookieValue !== `${providerId}:${state}`) {
|
|
326
|
-
return {
|
|
402
|
+
return {
|
|
403
|
+
success: false,
|
|
404
|
+
type: "error",
|
|
405
|
+
error: "invalid_state",
|
|
406
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=invalid_state`
|
|
407
|
+
};
|
|
327
408
|
}
|
|
328
409
|
let oauthRequest = null;
|
|
329
410
|
let OAuthRequestModel = null;
|
|
330
411
|
try {
|
|
331
412
|
OAuthRequestModel = await models.getGlobal("RBOAuthRequest", ctx);
|
|
332
|
-
oauthRequest = await OAuthRequestModel.findOne({
|
|
413
|
+
oauthRequest = await OAuthRequestModel.findOne({
|
|
414
|
+
_id: state,
|
|
415
|
+
providerId
|
|
416
|
+
}).lean();
|
|
333
417
|
} catch (err) {
|
|
334
418
|
console.warn("oauth::failed_to_load_request", err);
|
|
335
|
-
return {
|
|
419
|
+
return {
|
|
420
|
+
success: false,
|
|
421
|
+
type: "error",
|
|
422
|
+
error: "oauth_request_load_failed",
|
|
423
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=oauth_request_load_failed`
|
|
424
|
+
};
|
|
336
425
|
}
|
|
337
426
|
if (!oauthRequest) {
|
|
338
|
-
return {
|
|
427
|
+
return {
|
|
428
|
+
success: false,
|
|
429
|
+
type: "error",
|
|
430
|
+
error: "invalid_state",
|
|
431
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=invalid_state`
|
|
432
|
+
};
|
|
339
433
|
}
|
|
340
434
|
const returnTo = typeof oauthRequest.returnTo === "string" ? oauthRequest.returnTo : void 0;
|
|
341
435
|
const codeVerifier = typeof oauthRequest.codeVerifier === "string" ? oauthRequest.codeVerifier : "";
|
|
342
436
|
if (!codeVerifier) {
|
|
343
|
-
return {
|
|
437
|
+
return {
|
|
438
|
+
success: false,
|
|
439
|
+
type: "error",
|
|
440
|
+
error: "missing_code_verifier",
|
|
441
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=missing_code_verifier`
|
|
442
|
+
};
|
|
344
443
|
}
|
|
345
444
|
const oidc = await getOidcWellKnown(provider.issuer);
|
|
346
445
|
const redirectUri = `${origin}${callbackPath}`;
|
|
@@ -365,7 +464,12 @@ const processOAuthCallback = async ({
|
|
|
365
464
|
if (!tokenResponse.ok || !tokenJson || typeof tokenJson !== "object") {
|
|
366
465
|
const body = tokenJson ? JSON.stringify(tokenJson) : "";
|
|
367
466
|
console.warn("oauth::token_exchange failed", tokenResponse.status, body);
|
|
368
|
-
return {
|
|
467
|
+
return {
|
|
468
|
+
success: false,
|
|
469
|
+
type: "error",
|
|
470
|
+
error: "token_exchange_failed",
|
|
471
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=token_exchange_failed`
|
|
472
|
+
};
|
|
369
473
|
}
|
|
370
474
|
const accessToken = typeof tokenJson.access_token === "string" ? tokenJson.access_token : "";
|
|
371
475
|
const refreshToken = typeof tokenJson.refresh_token === "string" ? tokenJson.refresh_token : void 0;
|
|
@@ -391,7 +495,12 @@ const processOAuthCallback = async ({
|
|
|
391
495
|
const accessTokenPayload = decodeJwtPayload(accessToken);
|
|
392
496
|
const subject = typeof userInfo?.sub === "string" ? userInfo.sub : typeof idTokenPayload?.sub === "string" ? idTokenPayload.sub : typeof accessTokenPayload?.sub === "string" ? accessTokenPayload.sub : "";
|
|
393
497
|
if (!subject) {
|
|
394
|
-
return {
|
|
498
|
+
return {
|
|
499
|
+
success: false,
|
|
500
|
+
type: "error",
|
|
501
|
+
error: "missing_subject",
|
|
502
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=missing_subject`
|
|
503
|
+
};
|
|
395
504
|
}
|
|
396
505
|
const email = typeof userInfo?.email === "string" ? userInfo.email : typeof idTokenPayload?.email === "string" ? idTokenPayload.email : void 0;
|
|
397
506
|
const name = typeof userInfo?.name === "string" ? userInfo.name : typeof idTokenPayload?.name === "string" ? idTokenPayload.name : void 0;
|
|
@@ -411,14 +520,15 @@ const processOAuthCallback = async ({
|
|
|
411
520
|
const oauthUserName = [oauthUserNameFirst, oauthUserNameLast].filter(Boolean).join(" ").trim();
|
|
412
521
|
const resolvedEmail = email ?? (oauthUserEmail || void 0);
|
|
413
522
|
const resolvedName = name ?? (oauthUserName || void 0);
|
|
414
|
-
const [User, Tenant] = await Promise.all([
|
|
415
|
-
models.getGlobal("RBUser", ctx),
|
|
416
|
-
models.getGlobal("RBTenant", ctx)
|
|
417
|
-
]);
|
|
523
|
+
const [User, Tenant] = await Promise.all([models.getGlobal("RBUser", ctx), models.getGlobal("RBTenant", ctx)]);
|
|
418
524
|
const subjectQueryKey = `oauthProviders.${providerId}.subject`;
|
|
419
|
-
let user = await User.findOne({
|
|
525
|
+
let user = await User.findOne({
|
|
526
|
+
[subjectQueryKey]: subject
|
|
527
|
+
});
|
|
420
528
|
if (!user && resolvedEmail) {
|
|
421
|
-
user = await User.findOne({
|
|
529
|
+
user = await User.findOne({
|
|
530
|
+
email: resolvedEmail
|
|
531
|
+
});
|
|
422
532
|
}
|
|
423
533
|
const shouldCreateUser = createUserOnFirstSignIn ?? true;
|
|
424
534
|
if (!user && !shouldCreateUser) {
|
|
@@ -441,7 +551,12 @@ const processOAuthCallback = async ({
|
|
|
441
551
|
return result;
|
|
442
552
|
}
|
|
443
553
|
if (!ctx.req.session) {
|
|
444
|
-
return {
|
|
554
|
+
return {
|
|
555
|
+
success: false,
|
|
556
|
+
type: "error",
|
|
557
|
+
error: "session_unavailable",
|
|
558
|
+
redirectPath: `${AUTH_ERROR_REDIRECT_BASE}?error=session_unavailable`
|
|
559
|
+
};
|
|
445
560
|
}
|
|
446
561
|
const now = /* @__PURE__ */ new Date();
|
|
447
562
|
let providerCreatedAt;
|
|
@@ -498,7 +613,11 @@ const processOAuthCallback = async ({
|
|
|
498
613
|
if (!user.name && resolvedName) {
|
|
499
614
|
setFields.name = resolvedName;
|
|
500
615
|
}
|
|
501
|
-
await User.updateOne({
|
|
616
|
+
await User.updateOne({
|
|
617
|
+
_id: user._id
|
|
618
|
+
}, {
|
|
619
|
+
$set: setFields
|
|
620
|
+
});
|
|
502
621
|
}
|
|
503
622
|
const tenantId = user.tenants?.[0]?.toString?.() || "00000000";
|
|
504
623
|
const signedInTenants = (user.tenants || []).map(String);
|
|
@@ -513,7 +632,10 @@ const processOAuthCallback = async ({
|
|
|
513
632
|
};
|
|
514
633
|
try {
|
|
515
634
|
if (OAuthRequestModel) {
|
|
516
|
-
await OAuthRequestModel.deleteOne({
|
|
635
|
+
await OAuthRequestModel.deleteOne({
|
|
636
|
+
_id: state,
|
|
637
|
+
providerId
|
|
638
|
+
});
|
|
517
639
|
}
|
|
518
640
|
} catch (err) {
|
|
519
641
|
console.warn("oauth::failed_to_delete_request", err);
|
|
@@ -553,10 +675,15 @@ const createOAuthStartHandler = ({
|
|
|
553
675
|
});
|
|
554
676
|
if (!result.success) {
|
|
555
677
|
ctx.res.status(result.statusCode);
|
|
556
|
-
return {
|
|
678
|
+
return {
|
|
679
|
+
success: false,
|
|
680
|
+
error: result.error
|
|
681
|
+
};
|
|
557
682
|
}
|
|
558
683
|
ctx.res.redirect(result.redirectUrl);
|
|
559
|
-
return {
|
|
684
|
+
return {
|
|
685
|
+
success: true
|
|
686
|
+
};
|
|
560
687
|
};
|
|
561
688
|
const createOAuthCallbackHandler = ({
|
|
562
689
|
providerId,
|
|
@@ -573,7 +700,10 @@ const createOAuthCallbackHandler = ({
|
|
|
573
700
|
});
|
|
574
701
|
if (result.type === "error") {
|
|
575
702
|
ctx.res.redirect(result.redirectPath);
|
|
576
|
-
return {
|
|
703
|
+
return {
|
|
704
|
+
success: false,
|
|
705
|
+
error: result.error
|
|
706
|
+
};
|
|
577
707
|
}
|
|
578
708
|
if (result.type === "missing_user") {
|
|
579
709
|
if (result.redirectPath) {
|
|
@@ -581,10 +711,15 @@ const createOAuthCallbackHandler = ({
|
|
|
581
711
|
} else {
|
|
582
712
|
ctx.res.redirect("/auth/sign-up");
|
|
583
713
|
}
|
|
584
|
-
return {
|
|
714
|
+
return {
|
|
715
|
+
success: false,
|
|
716
|
+
error: "user_not_found"
|
|
717
|
+
};
|
|
585
718
|
}
|
|
586
719
|
ctx.res.redirect(result.redirectPath);
|
|
587
|
-
return {
|
|
720
|
+
return {
|
|
721
|
+
success: true
|
|
722
|
+
};
|
|
588
723
|
};
|
|
589
724
|
const base64UrlEncode = (input) => Buffer.from(input).toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
590
725
|
const createAppleClientSecret = ({
|
|
@@ -606,7 +741,11 @@ const createAppleClientSecret = ({
|
|
|
606
741
|
const nowSeconds = Math.floor(now.getTime() / 1e3);
|
|
607
742
|
const expiresIn = Number.isFinite(expiresInSeconds) ? expiresInSeconds : 10 * 60;
|
|
608
743
|
const exp = nowSeconds + Math.max(60, Math.min(expiresIn, 60 * 60 * 24 * 180));
|
|
609
|
-
const header = {
|
|
744
|
+
const header = {
|
|
745
|
+
alg: "ES256",
|
|
746
|
+
kid: keyIdValue,
|
|
747
|
+
typ: "JWT"
|
|
748
|
+
};
|
|
610
749
|
const payload = {
|
|
611
750
|
iss: teamIdValue,
|
|
612
751
|
iat: nowSeconds,
|