{"version":3,"sources":["../../src/helpers/oidc.ts","../../src/helpers/ip/utils.ts","../../src/helpers/urls.ts","../../src/helpers/uuid.ts"],"sourcesContent":["import { generators, Issuer } from 'openid-client'\nimport { z } from 'zod'\n\nimport { isSafeUrl } from './urls'\nimport { generateUUIDv4 } from './uuid'\n\nimport type { IncomingMessage, ServerResponse } from 'http'\nimport type { Client, UserinfoResponse } from 'openid-client'\n\ntype Session = Record<string, unknown> & {\n    save: () => Promise<void>\n    destroy: () => Promise<void>\n}\n\ntype SessionGetter = (req: IncomingMessage, res: ServerResponse) => Promise<Session>\ntype OIDCClientConfig = {\n    serverUrl: string\n    clientId: string\n    clientSecret: string\n    scope?: string\n    clientOptions?: Record<string, unknown>\n    issuerOptions?: Record<string, unknown>\n}\n\ntype LoggerType = {\n    info: (data: unknown) => void\n    error: (data: unknown) => void\n}\n\ntype OIDCCallbackData<UserInfo extends Record<string, unknown> = Record<string, never>> = {\n    accessToken?: string\n    refreshToken?: string\n    idToken?: string\n    userInfo?: UserinfoResponse<UserInfo>\n}\n\ntype ErrorHandler = (err: unknown, req: IncomingMessage, res: ServerResponse, next: NextFunction) => void\n\ninterface AbstractApp {\n    get(endpoint: string, ...handlers: Array<RequestHandler | ErrorHandler>): void\n}\n\ntype MiddlewareOptions = {\n    app: AbstractApp\n    apiPrefix?: string\n}\n\ntype OnAuthSuccessHandler<UserInfo extends Record<string, unknown> = Record<string, never>> = (\n    req: IncomingMessage,\n    res: ServerResponse,\n    data: OIDCCallbackData<UserInfo>\n) => void | Promise<void>\n\ntype OIDCMiddlewareOptions<UserInfo extends Record<string, unknown> = Record<string, never>> = {\n    getSession: SessionGetter\n    oidcConfig: OIDCClientConfig\n    redirectUri: string | Array<string>\n    onAuthSuccess?: OnAuthSuccessHandler<UserInfo>\n    middlewareOptions?: MiddlewareOptions\n    onError?: ErrorHandler\n    logger?: LoggerType\n}\n\ntype NextFunction = (err?: unknown) => void\n\ntype RequestHandler = (req: IncomingMessage, res: ServerResponse, next?: NextFunction) => void | Promise<void>\n\nexport class OIDCMiddleware<UserInfo extends Record<string, unknown> = Record<string, never>> {\n    private static OIDC_ID_TOKEN_KEY = 'oidcIdToken' as const\n    private static OIDC_ACCESS_TOKEN_KEY = 'oidcAccessToken' as const\n    private static OIDC_REFRESH_TOKEN_KEY = 'oidcRefreshToken' as const\n    private static OIDC_NEXT_URL_KEY = 'oidcNextUrl' as const\n    private static OIDC_CHECKS_KEY = 'oidcChecks' as const\n    private static OIDC_REDIRECT_URI_KEY = 'oidcRedirectUri' as const\n    private static CHECK_SCHEMA = z.object({ nonce: z.string(), state: z.string() })\n\n    private readonly getSession: SessionGetter\n    private readonly client: Client\n    private readonly logger: LoggerType\n    private readonly redirectUris: Array<string>\n    private readonly onAuthSuccess?: OnAuthSuccessHandler<UserInfo>\n    private readonly onError?: ErrorHandler\n    private readonly middlewareOptions: MiddlewareOptions | undefined\n    private readonly scope?: string\n\n    static getQueryParams (req: IncomingMessage): URLSearchParams {\n        return new URL(req.url || '/', 'https://_').searchParams\n    }\n\n    constructor ({\n        getSession,\n        oidcConfig,\n        redirectUri,\n        logger,\n        onAuthSuccess,\n        onError,\n        middlewareOptions,\n    }: OIDCMiddlewareOptions<UserInfo>) {\n        this.getSession = getSession\n        const { serverUrl, clientId, clientSecret, clientOptions, issuerOptions, scope } = oidcConfig\n\n        const issuer = new Issuer({\n            authorization_endpoint: `${serverUrl}/oidc/auth`,\n            token_endpoint: `${serverUrl}/oidc/token`,\n            end_session_endpoint: `${serverUrl}/oidc/session/end`,\n            jwks_uri: `${serverUrl}/oidc/jwks`,\n            revocation_endpoint: `${serverUrl}/oidc/token/revocation`,\n            userinfo_endpoint: `${serverUrl}/oidc/me`,\n            issuer: serverUrl,\n            ...(issuerOptions || {}),\n        })\n\n        this.redirectUris = Array.isArray(redirectUri) ? redirectUri : [redirectUri]\n        this.middlewareOptions = middlewareOptions\n        this.onAuthSuccess = onAuthSuccess\n        this.onError = onError\n        this.scope = scope || 'openid'\n\n        this.client = new issuer.Client({\n            client_id: clientId,\n            client_secret: clientSecret,\n            redirect_uris: this.redirectUris,\n            response_types: ['code'],\n            token_endpoint_auth_method: 'client_secret_basic',\n            ...(clientOptions || {}),\n        })\n\n        this.logger = logger || console\n\n        this.sendError = this.sendError.bind(this)\n        this.getAuthHandler = this.getAuthHandler.bind(this)\n        this.getCallbackHandler = this.getCallbackHandler.bind(this)\n        this.prepareMiddleware = this.prepareMiddleware.bind(this)\n    }\n\n    private sendError (err: unknown, req: IncomingMessage, res: ServerResponse, next?: NextFunction): void {\n        if (next && this.onError) {\n            this.onError(err, req, res, next)\n            return\n        }\n\n        if (next) {\n            next(err)\n            return\n        }\n\n        const errId = generateUUIDv4()\n        this.logger.error({ msg: 'oidc auth error', errId, err })\n\n        res.writeHead(500, { 'Content-Type': 'text/plain' })\n        res.end(`OIDC auth error: ${errId}`)\n    }\n\n    getAuthHandler (): RequestHandler {\n        const sessionGetter = this.getSession\n        const client = this.client\n        const sendError = this.sendError\n        const scope = this.scope\n        const redirectUris = this.redirectUris\n\n        return async function authHandler (req, res, next) {\n            const session = await sessionGetter(req, res)\n\n            try {\n                const query = OIDCMiddleware.getQueryParams(req)\n                const queryRedirectUri = query.get('redirect_uri')\n                const next = query.get('next')\n\n                if (next && isSafeUrl(next)) {\n                    session[OIDCMiddleware.OIDC_NEXT_URL_KEY] = next\n                } else {\n                    delete session[OIDCMiddleware.OIDC_NEXT_URL_KEY]\n                }\n\n                const redirectUri = redirectUris.find(uri => uri === queryRedirectUri) ?? redirectUris[0]\n                const checks = { nonce: generators.nonce(), state: generators.state() }\n                session[OIDCMiddleware.OIDC_CHECKS_KEY] = { ...checks }\n                session[OIDCMiddleware.OIDC_REDIRECT_URI_KEY] = redirectUri\n                await session.save()\n\n                const authUrl = client.authorizationUrl({\n                    scope,\n                    redirect_uri: redirectUri,\n                    ...checks,\n                })\n\n                res.writeHead(302, { Location: authUrl })\n                res.end()\n            } catch (err) {\n                delete session[OIDCMiddleware.OIDC_CHECKS_KEY]\n                delete session[OIDCMiddleware.OIDC_NEXT_URL_KEY]\n                await session.save()\n\n                return sendError(err, req, res, next)\n            }\n        }\n    }\n\n    getCallbackHandler (): RequestHandler {\n        const sessionGetter = this.getSession\n        const sendError = this.sendError\n        const client = this.client\n        const onAuthSuccess = this.onAuthSuccess\n        const redirectUris = this.redirectUris\n\n        return async function callbackHandler (req, res, next) {\n            let session = await sessionGetter(req, res)\n\n            try {\n                const { success, data: checks } = OIDCMiddleware.CHECK_SCHEMA.safeParse(session[OIDCMiddleware.OIDC_CHECKS_KEY])\n                const nextUrl = session[OIDCMiddleware.OIDC_NEXT_URL_KEY]\n                const redirectUri = session[OIDCMiddleware.OIDC_REDIRECT_URI_KEY]\n\n                if (typeof redirectUri !== 'string' || !redirectUris.includes(redirectUri)) {\n                    return sendError(new Error('Invalid redirect URI'), req, res, next)\n                }\n\n                if (!success) {\n                    return sendError(new Error('Invalid nonce or state'), req, res, next)\n                }\n\n                const params = client.callbackParams(req)\n                const { access_token: accessToken, refresh_token: refreshToken, id_token: idToken } = await client.callback(redirectUri, params, checks)\n\n                let userInfo: UserinfoResponse<UserInfo> | undefined\n                if (accessToken) {\n                    userInfo = await client.userinfo<UserInfo>(accessToken)\n                }\n\n                // Step 1. Remove temporary session data and save session\n                delete session[OIDCMiddleware.OIDC_CHECKS_KEY]\n                delete session[OIDCMiddleware.OIDC_NEXT_URL_KEY]\n                await session.save()\n\n                // Step 2. Call onAuthSuccess to sync user, start new session and so on\n                if (onAuthSuccess) {\n                    await onAuthSuccess(req, res, { accessToken, refreshToken, idToken, userInfo })\n                    // NOTE: session might be regenerated in onAuthSuccess\n                    session = await sessionGetter(req, res)\n                }\n\n                // Step 3. Save tokens for later use\n                session[OIDCMiddleware.OIDC_ID_TOKEN_KEY] = idToken\n                session[OIDCMiddleware.OIDC_ACCESS_TOKEN_KEY] = accessToken\n                session[OIDCMiddleware.OIDC_REFRESH_TOKEN_KEY] = refreshToken\n\n                await session.save()\n\n                const location = typeof nextUrl === 'string' && isSafeUrl(nextUrl) ? nextUrl : '/'\n                res.writeHead(302, { Location: location })\n                res.end()\n            } catch (err) {\n                delete session[OIDCMiddleware.OIDC_CHECKS_KEY]\n                delete session[OIDCMiddleware.OIDC_NEXT_URL_KEY]\n                await session.save()\n\n                return sendError(err, req, res, next)\n            }\n        }\n    }\n\n    prepareMiddleware (): AbstractApp | null {\n        if (!this.middlewareOptions) {\n            return null\n        }\n\n        const { app, apiPrefix = '/api/oidc' } = this.middlewareOptions\n\n        app.get(`${apiPrefix}/auth`, this.getAuthHandler())\n        app.get(`${apiPrefix}/callback`, this.getCallbackHandler())\n\n        return app\n    }\n}","// RegExp for testing if a string represents an IPv4 address\nconst v4Seg = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'\nconst v4Str = `(${v4Seg}[.]){3}${v4Seg}`\nconst IPv4Reg = new RegExp(`^${v4Str}$`)\n\n// RegExp for testing if a string represents an IPv6 address\nconst v6Seg = '(?:[0-9a-fA-F]{1,4})'\nconst IPv6Reg = new RegExp(\n    '^(' +\n    `(?:${v6Seg}:){7}(?:${v6Seg}|:)|` +\n    `(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` +\n    `(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` +\n    `(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` +\n    `(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` +\n    `(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` +\n    `(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` +\n    `(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` +\n    ')(%[0-9a-zA-Z]{1,})?$'\n)\n\n/**\n * Returns true if the string represents an IPv4 address. Matches Node.js net.isIPv4\n * functionality.\n */\nexport function isIPv4 (s: string) {\n    return IPv4Reg.test(s)\n}\n\n/**\n * Returns true if the string represents an IPv6 address. Matches Node.js net.isIPv6\n * functionality.\n */\nexport function isIPv6 (s: string) {\n    return IPv6Reg.test(s)\n}\n\nexport function isIP (s: string) {\n    if (isIPv4(s)) return 4\n    if (isIPv6(s)) return 6\n    return 0\n}\n","const REGEXP_ESCAPE_CHARS = /[\\\\^$.*+?()[\\]{}|]/g\nconst WILDCARD_REGEXP_PART = '([a-zA-Z0-9-]{1,63})'\nconst WILDCARD_REGEXP_PART_ESCAPED = _escapeRegexp(WILDCARD_REGEXP_PART)\n\ntype URLCache = Map<string, URL>\ntype RegExpCache = Map<string, RegExp>\n\nimport { isIP, isLocalhost, isSpecial } from './ip'\n\nexport function isSafeUrl (url: unknown): boolean {\n    if (!url || typeof url !== 'string') return false\n    \n    let decodedUrl: string\n    try {\n        decodedUrl = decodeURI(url)\n    } catch (error) {\n        // If decodeURI fails, treat as unsafe\n        return false\n    }\n\n    // ReDoS-safe approach: normalize the string first, then use simple regex\n    // Remove all control characters and whitespace, then check for javascript:\n    const normalizedUrl = decodedUrl\n        // eslint-disable-next-line no-control-regex\n        .replace(/[\\u0000-\\u001F\\s]/g, '') // Remove control chars and whitespace\n        .toLowerCase()\n    \n    return !normalizedUrl.includes('javascript:')\n}\n\nexport function replaceDomainPrefix (originalUrl: string, prefix: string): string {\n    const url = new URL(originalUrl)\n\n    const originalHostnameParts = url.hostname.split('.')\n    const suffixParts = originalHostnameParts.length > 2 ? originalHostnameParts.slice(1) : originalHostnameParts\n    const suffix = suffixParts.join('.')\n\n    url.hostname = `${prefix}.${suffix}`\n\n    return url.toString()\n}\n\nfunction _escapeRegexp (source: string) {\n    return source.replace(REGEXP_ESCAPE_CHARS, '\\\\$&')\n}\n\nexport type ReplaceDomainOptions = { encoded?: boolean, urlsCache?: URLCache, regexpsCache?: RegExpCache }\n\nfunction _getUrl (strUrl: string, cache?: URLCache): URL {\n    if (!cache) return new URL(strUrl)\n\n    let parsed = cache.get(strUrl)\n    if (!parsed) {\n        parsed = new URL(strUrl)\n        cache.set(strUrl, parsed)\n    }\n    return parsed\n}\n\n/** NOTE: Don't use it outside of this file, since it mutates lastIndex */\nfunction _getCachedRegexp (pattern: string, cache?: RegExpCache): RegExp {\n    // NOTE: no user input here\n    // nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp\n    if (!cache) return new RegExp(pattern, 'g')\n\n    let re = cache.get(pattern)\n    if (!re) {\n        // NOTE: no user input here\n        // nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp\n        re = new RegExp(pattern, 'g')\n        cache.set(pattern, re)\n    }\n    re.lastIndex = 0\n    return re\n}\n\nexport function getWildcardDomain (domain: string, cache?: URLCache) {\n    const url = _getUrl(domain, cache)\n    const [prefix, ...rest] = url.hostname.split('.')\n    const port = url.port ? `:${url.port}` : ''\n    return {\n        wildcardDomain: `${url.protocol}//*.${rest.join('.')}${port}`,\n        prefix,\n    }\n}\n\nexport function replaceDomain (source: string, from: string, to: string, options: ReplaceDomainOptions = {}): string {\n    const { encoded = false, urlsCache, regexpsCache } = options\n\n    const fromUrl = _getUrl(from, urlsCache)\n    // NOTE: URL parser encodes * as %2A in some browsers (Chromium), so decode the hostname to check for wildcards\n    const decodedHostname = decodeURIComponent(fromUrl.hostname)\n\n    // NOTE: for non-wildcard domain just do simple replace\n    if (!decodedHostname.startsWith('*.')) {\n        // Add negative lookahead to ensure domain boundary\n        // Not followed by: dot+domain chars, or domain chars directly\n        const escapedFrom = _escapeRegexp(from)\n        const fromWithBoundary = `${escapedFrom}(?!\\\\.${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})`\n        const fromSearch = _getCachedRegexp(fromWithBoundary, regexpsCache)\n        let replaced = source.replace(fromSearch, to)\n\n        if (encoded) {\n            const fromEncoded = encodeURIComponent(from)\n            const escapedFromEncoded = _escapeRegexp(fromEncoded)\n            // For encoded: not followed by %2E+domain chars or domain chars directly\n            const fromEncodedWithBoundary = `${escapedFromEncoded}(?!%2E${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})`\n            const fromEncodedSearch = _getCachedRegexp(fromEncodedWithBoundary, regexpsCache)\n            replaced = replaced.replace(fromEncodedSearch, encodeURIComponent(to))\n        }\n\n        return replaced\n    }\n\n    // NOTE: need to apply some magic on wildcards\n    // NOTE: only first * is needed\n    // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n    const fromPattern = from.replace('*', WILDCARD_REGEXP_PART)\n    // NOTE: only first * is needed\n    // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n    const toPattern = to.replace('*', '$1')\n\n    const escapedFrom = _escapeRegexp(fromPattern).replace(WILDCARD_REGEXP_PART_ESCAPED, WILDCARD_REGEXP_PART)\n    // Add negative lookahead to ensure domain boundary\n    const fromWithBoundary = `${escapedFrom}(?!\\\\.${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})`\n    const fromSearch = _getCachedRegexp(fromWithBoundary, regexpsCache)\n\n    let replaced = source.replace(fromSearch, toPattern)\n\n    if (encoded) {\n        // NOTE: only first * is needed\n        // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n        const fromEncoded = encodeURIComponent(from).replace('*', WILDCARD_REGEXP_PART)\n        // NOTE: only first * is needed\n        // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n        const toEncoded = encodeURIComponent(to).replace('*', '$1')\n\n        const escapedFromEncoded = _escapeRegexp(fromEncoded).replace(WILDCARD_REGEXP_PART_ESCAPED, WILDCARD_REGEXP_PART)\n        // For encoded: not followed by %2E+domain chars or domain chars directly\n        const fromEncodedWithBoundary = `${escapedFromEncoded}(?!%2E${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})` \n        const fromEncodedSearch = _getCachedRegexp(fromEncodedWithBoundary, regexpsCache)\n\n        replaced = replaced.replace(fromEncodedSearch, toEncoded)\n    }\n\n    return replaced\n}\n\ntype URLWithMeta = Readonly<URL> & {\n    isIP: boolean\n    isSpecialIP: boolean\n    isLocalhost: boolean\n}\n\nexport function getUrlMeta (url: string): URLWithMeta | null {\n    try {\n        const u: URLWithMeta = new URL(url) as URLWithMeta\n        const hostnameUnWrapped = (u.hostname.startsWith('[') && u.hostname.endsWith(']'))\n            ? u.hostname.slice(1, -1)\n            : u.hostname\n        u.isIP = isIP(hostnameUnWrapped) > 0\n        u.isSpecialIP = u.isIP && isSpecial(hostnameUnWrapped)\n        u.isLocalhost = u.hostname === 'localhost' || (u.isIP && isLocalhost(hostnameUnWrapped))\n\n        return u\n    } catch {\n        return null\n    }\n}\n","import { randomBytes } from 'crypto'\n\n/**\n * Generates v4 UUIDs in both browser and Node environments\n * @example\n * const uuid = generateUUIDv4()\n */\nexport function generateUUIDv4 (): string {\n    let randomValues: Uint8Array\n\n    if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n        // Browser or Node.js (if Node 19+ supports crypto.randomUUID)\n        return crypto.randomUUID()\n    } else if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {\n        // Browser environment\n        randomValues = new Uint8Array(16)\n        window.crypto.getRandomValues(randomValues)\n    } else {\n        // Node.js environment\n        randomValues = randomBytes(16)\n    }\n\n    // Setting the version (4) and variant (RFC4122)\n    randomValues[6] = (randomValues[6] & 0x0f) | 0x40 // version 4\n    randomValues[8] = (randomValues[8] & 0x3f) | 0x80 // variant\n\n    return [...randomValues]\n        .map((value, index) => {\n            const hex = value.toString(16).padStart(2, '0')\n            if (index === 4 || index === 6 || index === 8 || index === 10) {\n                return `-${hex}`\n            }\n            return hex\n        })\n        .join('')\n}\n"],"mappings":"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","names":["next"]}