UNPKG

aegis-auth

Version:

A credentials-based auth solution for Next.js (and other Node projects) with IP rate-limiting, account lockouts, and sessions in DB.

107 lines 4.82 kB
import { Ratelimit } from "@upstash/ratelimit"; import { Redis } from "@upstash/redis"; import _ from "lodash"; import { ZodError } from "zod"; import { completeEmailChange as completeEmailChangeCore, completePasswordReset as completePasswordResetCore, createSession as createSessionCore, createVerification as createVerificationCore, initiateEmailChange as initiateEmailChangeCore, initiatePasswordReset as initiatePasswordResetCore, loginUser as loginUserCore, logoutUser as logoutUserCore, registerUser as registerUserCore, revokeAllSessionsForUser as revokeAllSessionsForUserCore, revokeSession as revokeSessionCore, useVerificationToken as useVerificationTokenCore, validateAndRotateSession as validateAndRotateSessionCore, verifyEmail as verifyEmailCore, } from "./actions"; import { configSchema, defaultConfig } from "./config"; import { ConfigurationError } from "./errors/config"; import { parseRequest } from "./utils"; export class AegisAuth { createContext() { return { prisma: this.prisma, config: this.config, limiters: this.limiters, }; } createContextWithRequest(request) { return Object.assign(Object.assign({}, this.createContext()), { parsedRequest: parseRequest(request, this.config) }); } constructor(prisma, userConfig) { var _a; this.limiters = {}; this.prisma = prisma; const mergedConfig = _.defaultsDeep(userConfig, defaultConfig); try { configSchema.parse(mergedConfig); } catch (error) { if (error instanceof ZodError) { throw new ConfigurationError(error.errors .map((e) => `${e.path.join(".")}: ${e.message}`) .join("; ")); } throw new ConfigurationError((_a = error.message) !== null && _a !== void 0 ? _a : "Unknown configuration error"); } this.config = mergedConfig; // Initialize rate limiters ONCE if (this.config.rateLimiting.enabled) { const redis = new Redis({ url: this.config.rateLimiting.kvRestApiUrl, token: this.config.rateLimiting.kvRestApiToken, }); const routes = [ "login", "register", "verifyEmail", "initiatePasswordReset", "completePasswordReset", "initiateEmailChange", "completeEmailChange", ]; for (const route of routes) { const routeConfig = this.config.rateLimiting[route]; if (routeConfig.enabled) { this.limiters[route] = new Ratelimit({ redis, limiter: Ratelimit.slidingWindow(routeConfig.maxRequests, `${routeConfig.windowSeconds} s`), prefix: `aegis-route:${route}:`, }); } } } } async completeEmailChange(request, input) { return completeEmailChangeCore(this.createContextWithRequest(request), input); } async completePasswordReset(request, input) { return completePasswordResetCore(this.createContextWithRequest(request), input); } async createSession(request, input) { return createSessionCore(this.createContextWithRequest(request), input); } async createVerification(input) { return createVerificationCore(this.createContext(), input); } async initiateEmailChange(request, input) { return initiateEmailChangeCore(this.createContextWithRequest(request), input); } async initiatePasswordReset(request, input) { return initiatePasswordResetCore(this.createContextWithRequest(request), input); } async loginUser(request, input) { return loginUserCore(this.createContextWithRequest(request), input); } async logoutUser(input) { return logoutUserCore(this.createContext(), input); } async registerUser(request, input) { return registerUserCore(this.createContextWithRequest(request), input); } async revokeAllSessionsForUser(input) { return revokeAllSessionsForUserCore(this.createContext(), input); } async revokeSession(input) { return revokeSessionCore(this.createContext(), input); } async useVerificationToken(input) { return useVerificationTokenCore(this.createContext(), input); } async validateAndRotateSession(request, input) { return validateAndRotateSessionCore(this.createContextWithRequest(request), input); } async verifyEmail(request, input) { return verifyEmailCore(this.createContextWithRequest(request), input); } } //# sourceMappingURL=aegisAuth.js.map