{
  "version": 3,
  "sources": ["../src/auth.ts"],
  "sourcesContent": ["import fs from 'fs/promises';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport express, { Router } from 'express';\nimport { existsSync } from 'fs';\nimport { debugAndPrintError, generateId, logger, matchMaker } from '@colyseus/core';\nimport { type Request } from 'express-jwt';\nimport { type OAuthProviderCallback, oAuthProviderCallback, oauth } from './oauth.ts';\nimport { JWT, type JwtPayload } from './JWT.ts';\nimport { Hash } from './Hash.ts';\n\nexport type MayHaveUpgradeToken = { upgradingToken?: JwtPayload };\n\nexport type RegisterWithEmailAndPasswordCallback<T = any> = (email: string, password: string, options: T & MayHaveUpgradeToken) => Promise<unknown>;\nexport type RegisterAnonymouslyCallback<T = any> = (options: T) => Promise<unknown>;\nexport type FindUserByEmailCallback = (email: string) => Promise<(unknown & { password: string }) | null | undefined>;\n\nexport type SendEmailConfirmationCallback = (email: string, html: string, confirmLink: string) => Promise<unknown>;\nexport type EmailConfirmedCallback = (email: string) => Promise<unknown>;\n\nexport type ForgotPasswordCallback = (email: string, html: string, resetLink: string) => Promise<boolean | unknown>;\nexport type ResetPasswordCallback = (email: string, password: string) => Promise<unknown>;\n\nexport type ParseTokenCallback = (token: JwtPayload) => Promise<unknown> | unknown;\nexport type GenerateTokenCallback = (userdata: unknown) => Promise<unknown>;\nexport type HashPasswordCallback = (password: string) => Promise<string>;\n\nexport interface AuthSettings {\n  onFindUserByEmail: FindUserByEmailCallback,\n  onRegisterWithEmailAndPassword: RegisterWithEmailAndPasswordCallback,\n  onRegisterAnonymously: RegisterAnonymouslyCallback,\n\n  onSendEmailConfirmation?: SendEmailConfirmationCallback,\n  onEmailConfirmed?: EmailConfirmedCallback,\n\n  onForgotPassword?: ForgotPasswordCallback,\n  onResetPassword?: ResetPasswordCallback,\n\n  onOAuthProviderCallback?: OAuthProviderCallback,\n  onParseToken?: ParseTokenCallback,\n  onGenerateToken?: GenerateTokenCallback,\n  onHashPassword?: HashPasswordCallback,\n};\n\nlet onFindUserByEmail: FindUserByEmailCallback = (email: string) => { throw new Error('`auth.settings.onFindUserByEmail` not implemented.'); };\nlet onRegisterWithEmailAndPassword: RegisterWithEmailAndPasswordCallback = () => { throw new Error('`auth.settings.onRegisterWithEmailAndPassword` not implemented.'); };\nlet onForgotPassword: ForgotPasswordCallback = () => { throw new Error('`auth.settings.onForgotPassword` not implemented.'); };\nlet onParseToken: ParseTokenCallback = (jwt: JwtPayload) => jwt;\nlet onGenerateToken: GenerateTokenCallback = async (userdata: unknown) => await JWT.sign(userdata);\nlet onHashPassword: HashPasswordCallback = async (password: string) => Hash.make(password);\n\n/**\n * Detect HTML template path (for password reset form)\n */\n// __dirname is not available in ESM\nconst getDirname = () => (typeof __dirname !== 'undefined') ? __dirname : path.dirname(fileURLToPath(import.meta.url));\n\nconst htmlTemplatePath = [\n  path.join(process.cwd(), \"html\"),\n  path.join(getDirname(), \"..\", \"html\"),\n].find((filePath) => existsSync(filePath));\n\nconst RESET_PASSWORD_TOKEN_EXPIRATION_MINUTES = 30;\n\nexport const auth = {\n  /**\n   * Backend URL (used for OAuth callbacks and email confirmation links)\n   */\n  backend_url: \"\",\n\n  /**\n   * OAuth utilities\n   */\n  oauth: oauth,\n\n  settings: {\n    /**\n     * Find user by email.\n     */\n    onFindUserByEmail,\n\n    /**\n     * Register user by email and password.\n     */\n    onRegisterWithEmailAndPassword,\n\n    /**\n     * (Optional) Register anonymous user.\n     */\n    onRegisterAnonymously: undefined as RegisterAnonymouslyCallback,\n\n    /**\n     * (Optional) Send email address verification confirmation email.\n     */\n    onSendEmailConfirmation: undefined as SendEmailConfirmationCallback,\n\n    /**\n     * (Optional) Send email address verification confirmation email.\n     */\n    onEmailConfirmed: undefined as EmailConfirmedCallback,\n\n    /**\n     * (Optional) Send reset password link via email.\n     */\n    onForgotPassword,\n\n    /**\n     * (Optional) Reset password action.\n     */\n    onResetPassword: undefined as ResetPasswordCallback,\n\n    /**\n     * By default, it returns the contents of the JWT token. (onGenerateToken)\n     */\n    onParseToken,\n\n    /**\n     * By default, it encodes the full `userdata` object into the JWT token.\n     */\n    onGenerateToken,\n\n    /**\n     * Hash password before storing it. By default, it uses SHA1 + process.env.AUTH_SALT.\n     */\n    onHashPassword,\n  } as AuthSettings,\n\n  prefix: \"/auth\",\n\n  /**\n   * Middleware that verifies JsonWebTokens.\n   * Works with both Express and better-call.\n   *\n   * Express: sets `req.auth`\n   * better-call: decoded JWT payload is available in `ctx.context.auth`\n   */\n  middleware: JWT.middleware,\n\n  routes: function (settings: Partial<AuthSettings> = {}): Router {\n    if (process.env.NODE_ENV !== 'production') {\n      // do not warn in production\n      console.warn(`\n  @colyseus/auth API's are in beta and may change in the future.\n  Please give feedback and report any issues you may find at https://github.com/colyseus/colyseus/issues/660\n      `);\n    }\n\n    const router = express.Router();\n\n    //\n    // Auto-detect backend URL from the first request, if not defined.\n    // (We do only once to reduce chances of 'Host' header injection vulnerability)\n    //\n    const originDetector: any = function (req, _, next) {\n      if (!auth.backend_url) {\n        auth.backend_url = req.protocol + '://' + req.get('host');\n      }\n      if (!oauth.defaults.origin) {\n        oauth.defaults.origin = auth.backend_url;\n      }\n      // remove this middleware from the stack\n      const stackIndex = router.stack.indexOf(originDetector);\n      if (stackIndex !== -1) { router.stack.splice(stackIndex, 1); }\n      next();\n    };\n    router.use(originDetector);\n\n    // set register/login callbacks\n    Object.keys(settings).forEach(key => {\n      auth.settings[key] = settings[key];\n    });\n\n    if (!auth.settings.onParseToken) {\n      auth.settings.onParseToken = onParseToken;\n    }\n    if (!auth.settings.onGenerateToken) {\n      auth.settings.onGenerateToken = onGenerateToken;\n    }\n    if (!auth.settings.onHashPassword) {\n      auth.settings.onHashPassword = onHashPassword;\n    }\n\n    /**\n     * OAuth (optional)\n     */\n    if (settings.onOAuthProviderCallback) {\n      oauth.onCallback(settings.onOAuthProviderCallback);\n    }\n\n    if (oAuthProviderCallback) {\n      const prefix = oauth.prefix;\n\n      // make sure oauth.prefix contains the full prefix\n      oauth.prefix = auth.prefix + prefix;\n\n      router.use(prefix, oauth.routes());\n    }\n\n    /**\n     * Get user data from JWT token.\n     */\n    router.get(\"/userdata\", auth.middleware(), async (req: Request, res) => {\n      try {\n        res.json({ user: await auth.settings.onParseToken(req.auth), });\n      } catch (e: any) {\n        res.status(401).json({ error: e.message });\n      }\n    });\n\n    /**\n     * Login user by email and password.\n     */\n    router.post(\"/login\", express.json(), async (req, res) => {\n      try {\n        const email = req.body.email;\n        if (!isValidEmail(email)) { throw new Error(\"email_malformed\"); }\n\n        const user = Object.assign({}, await auth.settings.onFindUserByEmail(email));\n        if (user && user.password === await Hash.make(req.body.password)) {\n          delete user.password; // remove password from JWT payload\n          res.json({ user, token: await auth.settings.onGenerateToken(user) });\n\n        } else {\n          throw new Error(\"invalid_credentials\");\n        }\n\n      } catch (e: any) {\n        logger.error(e);\n        res.status(401).json({ error: e.message });\n      }\n    });\n\n    /**\n     * Register user by email and password.\n     * - auth.middleware() is used here to allow upgrading anonymous users.\n     */\n    router.post(\"/register\", express.json(), async (req: Request, res) => {\n      const email = req.body.email;\n      const password = req.body.password;\n\n      if (!isValidEmail(email)) {\n        return res.status(400).json({ error: \"email_malformed\" });\n      }\n\n      let existingUser: any;\n      try {\n        existingUser = await auth.settings.onFindUserByEmail(email)\n\n      } catch (e: any) {\n        logger.error('@colyseus/auth, onFindUserByEmail exception:' + e.stack);\n      }\n\n      try {\n        // TODO: allow to set password on existing user, if valid token is equivalent to email\n        //  (existingUser.password && existingUser.password.length > 0)\n        if (existingUser) {\n          throw new Error(\"email_already_in_use\");\n        }\n\n        if (!isValidPassword(password)) {\n          return res.status(400).json({ error: \"password_too_short\" });\n        }\n\n        // Build options\n        const options: MayHaveUpgradeToken = req.body.options || {};\n\n        // Verify Authorization header, if present.\n        if (req.headers.authorization) {\n          const authHeader = req.headers.authorization;\n          const authToken = (authHeader.startsWith(\"Bearer \") && authHeader.substring(7, authHeader.length)) || undefined;\n          options.upgradingToken = await JWT.verify(authToken);\n        }\n\n        // Register\n        await auth.settings.onRegisterWithEmailAndPassword(email, await Hash.make(password), options);\n\n        const user = Object.assign({}, await auth.settings.onFindUserByEmail(email));\n        delete user.password; // remove password from JWT payload\n\n        const token = await auth.settings.onGenerateToken(user);\n\n        // Call `onSendEmailConfirmation` callback, if defined.\n        if (typeof (auth.settings.onSendEmailConfirmation) === \"function\") {\n          const confirmEmailLink = `${auth.backend_url}${auth.prefix}/confirm-email?token=${token}`;\n          const html = (await fs.readFile(path.join(htmlTemplatePath, \"address-confirmation-email.html\"), \"utf-8\"))\n            .replace(\"[LINK]\", confirmEmailLink);\n\n          await auth.settings.onSendEmailConfirmation(email, html, confirmEmailLink);\n        }\n\n        res.json({ user, token, });\n\n      } catch (e: any) {\n        logger.error(e);\n        res.status(401).json({ error: e.message });\n      }\n    });\n\n    router.get(\"/confirm-email\", async (req, res) => {\n      if (req.query.success || req.query.error) {\n        const html = await fs.readFile(path.join(htmlTemplatePath, \"address-confirmation.html\"), \"utf-8\");\n        return res.end(html);\n      }\n\n      // send \"address confirmed\" message\n      if (typeof (auth.settings.onEmailConfirmed) !== \"function\") {\n        return res.status(404).end('Not found.');\n      }\n\n      try {\n        const token = (req.query.token || \"\").toString();\n        const data = await JWT.verify<{ email: string }>(token);\n\n        await auth.settings.onEmailConfirmed(data.email);\n        res.redirect(auth.prefix + \"/confirm-email?success=\" + encodeURIComponent(\"Email confirmed successfully!\"));\n\n      } catch (e: any) {\n        res.redirect(auth.prefix + \"/confirm-email?error=\" + e.message);\n      }\n    });\n\n    /**\n     * Anonymous sign-in\n     */\n    router.post(\"/anonymous\", express.json(), async (req, res) => {\n      try {\n        const options = (req.body || {}).options;\n\n        // register anonymous user, if callback is defined.\n        const user = (auth.settings.onRegisterAnonymously)\n          ? await auth.settings.onRegisterAnonymously(options)\n          : { ...options, id: undefined, anonymousId: generateId(21), anonymous: true }\n\n        res.json({\n          user,\n          token: await auth.settings.onGenerateToken(user)\n        });\n      } catch (e: any) {\n        debugAndPrintError(e);\n        res.status(401).json({ error: e.message });\n      }\n    });\n\n    router.post(\"/forgot-password\", express.json(), async (req, res) => {\n      try {\n        //\n        // check if \"forgot password\" feature is fully implemented\n        //\n        if (typeof (auth.settings.onForgotPassword) !== \"function\") {\n          throw new Error(\"auth.settings.onForgotPassword must be implemented.\");\n        }\n\n        if (typeof (auth.settings.onResetPassword) !== \"function\") {\n          throw new Error(\"auth.settings.onResetPassword must be implemented.\");\n        }\n\n        const email = req.body.email;\n        const user = await auth.settings.onFindUserByEmail(email);\n        if (!user) {\n          throw new Error(\"email_not_found\");\n        }\n\n        const token = await JWT.sign({ email }, { expiresIn: `${RESET_PASSWORD_TOKEN_EXPIRATION_MINUTES}m` });\n        const passwordResetLink = `${auth.backend_url}${auth.prefix}/reset-password?token=${token}`;\n        const html = (await fs.readFile(path.join(htmlTemplatePath, \"reset-password-email.html\"), \"utf-8\"))\n          .replace(\"[LINK]\", passwordResetLink);\n\n        const result = (await auth.settings.onForgotPassword(email, html, passwordResetLink)) ?? true;\n        res.json(result);\n\n      } catch (e: any) {\n        debugAndPrintError(e);\n        res.status(401).json({ error: e.message });\n      }\n    });\n\n    // reset password form\n    router.get(\"/reset-password\", async (req, res) => {\n      try {\n        const token = (req.query.token || \"\").toString();\n\n        const htmlForm = (await fs.readFile(path.join(htmlTemplatePath, \"reset-password-form.html\"), \"utf-8\"))\n          .replace(\"[ACTION]\", auth.prefix + \"/reset-password\")\n          .replace(\"[TOKEN]\", token);\n\n        res\n          .set(\"content-type\", \"text/html\")\n          .send(htmlForm);\n\n      } catch (e: any) {\n        logger.debug(e);\n        res.end(`Error: ${e.message}`);\n      }\n    });\n\n    // reset password form ACTION\n    router.post(\"/reset-password\", express.urlencoded({ extended: false }), async (req, res) => {\n      const token = req.body.token;\n      const password = req.body.password;\n\n      try {\n        const data = await JWT.verify<{ email: string }>(token);\n\n        if (matchMaker.presence?.get(\"reset-password:\" + token)) {\n          throw new Error(\"token_already_used\");\n        }\n\n        if (!isValidPassword(password)) {\n          throw new Error(\"Password is too short.\");\n        }\n\n        const result = await auth.settings.onResetPassword(data.email, await Hash.make(password)) ?? true;\n\n        if (!result) {\n          throw new Error(\"Could not reset password.\");\n        }\n\n        // invalidate used token for 30m\n        matchMaker.presence?.setex(\"reset-password:\" + token, \"1\", 60 * RESET_PASSWORD_TOKEN_EXPIRATION_MINUTES);\n\n        res.redirect(auth.prefix + \"/reset-password?success=\" + encodeURIComponent(\"Password reset successfully!\"));\n\n      } catch (e: any) {\n        res.redirect(auth.prefix + \"/reset-password?token=\" + token + \"&error=\" + e.message);\n      }\n    });\n\n    return router;\n  },\n};\n\nfunction isValidEmail(email: string) {\n  return /^[^\\s@]+@[^\\s@]+\\.[a-z]{2,}$/i.test(email)\n}\n\nfunction isValidPassword(password: string) {\n  return password.length >= 6;\n}\n"],
  "mappings": "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",
  "names": ["path", "express", "fs"]
}
