@geekapps/auth-nextjs 0.14.0 → 0.16.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.
@@ -0,0 +1,113 @@
1
+ /**
2
+ * App Connections — chamar ações de negócio de OUTRA Application.
3
+ *
4
+ * Uma conexão liga um USUÁRIO desta app (X) a uma app alvo (Y). Ele a aprova
5
+ * uma vez no consent, escolhendo as ações liberadas e a organização dentro do
6
+ * Y sob a qual elas rodam. A chamada vai com o access token desse usuário (o
7
+ * da sessão, por padrão): é ele que diz ao proxy qual conexão usar.
8
+ *
9
+ * Nada aqui fala com a API do Y diretamente: tudo passa pelo proxy do
10
+ * auth-server, que valida a conexão e injeta a credencial. Esta app nunca vê
11
+ * essa credencial — é esse o ponto do proxy.
12
+ *
13
+ * O catálogo tipado (`GeekappsConnections`) vem do arquivo gerado por
14
+ * `npx geekapps-connections`.
15
+ */
16
+ /** Opções por chamada. Sem `userToken`, usa o access token do usuário logado na sessão. */
17
+ type ConnectionCallOptions = {
18
+ userToken?: string;
19
+ };
20
+ type AppConnectionsConfig = {
21
+ issuer?: string;
22
+ /** client_id/secret desta app (a consumidora, X). */
23
+ clientId?: string;
24
+ clientSecret?: string;
25
+ };
26
+ /**
27
+ * Preenchida por declaration merging no arquivo gerado
28
+ * (`geekapps-connections.d.ts`). Vazia aqui de propósito: o SDK não sabe
29
+ * quais apps existem — quem sabe é o auth-server, no momento da geração.
30
+ */
31
+ interface GeekappsConnections {
32
+ }
33
+ /** Erro de uma chamada de proxy — carrega o status HTTP para dar pra tratar. */
34
+ declare class AppConnectionError extends Error {
35
+ readonly status: number;
36
+ readonly code: string | undefined;
37
+ readonly body: unknown;
38
+ constructor(message: string, status: number, code: string | undefined, body: unknown);
39
+ }
40
+ /**
41
+ * A chamada crua do proxy, para quando não há catálogo gerado. `targetAppId` é
42
+ * o client_id da app alvo e `actionKey` é a AppAction.key — o mesmo valor que
43
+ * aparece como scope no consent.
44
+ */
45
+ declare function callAppConnection<T = unknown>(params: {
46
+ targetAppId: string;
47
+ actionKey: string;
48
+ payload?: unknown;
49
+ /** Access token do usuário dono da conexão. Padrão: o do usuário logado. */
50
+ userToken?: string;
51
+ config?: AppConnectionsConfig;
52
+ }): Promise<T>;
53
+ type ConnectionRegistryEntry = {
54
+ appId: string;
55
+ actions: Record<string, string>;
56
+ };
57
+ /** Chamado por arquivos gerados no formato antigo. Não é necessário no fluxo automático. */
58
+ declare function registerConnections(entries: Record<string, ConnectionRegistryEntry>): void;
59
+ /**
60
+ * Sem tipos gerados (primeira execução), qualquer `app.ação` é aceita. Assim
61
+ * que o SDK escreve `geekapps-connections.d.ts`, a interface estendida passa a
62
+ * valer e o TypeScript confere payload e retorno.
63
+ */
64
+ type AppConnectionsClient = keyof GeekappsConnections extends never ? Record<string, Record<string, (payload?: unknown, options?: ConnectionCallOptions) => Promise<unknown>>> : GeekappsConnections;
65
+ /** Cliente com config explícita — para quem não usa as env vars padrão. */
66
+ declare function createAppConnections(config?: AppConnectionsConfig): AppConnectionsClient;
67
+ /** Catálogo explícito, como o gerado por `npx geekapps-connections` (`geekappsConnectionsCatalog`). */
68
+ type ConnectionsCatalog = Record<string, {
69
+ readonly appId: string;
70
+ readonly actions: Readonly<Record<string, string>>;
71
+ }>;
72
+ /**
73
+ * Opcional: usa um catálogo fixo em vez de consultar o auth-server. Útil em
74
+ * testes ou quando a app não pode falar com o servidor em runtime.
75
+ *
76
+ * const connections = defineAppConnections<GeekappsConnections>(geekappsConnectionsCatalog);
77
+ */
78
+ declare function defineAppConnections<T>(catalog: ConnectionsCatalog, config?: AppConnectionsConfig): T;
79
+ /** Cliente padrão, lendo GEEKAPPS_AUTH_CLIENT_ID / _SECRET do ambiente. */
80
+ declare const appConnections: AppConnectionsClient;
81
+ type ConnectAppParams = {
82
+ /** client_id da app ALVO (a que expõe as ações). */
83
+ targetAppId: string;
84
+ /** AppAction.key das ações pedidas — as mesmas que aparecem no consent. */
85
+ actions: string[];
86
+ /** URL desta app que recebe o retorno do consent (rota que chama `completeAppConnection`). Precisa estar nos redirect URIs desta app. */
87
+ redirectUri: string;
88
+ /** Para onde `completeAppConnection` manda o usuário depois (padrão "/"). */
89
+ returnTo?: string;
90
+ /** Nome desta app exibido no consent. */
91
+ displayName?: string;
92
+ config?: AppConnectionsConfig;
93
+ };
94
+ /**
95
+ * Inicia a conexão desta app com `targetAppId`: guarda PKCE/state em cookies
96
+ * httpOnly e redireciona para o consent. Chame de um Server Action ou Route
97
+ * Handler — não retorna (o `redirect` do Next interrompe a execução).
98
+ */
99
+ declare function connectApp(params: ConnectAppParams): Promise<never>;
100
+ /**
101
+ * Fecha o fluxo de `connectApp`. Chame no callback com o `code` e o `state`
102
+ * da query; devolve o `returnTo` para você redirecionar. Lança
103
+ * AppConnectionError se o state não bater ou o auth-server recusar.
104
+ */
105
+ declare function completeAppConnection(params: {
106
+ code: string;
107
+ state: string;
108
+ config?: AppConnectionsConfig;
109
+ }): Promise<{
110
+ returnTo: string;
111
+ }>;
112
+
113
+ export { AppConnectionError, type AppConnectionsClient, type AppConnectionsConfig, type ConnectAppParams, type ConnectionCallOptions, type ConnectionsCatalog, type GeekappsConnections, appConnections, callAppConnection, completeAppConnection, connectApp, createAppConnections, defineAppConnections, registerConnections };
@@ -841,15 +841,16 @@ async function callAppConnection(params) {
841
841
  );
842
842
  }
843
843
  const url = `${issuer}/connections/${encodeURIComponent(params.targetAppId)}/actions/${encodeURIComponent(params.actionKey)}`;
844
- const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString("base64");
845
844
  const response = await fetch(url, {
846
845
  method: "POST",
847
- headers: {
848
- authorization: `Basic ${credentials}`,
849
- "x-user-token": userToken,
850
- "content-type": "application/json"
851
- },
852
- body: JSON.stringify(params.payload === void 0 ? {} : { payload: params.payload }),
846
+ headers: { "content-type": "application/json" },
847
+ // Credenciais da app e token do usuário vão no corpo, não em headers.
848
+ body: JSON.stringify({
849
+ client_id: clientId,
850
+ client_secret: clientSecret,
851
+ user_token: userToken,
852
+ ...params.payload === void 0 ? {} : { payload: params.payload }
853
+ }),
853
854
  cache: "no-store"
854
855
  });
855
856
  const body = await response.json().catch(() => null);
@@ -1005,6 +1006,7 @@ async function connectApp(params) {
1005
1006
  url.searchParams.set("code_challenge", createHash2("sha256").update(codeVerifier).digest("base64url"));
1006
1007
  url.searchParams.set("code_challenge_method", "S256");
1007
1008
  url.searchParams.set("target_app_id", params.targetAppId);
1009
+ url.searchParams.set("prompt", "select_account consent");
1008
1010
  if (params.displayName) url.searchParams.set("connection_display_name", params.displayName);
1009
1011
  redirect2(url.toString());
1010
1012
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/connections.ts","../src/server.ts"],"sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { buildModel, fetchRemoteCatalog, renderAugmentation, toRegistry } from \"@geekapps/auth-cli/lib\";\nimport { cookies } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport { GEEKAPPS_AUTH_SERVER_URL, configureGeekappsAuth } from \"./server\";\n\n/**\n * App Connections — chamar ações de negócio de OUTRA Application.\n *\n * Uma conexão liga um USUÁRIO desta app (X) a uma app alvo (Y). Ele a aprova\n * uma vez no consent, escolhendo as ações liberadas e a organização dentro do\n * Y sob a qual elas rodam. A chamada vai com o access token desse usuário (o\n * da sessão, por padrão): é ele que diz ao proxy qual conexão usar.\n *\n * Nada aqui fala com a API do Y diretamente: tudo passa pelo proxy do\n * auth-server, que valida a conexão e injeta a credencial. Esta app nunca vê\n * essa credencial — é esse o ponto do proxy.\n *\n * O catálogo tipado (`GeekappsConnections`) vem do arquivo gerado por\n * `npx geekapps-connections`.\n */\n\n/** Opções por chamada. Sem `userToken`, usa o access token do usuário logado na sessão. */\nexport type ConnectionCallOptions = { userToken?: string };\n\nexport type AppConnectionsConfig = {\n issuer?: string;\n /** client_id/secret desta app (a consumidora, X). */\n clientId?: string;\n clientSecret?: string;\n};\n\n/**\n * Preenchida por declaration merging no arquivo gerado\n * (`geekapps-connections.d.ts`). Vazia aqui de propósito: o SDK não sabe\n * quais apps existem — quem sabe é o auth-server, no momento da geração.\n */\nexport interface GeekappsConnections {}\n\n/** Erro de uma chamada de proxy — carrega o status HTTP para dar pra tratar. */\nexport class AppConnectionError extends Error {\n readonly status: number;\n readonly code: string | undefined;\n readonly body: unknown;\n\n constructor(message: string, status: number, code: string | undefined, body: unknown) {\n super(message);\n this.name = \"AppConnectionError\";\n this.status = status;\n this.code = code;\n this.body = body;\n }\n}\n\nfunction env(name: string) {\n const value = process.env[name];\n return value && value.trim().length > 0 ? value : undefined;\n}\n\nfunction resolveConfig(config: AppConnectionsConfig) {\n const issuer = (\n config.issuer ??\n env(\"GEEKAPPS_AUTH_SERVER_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_SERVER_URL\") ??\n GEEKAPPS_AUTH_SERVER_URL\n ).replace(/\\/$/, \"\");\n\n return {\n issuer,\n clientId: config.clientId ?? env(\"GEEKAPPS_AUTH_CLIENT_ID\") ?? \"\",\n clientSecret: config.clientSecret ?? env(\"GEEKAPPS_AUTH_CLIENT_SECRET\") ?? \"\",\n };\n}\n\n/**\n * A chamada crua do proxy, para quando não há catálogo gerado. `targetAppId` é\n * o client_id da app alvo e `actionKey` é a AppAction.key — o mesmo valor que\n * aparece como scope no consent.\n */\nexport async function callAppConnection<T = unknown>(params: {\n targetAppId: string;\n actionKey: string;\n payload?: unknown;\n /** Access token do usuário dono da conexão. Padrão: o do usuário logado. */\n userToken?: string;\n config?: AppConnectionsConfig;\n}): Promise<T> {\n const { issuer, clientId, clientSecret } = resolveConfig(params.config ?? {});\n if (!clientId || !clientSecret) {\n throw new Error(\n \"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID e GEEKAPPS_AUTH_CLIENT_SECRET — é com essas credenciais que o proxy identifica a app que está chamando.\",\n );\n }\n\n // A conexão é do usuário: sem o token dele o proxy não sabe qual usar.\n const userToken = params.userToken ?? (await configureGeekappsAuth().GetAccessToken());\n if (!userToken) {\n throw new AppConnectionError(\n \"App Connections: não há usuário logado — a conexão é do usuário, a chamada precisa do access token dele.\",\n 401,\n \"user_token_required\",\n null,\n );\n }\n\n const url = `${issuer}/connections/${encodeURIComponent(params.targetAppId)}/actions/${encodeURIComponent(params.actionKey)}`;\n const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString(\"base64\");\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n authorization: `Basic ${credentials}`,\n \"x-user-token\": userToken,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(params.payload === undefined ? {} : { payload: params.payload }),\n cache: \"no-store\",\n });\n\n const body = await response.json().catch(() => null);\n\n if (!response.ok) {\n const code =\n body && typeof body === \"object\" && typeof (body as { error?: unknown }).error === \"string\"\n ? (body as { error: string }).error\n : undefined;\n throw new AppConnectionError(\n `App Connections: ${params.actionKey} falhou (${response.status}${code ? ` ${code}` : \"\"})`,\n response.status,\n code,\n body,\n );\n }\n\n return body as T;\n}\n\ntype ConnectionRegistryEntry = { appId: string; actions: Record<string, string> };\ntype Registry = Map<string, ConnectionRegistryEntry>;\n\n/** Registry de arquivos gerados no formato antigo (`registerConnections`). Mantido por compatibilidade. */\nconst _registry: Registry = new Map();\n\n/** Chamado por arquivos gerados no formato antigo. Não é necessário no fluxo automático. */\nexport function registerConnections(entries: Record<string, ConnectionRegistryEntry>) {\n for (const [name, entry] of Object.entries(entries)) _registry.set(name, entry);\n}\n\n// ─── Catálogo automático ────────────────────────────────────────────────────\n//\n// O SDK resolve `appConnections.<app>.<ação>` consultando o catálogo do\n// auth-server (cache em memória). Em desenvolvimento, também mantém um\n// `geekapps-connections.d.ts` na raiz do projeto que estende\n// `GeekappsConnections`: é isso que dá os tipos, sem o dev rodar nada.\n\nconst TYPES_MODULE = \"@geekapps/auth-nextjs/connections\";\nconst TYPES_FILE = \"geekapps-connections.d.ts\";\nconst REFRESH_MIN_INTERVAL_MS = 5_000;\n\nconst _remote = new Map<string, { at: number; registry: Registry }>();\nconst _inflight = new Map<string, Promise<Registry>>();\n\nasync function writeTypesInDev(model: ReturnType<typeof buildModel>) {\n if (process.env.NODE_ENV !== \"development\" || process.env.GEEKAPPS_CONNECTIONS_TYPES === \"off\") return;\n try {\n const { existsSync, readFileSync, writeFileSync } = await import(\"node:fs\");\n const { resolve } = await import(\"node:path\");\n const file = resolve(process.cwd(), TYPES_FILE);\n const content = renderAugmentation(model, TYPES_MODULE);\n if (existsSync(file) && readFileSync(file, \"utf-8\") === content) return;\n writeFileSync(file, content, \"utf-8\");\n } catch {\n // Os tipos são conveniência de desenvolvimento: nunca derrubam a chamada.\n }\n}\n\nasync function loadRemoteRegistry(config: AppConnectionsConfig, force = false): Promise<Registry> {\n const { issuer, clientId, clientSecret } = resolveConfig(config);\n if (!clientId || !clientSecret) {\n throw new Error(\n \"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID e GEEKAPPS_AUTH_CLIENT_SECRET — é com essas credenciais que o SDK descobre as apps conectáveis.\",\n );\n }\n\n const cacheKey = `${issuer}|${clientId}`;\n const ttl = process.env.NODE_ENV === \"development\" ? 30_000 : 5 * 60_000;\n const cached = _remote.get(cacheKey);\n const age = cached ? Date.now() - cached.at : Infinity;\n if (cached && (force ? age < REFRESH_MIN_INTERVAL_MS : age < ttl)) return cached.registry;\n\n const pending = _inflight.get(cacheKey);\n if (pending) return pending;\n\n const request = (async () => {\n try {\n const model = buildModel(await fetchRemoteCatalog({ issuer, clientId, clientSecret }));\n const registry: Registry = new Map(Object.entries(toRegistry(model)));\n _remote.set(cacheKey, { at: Date.now(), registry });\n void writeTypesInDev(model);\n return registry;\n } catch (error) {\n // Com um catálogo antigo em cache, é melhor continuar com ele do que falhar.\n if (cached) return cached.registry;\n throw new AppConnectionError(`App Connections: ${(error as Error).message}`, 502, \"catalog_unavailable\", null);\n } finally {\n _inflight.delete(cacheKey);\n }\n })();\n _inflight.set(cacheKey, request);\n return request;\n}\n\ntype RegistryProvider = (force?: boolean) => Promise<Registry>;\n\nasync function resolveTarget(provider: RegistryProvider, appName: string, actionName: string) {\n for (const force of [false, true]) {\n const registry = await provider(force);\n const entry = registry.get(appName);\n const key = entry?.actions[actionName];\n // Não achou? Pode ser app/ação nova: refaz a busca uma vez antes de desistir.\n if (entry && key) return { appId: entry.appId, key };\n }\n\n throw new Error(\n `App Connections: \"${appName}.${actionName}\" não existe no catálogo. Confira se a app alvo cadastrou a ação (geekapps-actions sync).`,\n );\n}\n\n/**\n * Proxy de dois níveis: `appConnections.<app>.<ação>(payload)`. Usa Proxy\n * porque os nomes das apps e das ações vêm do catálogo, não do código.\n */\nfunction createCatalog(config: AppConnectionsConfig, provider: RegistryProvider): unknown {\n return new Proxy(Object.create(null) as Record<string, unknown>, {\n get(_target, appName: string | symbol) {\n if (typeof appName !== \"string\") return undefined;\n\n return new Proxy(Object.create(null) as Record<string, unknown>, {\n get(_t, actionName: string | symbol) {\n if (typeof actionName !== \"string\") return undefined;\n\n return async (payload?: unknown, options?: ConnectionCallOptions) => {\n const target = await resolveTarget(provider, appName, actionName);\n return callAppConnection({\n targetAppId: target.appId,\n actionKey: target.key,\n payload,\n userToken: options?.userToken,\n config,\n });\n };\n },\n });\n },\n });\n}\n\n/**\n * Sem tipos gerados (primeira execução), qualquer `app.ação` é aceita. Assim\n * que o SDK escreve `geekapps-connections.d.ts`, a interface estendida passa a\n * valer e o TypeScript confere payload e retorno.\n */\nexport type AppConnectionsClient = keyof GeekappsConnections extends never\n ? Record<string, Record<string, (payload?: unknown, options?: ConnectionCallOptions) => Promise<unknown>>>\n : GeekappsConnections;\n\nconst _devRefresh = new Set<string>();\n\n/**\n * Em desenvolvimento, consulta o catálogo ao subir e a cada 30s, para que\n * `geekapps-connections.d.ts` acompanhe a app alvo mesmo sem nenhuma chamada.\n */\nfunction startDevRefresh(config: AppConnectionsConfig) {\n if (process.env.NODE_ENV !== \"development\") return;\n const { issuer, clientId, clientSecret } = resolveConfig(config);\n if (!clientId || !clientSecret) return;\n const key = `${issuer}|${clientId}`;\n if (_devRefresh.has(key)) return;\n _devRefresh.add(key);\n\n const tick = () => void loadRemoteRegistry(config, true).catch(() => undefined);\n tick();\n setInterval(tick, 30_000).unref?.();\n}\n\n/** Cliente com config explícita — para quem não usa as env vars padrão. */\nexport function createAppConnections(config: AppConnectionsConfig = {}): AppConnectionsClient {\n startDevRefresh(config);\n const provider: RegistryProvider = async (force) => {\n const remote = await loadRemoteRegistry(config, force);\n // Entradas do formato antigo (registerConnections) continuam valendo.\n return new Map([..._registry, ...remote]);\n };\n return createCatalog(config, provider) as AppConnectionsClient;\n}\n\n/** Catálogo explícito, como o gerado por `npx geekapps-connections` (`geekappsConnectionsCatalog`). */\nexport type ConnectionsCatalog = Record<string, { readonly appId: string; readonly actions: Readonly<Record<string, string>> }>;\n\n/**\n * Opcional: usa um catálogo fixo em vez de consultar o auth-server. Útil em\n * testes ou quando a app não pode falar com o servidor em runtime.\n *\n * const connections = defineAppConnections<GeekappsConnections>(geekappsConnectionsCatalog);\n */\nexport function defineAppConnections<T>(catalog: ConnectionsCatalog, config: AppConnectionsConfig = {}): T {\n const registry: Registry = new Map(Object.entries(catalog as Record<string, ConnectionRegistryEntry>));\n return createCatalog(config, async () => registry) as T;\n}\n\n/** Cliente padrão, lendo GEEKAPPS_AUTH_CLIENT_ID / _SECRET do ambiente. */\nexport const appConnections: AppConnectionsClient = createAppConnections();\n\n// ─── Conectar esta app a outra (consent) ────────────────────────────────────\n//\n// O admin aprova UMA vez, no consent do auth-server, quais ações esta app\n// poderá chamar na app alvo. `connectApp` abre esse consent e\n// `completeAppConnection` fecha o fluxo no callback. Depois disso, o catálogo\n// (`npx geekapps-connections`) já enxerga a conexão.\n\nconst CONNECT_COOKIES = {\n verifier: \"gk_conn_pkce\",\n state: \"gk_conn_state\",\n returnTo: \"gk_conn_return\",\n redirectUri: \"gk_conn_redirect\",\n} as const;\n\nexport type ConnectAppParams = {\n /** client_id da app ALVO (a que expõe as ações). */\n targetAppId: string;\n /** AppAction.key das ações pedidas — as mesmas que aparecem no consent. */\n actions: string[];\n /** URL desta app que recebe o retorno do consent (rota que chama `completeAppConnection`). Precisa estar nos redirect URIs desta app. */\n redirectUri: string;\n /** Para onde `completeAppConnection` manda o usuário depois (padrão \"/\"). */\n returnTo?: string;\n /** Nome desta app exibido no consent. */\n displayName?: string;\n config?: AppConnectionsConfig;\n};\n\n/**\n * Inicia a conexão desta app com `targetAppId`: guarda PKCE/state em cookies\n * httpOnly e redireciona para o consent. Chame de um Server Action ou Route\n * Handler — não retorna (o `redirect` do Next interrompe a execução).\n */\nexport async function connectApp(params: ConnectAppParams): Promise<never> {\n const { issuer, clientId } = resolveConfig(params.config ?? {});\n if (!clientId) {\n throw new Error(\"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID — é o client_id desta app, a que pede a conexão.\");\n }\n if (params.actions.length === 0) {\n throw new Error(\"App Connections: informe ao menos uma ação em `actions`.\");\n }\n\n const codeVerifier = randomBytes(64).toString(\"base64url\");\n const state = randomBytes(24).toString(\"base64url\");\n\n const store = await cookies();\n const options = { httpOnly: true, secure: true, sameSite: \"lax\" as const, path: \"/\", maxAge: 600 };\n store.set(CONNECT_COOKIES.verifier, codeVerifier, options);\n store.set(CONNECT_COOKIES.state, state, options);\n store.set(CONNECT_COOKIES.returnTo, params.returnTo ?? \"/\", options);\n store.set(CONNECT_COOKIES.redirectUri, params.redirectUri, options);\n\n const url = new URL(`${issuer}/authorize`);\n url.searchParams.set(\"client_id\", clientId);\n url.searchParams.set(\"redirect_uri\", params.redirectUri);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"scope\", `openid ${params.actions.join(\" \")}`);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", createHash(\"sha256\").update(codeVerifier).digest(\"base64url\"));\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"target_app_id\", params.targetAppId);\n if (params.displayName) url.searchParams.set(\"connection_display_name\", params.displayName);\n\n redirect(url.toString());\n}\n\n/**\n * Fecha o fluxo de `connectApp`. Chame no callback com o `code` e o `state`\n * da query; devolve o `returnTo` para você redirecionar. Lança\n * AppConnectionError se o state não bater ou o auth-server recusar.\n */\nexport async function completeAppConnection(params: {\n code: string;\n state: string;\n config?: AppConnectionsConfig;\n}): Promise<{ returnTo: string }> {\n const { issuer, clientId, clientSecret } = resolveConfig(params.config ?? {});\n if (!clientId || !clientSecret) {\n throw new Error(\"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID e GEEKAPPS_AUTH_CLIENT_SECRET.\");\n }\n\n const store = await cookies();\n const read = (name: string) => store.get(name)?.value;\n const expectedState = read(CONNECT_COOKIES.state);\n const codeVerifier = read(CONNECT_COOKIES.verifier);\n const redirectUri = read(CONNECT_COOKIES.redirectUri);\n const returnTo = read(CONNECT_COOKIES.returnTo) ?? \"/\";\n\n for (const name of Object.values(CONNECT_COOKIES)) store.set(name, \"\", { maxAge: 0, path: \"/\" });\n\n if (!expectedState || !codeVerifier || !redirectUri || params.state !== expectedState) {\n throw new AppConnectionError(\"App Connections: estado inválido — inicie a conexão novamente.\", 400, \"invalid_state\", null);\n }\n\n const response = await fetch(`${issuer}/oauth/token`, {\n method: \"POST\",\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString(\"base64\")}`,\n \"content-type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n code: params.code,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n const code = body && typeof body.error === \"string\" ? body.error : undefined;\n throw new AppConnectionError(\n `App Connections: não foi possível concluir a conexão (${response.status}${code ? ` ${code}` : \"\"})`,\n response.status,\n code,\n body,\n );\n }\n\n return { returnTo };\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { cookies, headers } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport { NextResponse, type NextRequest } from \"next/server\";\nimport { createRemoteJWKSet, jwtVerify, type JWTPayload } from \"jose\";\n\n/**\n * A sessão não vale mais: expirou, foi revogada no painel ou o refresh token\n * foi invalidado. Os cookies já foram limpos quando este erro é lançado, então\n * o tratamento normal é redirecionar para o login.\n */\nexport class GeekappsSessionExpiredError extends Error {\n readonly code = \"session_expired\" as const;\n\n constructor(message = \"A sessão expirou ou foi revogada. Entre novamente.\") {\n super(message);\n this.name = \"GeekappsSessionExpiredError\";\n }\n}\n\n/**\n * Fixed URL of the Geekapps Auth Server (OIDC issuer + API). This never\n * changes per-environment, so it is hardcoded rather than read from env.\n */\nexport const GEEKAPPS_AUTH_SERVER_URL = \"https://accounts-api.geekapps.com.br\";\n\nexport type GeekappsAuthConfig = {\n /**\n * Auth Server (OIDC) issuer URL. Defaults to GEEKAPPS_AUTH_SERVER_URL and\n * should not need overriding in normal use.\n *\n * Deprecated (still supported as a fallback): GEEKAPPS_AUTH_SERVER_ISSUER,\n * GEEKAPPS_AUTH_ISSUER, GEEKAPPS_AUTH_SERVER_URL env, GEEKAPPS_AUTH_API_URL\n */\n issuer?: string;\n\n /**\n * OAuth client id. Optional when GEEKAPPS_AUTH_CLIENT_ID is defined.\n */\n clientId?: string;\n\n /**\n * OAuth client secret for confidential clients. Optional when\n * GEEKAPPS_AUTH_CLIENT_SECRET is defined.\n */\n clientSecret?: string;\n\n /**\n * Callback URL. Optional when GEEKAPPS_AUTH_REDIRECT_URI is defined.\n * If omitted, it is inferred from the current request origin + basePath/callback.\n */\n redirectUri?: string;\n\n scopes?: string[];\n basePath?: string;\n /**\n * @deprecated cookiePrefix is now auto-derived from clientId.\n * This field is kept for backwards compatibility but is ignored.\n */\n cookiePrefix?: string;\n secureCookies?: boolean;\n\n /**\n * Friendly alias used by apps. Same as afterSignInRedirectTo.\n */\n redirectTo?: string;\n\n afterSignInRedirectTo?: string;\n afterSignOutRedirectTo?: string;\n};\n\ntype ResolvedGeekappsAuthConfig = GeekappsAuthConfig & {\n issuer: string;\n clientId: string;\n basePath: string;\n cookiePrefix: string;\n};\n\nexport type SessionTokens = {\n accessToken: string | null;\n refreshToken: string | null;\n idToken: string | null;\n sessionId: string | null;\n};\n\nexport type StoredAccount = {\n /** Stable identifier — `sub` from id_token or fallback to sessionId. */\n id: string;\n accessToken: string;\n refreshToken: string | null;\n idToken: string | null;\n sessionId: string | null;\n user: {\n sub: string;\n name?: string | null;\n email?: string | null;\n picture?: string | null;\n phone?: string | null;\n };\n};\n\nexport type ServerAuthApiClient = {\n get: <T>(path: string) => Promise<T>;\n post: <T>(path: string, body?: unknown) => Promise<T>;\n patch: <T>(path: string, body?: unknown) => Promise<T>;\n put: <T>(path: string, body?: unknown) => Promise<T>;\n delete: <T>(path: string) => Promise<T>;\n};\n\ntype JsonObject = Record<string, unknown>;\n\ntype TokenLikeResponse = JsonObject & {\n access_token?: string;\n accessToken?: string;\n refresh_token?: string;\n refreshToken?: string;\n id_token?: string;\n idToken?: string;\n session_id?: string;\n sessionId?: string;\n tokens?: {\n access_token?: string;\n accessToken?: string;\n refresh_token?: string;\n refreshToken?: string;\n id_token?: string;\n idToken?: string;\n session_id?: string;\n sessionId?: string;\n };\n};\n\nconst MAX_ACCOUNTS = 8;\n\nfunction normalizeBaseUrl(url: string) {\n return url.replace(/\\/$/, \"\");\n}\n\nfunction normalizeBasePath(path = \"/api/auth\") {\n if (!path.startsWith(\"/\")) return `/${path}`;\n return path.replace(/\\/$/, \"\");\n}\n\nfunction createUrl(baseUrl: string, path: string) {\n if (/^https?:\\/\\//.test(path)) return path;\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${normalizeBaseUrl(baseUrl)}${normalizedPath}`;\n}\n\nfunction env(name: string) {\n const value = process.env[name];\n return value && value.trim().length > 0 ? value : undefined;\n}\n\nfunction resolveIssuer(input: GeekappsAuthConfig) {\n return normalizeBaseUrl(\n input.issuer ??\n env(\"GEEKAPPS_AUTH_SERVER_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_SERVER_URL\") ??\n // Deprecated: kept for backwards compatibility during the auth-server rename.\n env(\"GEEKAPPS_AUTH_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_API_URL\") ??\n GEEKAPPS_AUTH_SERVER_URL,\n );\n}\n\nfunction resolveClientId(input: GeekappsAuthConfig) {\n return input.clientId ?? env(\"GEEKAPPS_AUTH_CLIENT_ID\") ?? \"\";\n}\n\nfunction resolveClientSecret(input: GeekappsAuthConfig) {\n return input.clientSecret ?? env(\"GEEKAPPS_AUTH_CLIENT_SECRET\");\n}\n\nfunction applyClientCredentials(url: URL, config: ResolvedGeekappsAuthConfig) {\n if (!config.clientId || !config.clientSecret) return;\n url.searchParams.set(\"client_id\", config.clientId);\n url.searchParams.set(\"client_secret\", config.clientSecret);\n}\n\nfunction resolveConfiguredRedirectUri(input: GeekappsAuthConfig) {\n return input.redirectUri ?? env(\"GEEKAPPS_AUTH_REDIRECT_URI\");\n}\n\n/**\n * Derives a short stable 8-char hex hash from a clientId string.\n * Uses a simple djb2-style hash — no crypto dependency needed.\n */\nfunction hashClientId(clientId: string): string {\n let h = 5381;\n for (let i = 0; i < clientId.length; i++) {\n h = ((h << 5) + h) ^ (clientId.charCodeAt(i) & 0xff);\n h = h >>> 0; // keep unsigned 32-bit\n }\n return h.toString(16).padStart(8, \"0\");\n}\n\n/**\n * Auto-derives the cookie prefix from clientId.\n * Format: `gk_{8-char-hash}` — guaranteed unique per OAuth client.\n * Falls back to `gk` when clientId is empty (dev/test environments).\n */\nfunction deriveCookiePrefix(clientId: string): string {\n if (!clientId) return \"gk\";\n return `gk_${hashClientId(clientId)}`;\n}\n\n// GEEKAPPS_APP_URL é o override de produção: em prod o app roda atrás de\n// Docker sem proxy setando x-forwarded-host/x-forwarded-proto, então nem o\n// header Host nem request.nextUrl.origin são confiáveis (refletem o host\n// INTERNO do container, não o domínio público real) — por isso, quando\n// configurada, essa env var sempre vence. Sem ela (dev local, onde não está\n// setada no .env), deriva do próprio request — em localhost sem proxy o\n// Host já é localhost:PORTA mesmo, então funciona sem precisar de override.\nfunction requestOrigin(request: NextRequest) {\n const configured = env(\"GEEKAPPS_APP_URL\");\n if (configured) return configured.replace(/\\/$/, \"\");\n\n if (request.nextUrl?.origin) return request.nextUrl.origin;\n\n throw new Error(\n \"Cannot determine app origin. Set GEEKAPPS_APP_URL or ensure request.nextUrl is available.\",\n );\n}\n\nfunction resolveRedirectUri(config: ResolvedGeekappsAuthConfig, request: NextRequest) {\n return config.redirectUri ?? `${requestOrigin(request)}${config.basePath}/callback`;\n}\n\nfunction tokenFromResponse(data: TokenLikeResponse): SessionTokens {\n return {\n accessToken: data.accessToken ?? data.access_token ?? data.tokens?.accessToken ?? data.tokens?.access_token ?? null,\n refreshToken:\n data.refreshToken ?? data.refresh_token ?? data.tokens?.refreshToken ?? data.tokens?.refresh_token ?? null,\n idToken: data.idToken ?? data.id_token ?? data.tokens?.idToken ?? data.tokens?.id_token ?? null,\n sessionId: data.sessionId ?? data.session_id ?? data.tokens?.sessionId ?? data.tokens?.session_id ?? null,\n };\n}\n\n/** Decode a JWT payload without verifying signature (safe for client-visible claims). */\nfunction decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split(\".\");\n if (parts.length < 2) return null;\n const payload = parts[1];\n if (!payload) return null;\n return JSON.parse(Buffer.from(payload, \"base64url\").toString(\"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction parseAccountFromJwt(tokens: SessionTokens): StoredAccount | null {\n if (!tokens.accessToken) return null;\n\n const jwtToParse = tokens.idToken ?? tokens.accessToken;\n const payload = decodeJwtPayload(jwtToParse);\n if (!payload) return null;\n\n const sub = typeof payload.sub === \"string\" ? payload.sub : null;\n const id = sub ?? tokens.sessionId;\n if (!id) return null;\n\n return {\n id,\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n idToken: tokens.idToken ?? null,\n sessionId: tokens.sessionId,\n user: {\n sub: id,\n name: typeof payload.name === \"string\" ? payload.name : null,\n email: typeof payload.email === \"string\" ? payload.email : null,\n picture: typeof payload.picture === \"string\" ? payload.picture : null,\n phone: typeof payload.phone_number === \"string\" ? payload.phone_number : null,\n },\n };\n}\n\n/**\n * Cookie name scheme — 3 cookies per slot, each well under 4096 bytes:\n *\n * {prefix}_m{n} — metadata blob (base64url JSON): { id, sid?, n?, e?, p? }\n * Claims extracted from id_token at login. Never stores tokens.\n * {prefix}_at{n} — access token (httpOnly). ~1-2 KB.\n * {prefix}_rt{n} — refresh token (httpOnly). ~1 KB.\n * {prefix}_active — active slot index (\"1\", \"2\", …)\n * {prefix}_count — total stored slots\n * {prefix}_ao — active org id for this app\n * {prefix}_tp — non-httpOnly copy of active access token for client-side axios\n *\n * id_token is NOT stored in cookies — claims are extracted at login and cached in\n * the metadata cookie. This is the key size saving.\n */\nfunction getCookieNames(prefix: string) {\n return {\n active: `${prefix}_active`,\n count: `${prefix}_count`,\n activeOrganizationId: `${prefix}_ao`,\n tokenPub: `${prefix}_tp`,\n pkceVerifier: `${prefix}_pkce`,\n slotMeta: (n: number) => `${prefix}_m${n}`,\n slotAt: (n: number) => `${prefix}_at${n}`,\n slotRt: (n: number) => `${prefix}_rt${n}`,\n };\n}\n\nfunction generateCodeVerifier(): string {\n return randomBytes(64).toString(\"base64url\");\n}\n\nfunction createCodeChallenge(codeVerifier: string): string {\n return createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n}\n\ntype SlotMeta = {\n id: string;\n sid?: string;\n n?: string;\n e?: string;\n p?: string;\n};\n\nfunction encodeMeta(account: StoredAccount): string {\n const m: SlotMeta = { id: account.id };\n if (account.sessionId) m.sid = account.sessionId;\n if (account.user.name) m.n = account.user.name;\n if (account.user.email) m.e = account.user.email;\n if (account.user.picture) m.p = account.user.picture;\n return Buffer.from(JSON.stringify(m), \"utf8\").toString(\"base64url\");\n}\n\nfunction decodeMeta(value: string): SlotMeta | null {\n try {\n const m = JSON.parse(Buffer.from(value, \"base64url\").toString(\"utf8\")) as SlotMeta;\n return m.id ? m : null;\n } catch {\n return null;\n }\n}\n\nfunction getCookieOptions(config: ResolvedGeekappsAuthConfig) {\n return {\n httpOnly: true,\n secure: config.secureCookies ?? process.env.NODE_ENV === \"production\",\n sameSite: \"lax\" as const,\n path: \"/\",\n };\n}\n\nasync function readBody(request: NextRequest) {\n const text = await request.text();\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction appendSearchParams(url: string, request: NextRequest) {\n const target = new URL(url);\n request.nextUrl.searchParams.forEach((value, key) => {\n target.searchParams.set(key, value);\n });\n return target.toString();\n}\n\nfunction routeFromRequest(request: NextRequest, basePath: string) {\n const pathname = request.nextUrl.pathname;\n if (!pathname.startsWith(basePath)) return pathname;\n const route = pathname.slice(basePath.length);\n return route || \"/\";\n}\n\nfunction isJsonResponse(response: Response) {\n return response.headers.get(\"content-type\")?.includes(\"application/json\");\n}\n\nasync function responseFromApi(response: Response) {\n if (response.status === 204) return new NextResponse(null, { status: 204 });\n const body = isJsonResponse(response) ? await response.json().catch(() => null) : await response.text();\n return NextResponse.json(body, { status: response.status });\n}\n\nconst _remoteJWKSCache = new Map<string, ReturnType<typeof createRemoteJWKSet>>();\n\ntype ServiceTokenCache = { token: string; expiresAt: number };\nconst _serviceTokenCache = new Map<string, ServiceTokenCache>();\n\nasync function fetchServiceToken(issuer: string, clientId: string, clientSecret: string): Promise<string | null> {\n const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString(\"base64\");\n try {\n const res = await fetch(createUrl(issuer, \"/auth/token\"), {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n authorization: `Basic ${credentials}`,\n },\n body: \"grant_type=service_account\",\n cache: \"no-store\",\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { access_token?: string };\n return data.access_token ?? null;\n } catch {\n return null;\n }\n}\n\nasync function getServiceToken(issuer: string, clientId: string, clientSecret: string): Promise<string | null> {\n const key = `${issuer}:${clientId}`;\n const now = Date.now();\n const cached = _serviceTokenCache.get(key);\n if (cached && cached.expiresAt - 30_000 > now) return cached.token;\n const token = await fetchServiceToken(issuer, clientId, clientSecret);\n if (!token) return null;\n _serviceTokenCache.set(key, { token, expiresAt: now + 420_000 });\n return token;\n}\n\ntype ServiceAccountConfig = {\n issuer?: string;\n clientId?: string;\n clientSecret?: string;\n};\n\n/**\n * Returns a service account access token.\n * The issuer is always the Geekapps Auth Server (GEEKAPPS_AUTH_SERVER_URL) —\n * it does not need to be configured. Reads GEEKAPPS_SERVICE_ACCOUNT_CLIENT_ID,\n * GEEKAPPS_SERVICE_ACCOUNT_CLIENT_SECRET by default.\n * Any field can be overridden via the optional config argument.\n * Tokens are cached per client and auto-renewed before expiry (~7 min TTL).\n */\nexport function getServiceAccountToken(override: ServiceAccountConfig = {}): Promise<string | null> {\n const issuer = normalizeBaseUrl(\n override.issuer ??\n // Deprecated: kept for backwards compatibility during the auth-server rename.\n env(\"GEEKAPPS_AUTH_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_API_URL\") ??\n GEEKAPPS_AUTH_SERVER_URL,\n );\n const clientId = override.clientId ?? env(\"GEEKAPPS_SERVICE_ACCOUNT_CLIENT_ID\") ?? \"\";\n const clientSecret = override.clientSecret ?? env(\"GEEKAPPS_SERVICE_ACCOUNT_CLIENT_SECRET\") ?? \"\";\n if (!clientId || !clientSecret) return Promise.resolve(null);\n return getServiceToken(issuer, clientId, clientSecret);\n}\n\nfunction getRemoteJWKS(issuer: string) {\n if (!_remoteJWKSCache.has(issuer)) {\n _remoteJWKSCache.set(issuer, createRemoteJWKSet(new URL(`${issuer}/.well-known/jwks.json`)));\n }\n return _remoteJWKSCache.get(issuer)!;\n}\n\nexport async function verifyToken(\n token: string,\n issuer: string,\n): Promise<JWTPayload | null> {\n try {\n const { payload } = await jwtVerify(token, getRemoteJWKS(issuer), {\n algorithms: [\"RS256\"],\n issuer,\n });\n return payload;\n } catch {\n return null;\n }\n}\n\nexport function configureGeekappsAuth(input: GeekappsAuthConfig = {}) {\n const clientId = resolveClientId(input);\n const config: ResolvedGeekappsAuthConfig = {\n ...input,\n issuer: resolveIssuer(input),\n clientId,\n clientSecret: resolveClientSecret(input),\n redirectUri: resolveConfiguredRedirectUri(input),\n afterSignInRedirectTo:\n input.afterSignInRedirectTo ?? input.redirectTo ?? \"/\",\n basePath: normalizeBasePath(input.basePath),\n cookiePrefix: deriveCookiePrefix(clientId),\n };\n\n const cn = getCookieNames(config.cookiePrefix);\n\n // ── Slot helpers ──────────────────────────────────────────────────────────\n\n async function getCount(): Promise<number> {\n const cookieStore = await cookies();\n const raw = cookieStore.get(cn.count)?.value;\n const n = raw ? Number.parseInt(raw, 10) : 0;\n return Number.isNaN(n) ? 0 : n;\n }\n\n async function getActiveIndex(): Promise<number> {\n const cookieStore = await cookies();\n const raw = cookieStore.get(cn.active)?.value;\n if (!raw) return 0;\n const n = Number.parseInt(raw, 10);\n return Number.isNaN(n) ? 0 : n;\n }\n\n function readSlot(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n n: number,\n ): StoredAccount | null {\n const at = cookieStore.get(cn.slotAt(n))?.value;\n if (!at) return null;\n const meta = decodeMeta(cookieStore.get(cn.slotMeta(n))?.value ?? \"\");\n if (!meta) return null;\n return {\n id: meta.id,\n accessToken: at,\n refreshToken: cookieStore.get(cn.slotRt(n))?.value ?? null,\n idToken: null, // not stored in cookies; claims are in meta\n sessionId: meta.sid ?? null,\n user: {\n sub: meta.id,\n name: meta.n ?? null,\n email: meta.e ?? null,\n picture: meta.p ?? null,\n },\n };\n }\n\n function writeSlot(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n n: number,\n account: StoredAccount,\n ) {\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n cookieStore.set(cn.slotMeta(n), encodeMeta(account), opts);\n cookieStore.set(cn.slotAt(n), account.accessToken, opts);\n if (account.refreshToken) cookieStore.set(cn.slotRt(n), account.refreshToken, opts);\n }\n\n function clearSlot(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n n: number,\n ) {\n const clear = { ...getCookieOptions(config), maxAge: 0 };\n cookieStore.set(cn.slotMeta(n), \"\", clear);\n cookieStore.set(cn.slotAt(n), \"\", clear);\n cookieStore.set(cn.slotRt(n), \"\", clear);\n }\n\n // ── Public account helpers ─────────────────────────────────────────────────\n\n async function getAccountsList(): Promise<StoredAccount[]> {\n const [cookieStore, count] = await Promise.all([cookies(), getCount()]);\n const accounts: StoredAccount[] = [];\n for (let i = 1; i <= count; i++) {\n const slot = readSlot(cookieStore, i);\n if (slot) accounts.push(slot);\n }\n return accounts;\n }\n\n async function getActiveAccount(): Promise<StoredAccount | null> {\n const [cookieStore, activeIdx, count] = await Promise.all([cookies(), getActiveIndex(), getCount()]);\n if (count === 0) return null;\n if (activeIdx >= 1 && activeIdx <= count) {\n const slot = readSlot(cookieStore, activeIdx);\n if (slot) return slot;\n }\n // Fall back to slot 1\n return readSlot(cookieStore, 1);\n }\n\n async function getAccessToken() {\n // Prefer the token injected by the middleware via request header (same-request refresh)\n try {\n const hdrs = await headers();\n const auth = hdrs.get(\"authorization\");\n if (auth?.startsWith(\"Bearer \")) return auth.slice(7);\n } catch {}\n const active = await getActiveAccount();\n return active?.accessToken ?? null;\n }\n\n async function getRefreshToken() {\n const active = await getActiveAccount();\n return active?.refreshToken ?? null;\n }\n\n async function getSession(): Promise<SessionTokens | null> {\n const active = await getActiveAccount();\n if (!active) return null;\n return {\n accessToken: active.accessToken,\n refreshToken: active.refreshToken,\n idToken: active.idToken,\n sessionId: active.sessionId,\n };\n }\n\n async function getUser(): Promise<StoredAccount[\"user\"] | null> {\n const active = await getActiveAccount();\n return active?.user ?? null;\n }\n\n async function getUserById(userId: string, applicationId?: string): Promise<unknown | null> {\n const qs = new URLSearchParams({ ...(applicationId ? { applicationId } : {}) });\n try {\n return await apiRequest<unknown>(`/users/${userId}?${qs}`);\n } catch {\n return null;\n }\n }\n\n async function getOrganizations(): Promise<{ organizations: unknown[]; currentOrgId: string | null }> {\n const cookieStore = await cookies();\n const currentOrgId = cookieStore.get(cn.activeOrganizationId)?.value ?? null;\n try {\n const data = await apiRequest<unknown[] | { organizations: unknown[] }>(\"/organizations\");\n const organizations = Array.isArray(data) ? data : (data as { organizations: unknown[] }).organizations;\n return { organizations, currentOrgId };\n } catch {\n return { organizations: [], currentOrgId };\n }\n }\n\n function clearPublicTokenCookie(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n ) {\n // Clear legacy _tp cookie if present\n if (cookieStore.get(cn.tokenPub)?.value) {\n cookieStore.set(cn.tokenPub, \"\", { httpOnly: false, maxAge: 0, path: \"/\" });\n }\n }\n\n async function saveAccountToList(tokens: SessionTokens) {\n const account = parseAccountFromJwt(tokens);\n if (!account) return;\n\n const cookieStore = await cookies();\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n const count = await getCount();\n\n // Find existing slot for this account id\n let targetSlot = 0;\n for (let i = 1; i <= count; i++) {\n const existing = readSlot(cookieStore, i);\n if (existing?.id === account.id) {\n targetSlot = i;\n break;\n }\n }\n\n if (targetSlot === 0) {\n if (count >= MAX_ACCOUNTS) return;\n targetSlot = count + 1;\n cookieStore.set(cn.count, String(targetSlot), opts);\n }\n\n writeSlot(cookieStore, targetSlot, account);\n cookieStore.set(cn.active, String(targetSlot), opts);\n clearPublicTokenCookie(cookieStore);\n }\n\n // Alias for backwards compat\n const setSessionCookies = saveAccountToList;\n\n async function switchAccount(accountId: string): Promise<boolean> {\n const [cookieStore, count] = await Promise.all([cookies(), getCount()]);\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n\n for (let i = 1; i <= count; i++) {\n const slot = readSlot(cookieStore, i);\n if (slot && (slot.id === accountId || slot.sessionId === accountId)) {\n cookieStore.set(cn.active, String(i), opts);\n clearPublicTokenCookie(cookieStore);\n return true;\n }\n }\n return false;\n }\n\n async function removeActiveAccount() {\n const [cookieStore, activeIdx, count] = await Promise.all([cookies(), getActiveIndex(), getCount()]);\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n const clear = { ...getCookieOptions(config), maxAge: 0 };\n\n if (count === 0) return;\n\n const remaining: StoredAccount[] = [];\n for (let i = 1; i <= count; i++) {\n if (i === activeIdx) continue;\n const slot = readSlot(cookieStore, i);\n if (slot) remaining.push(slot);\n }\n\n for (let i = 1; i <= count; i++) {\n clearSlot(cookieStore, i);\n }\n\n if (remaining.length === 0) {\n cookieStore.set(cn.count, \"0\", clear);\n cookieStore.set(cn.active, \"0\", clear);\n await clearPublicTokenCookie(cookieStore);\n return;\n }\n\n // Re-compact remaining accounts into slots 1..n\n for (let i = 0; i < remaining.length; i++) {\n await writeSlot(cookieStore, i + 1, remaining[i]!);\n }\n cookieStore.set(cn.count, String(remaining.length), opts);\n cookieStore.set(cn.active, \"1\", opts);\n clearPublicTokenCookie(cookieStore);\n }\n\n async function clearAllSessionCookies() {\n const [cookieStore, count] = await Promise.all([cookies(), getCount()]);\n const clear = { ...getCookieOptions(config), maxAge: 0 };\n for (let i = 1; i <= count; i++) {\n clearSlot(cookieStore, i);\n }\n cookieStore.set(cn.count, \"0\", clear);\n cookieStore.set(cn.active, \"0\", clear);\n clearPublicTokenCookie(cookieStore);\n }\n\n async function tryRefreshTokens(): Promise<string | null> {\n const refreshToken = await getRefreshToken();\n if (!refreshToken || !config.clientId) return null;\n\n const basicAuth = Buffer.from(`${config.clientId}:${config.clientSecret ?? \"\"}`).toString(\"base64\");\n\n const response = await fetch(createUrl(config.issuer, \"/auth/token\"), {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n authorization: `Basic ${basicAuth}`,\n },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) return null;\n\n const data = (await response.json().catch(() => null)) as TokenLikeResponse | null;\n if (!data) return null;\n\n const tokens = tokenFromResponse(data);\n if (!tokens.accessToken) return null;\n\n await saveAccountToList(tokens);\n return tokens.accessToken;\n }\n\n async function apiRequest<T>(path: string, init: RequestInit = {}): Promise<T> {\n const accessToken = await getAccessToken();\n const requestHeaders = new Headers(init.headers);\n\n if (accessToken) requestHeaders.set(\"authorization\", `Bearer ${accessToken}`);\n if (init.body !== undefined && !requestHeaders.has(\"content-type\")) {\n requestHeaders.set(\"content-type\", \"application/json\");\n }\n\n const url = new URL(createUrl(config.issuer, path));\n applyClientCredentials(url, config);\n\n const response = await fetch(url, {\n ...init,\n headers: requestHeaders,\n cache: \"no-store\",\n });\n\n if (response.status === 401) {\n const newAccessToken = await tryRefreshTokens();\n\n if (!newAccessToken) {\n // Sem renovar depois de um 401, a sessão acabou: expirou, foi revogada\n // no painel ou o refresh token caiu. Os cookies apontam para algo que\n // não existe mais, então saem — senão toda requisição seguinte repete\n // o mesmo ciclo. Quem chamou recebe um erro que dá para tratar, em vez\n // de \"Auth API error 401\" vindo do fundo da pilha.\n await clearAllSessionCookies().catch(() => {});\n throw new GeekappsSessionExpiredError();\n }\n\n if (newAccessToken) {\n const retryHeaders = new Headers(init.headers);\n retryHeaders.set(\"authorization\", `Bearer ${newAccessToken}`);\n if (init.body !== undefined && !retryHeaders.has(\"content-type\")) {\n retryHeaders.set(\"content-type\", \"application/json\");\n }\n const retryUrl = new URL(createUrl(config.issuer, path));\n applyClientCredentials(retryUrl, config);\n const retryResponse = await fetch(retryUrl, {\n ...init,\n headers: retryHeaders,\n cache: \"no-store\",\n });\n if (!retryResponse.ok) {\n const error = await retryResponse.json().catch(() => null);\n throw new Error(error?.error_description ?? error?.error ?? error?.message ?? `Auth API error ${retryResponse.status}`);\n }\n if (retryResponse.status === 204) return null as T;\n return (await retryResponse.json()) as T;\n }\n }\n\n if (!response.ok) {\n const error = await response.json().catch(() => null);\n throw new Error(error?.error_description ?? error?.error ?? error?.message ?? `Auth API error ${response.status}`);\n }\n\n if (response.status === 204) return null as T;\n return (await response.json()) as T;\n }\n\n function createApiClient(): ServerAuthApiClient {\n return {\n get: (path) => apiRequest(path),\n post: (path, body) => apiRequest(path, { method: \"POST\", body: body === undefined ? undefined : JSON.stringify(body) }),\n patch: (path, body) => apiRequest(path, { method: \"PATCH\", body: body === undefined ? undefined : JSON.stringify(body) }),\n put: (path, body) => apiRequest(path, { method: \"PUT\", body: body === undefined ? undefined : JSON.stringify(body) }),\n delete: (path) => apiRequest(path, { method: \"DELETE\" }),\n };\n }\n\n async function requireUser(options: { redirectTo?: string } = {}) {\n const accessToken = await getAccessToken();\n if (!accessToken) {\n redirect(options.redirectTo ?? \"/\");\n }\n return accessToken;\n }\n\n function escapeHtml(str: string): string {\n return str.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\n }\n\n function sanitizeRedirectTo(value: string | null | undefined): string {\n const raw = value ?? \"/\";\n // Never redirect back into the auth basePath — that would loop or replay a stale code.\n if (raw.startsWith(config.basePath)) return \"/\";\n // Only allow relative paths to prevent open-redirect.\n if (raw.startsWith(\"/\") && !raw.startsWith(\"//\")) return raw;\n return \"/\";\n }\n\n async function createAuthorizeRedirect(request: NextRequest, mode: \"login\" | \"register\" | \"add-account\" | \"google\") {\n const redirectTo = sanitizeRedirectTo(request.nextUrl.searchParams.get(\"redirectTo\") ?? config.afterSignInRedirectTo);\n const flowId = request.nextUrl.searchParams.get(\"flow_id\");\n const url = new URL(createUrl(config.issuer, mode === \"google\" ? \"/auth/google\" : \"/authorize\"));\n\n if (!config.clientId) {\n return NextResponse.json(\n { error: \"missing_client_id\", message: \"Missing GEEKAPPS_AUTH_CLIENT_ID or clientId.\" },\n { status: 500 },\n );\n }\n\n url.searchParams.set(\"client_id\", config.clientId);\n url.searchParams.set(\"redirect_uri\", resolveRedirectUri(config, request));\n url.searchParams.set(\"response_type\", \"code\");\n const scopes = config.scopes ?? [\"openid\", \"profile\", \"email\"];\n if (!scopes.includes(\"offline_access\")) scopes.push(\"offline_access\");\n url.searchParams.set(\"scope\", scopes.join(\" \"));\n url.searchParams.set(\"state\", Buffer.from(JSON.stringify({ redirectTo, mode })).toString(\"base64url\"));\n if (mode === \"register\") url.searchParams.set(\"screen_hint\", \"signup\");\n if (mode === \"add-account\") {\n // Adding an account always needs a fresh login, regardless of any existing session.\n url.searchParams.set(\"prompt\", \"login\");\n } else {\n // `prompt` (login | select_account | none | consent) is forwarded as-is to\n // the IDP — see OidcPrompt in client.tsx for what each value does.\n const prompt = request.nextUrl.searchParams.get(\"prompt\");\n // Legacy fallback: silentLogin=false is equivalent to prompt=login.\n const silentLogin = request.nextUrl.searchParams.get(\"silentLogin\");\n const resolvedPrompt = prompt ?? (silentLogin === \"false\" ? \"login\" : null);\n if (resolvedPrompt) url.searchParams.set(\"prompt\", resolvedPrompt);\n }\n if (flowId) url.searchParams.set(\"flow_id\", flowId);\n\n const codeVerifier = generateCodeVerifier();\n url.searchParams.set(\"code_challenge\", createCodeChallenge(codeVerifier));\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n const response = NextResponse.redirect(url);\n const cn = getCookieNames(config.cookiePrefix);\n response.cookies.set(cn.pkceVerifier, codeVerifier, {\n ...getCookieOptions(config),\n maxAge: 60 * 10,\n });\n return response;\n }\n\n async function exchangeCode(request: NextRequest) {\n const code = request.nextUrl.searchParams.get(\"code\");\n const state = request.nextUrl.searchParams.get(\"state\");\n\n const origin = requestOrigin(request);\n\n if (!code) {\n const err = request.nextUrl.searchParams.get(\"error\") ?? \"missing_code\";\n const desc = request.nextUrl.searchParams.get(\"error_description\") ?? request.nextUrl.searchParams.get(\"error_message\") ?? \"No authorization code received\";\n return NextResponse.redirect(new URL(`${config.basePath}/callback?error=${encodeURIComponent(err)}&error_description=${encodeURIComponent(desc)}`, origin));\n }\n\n if (!config.clientId) {\n return NextResponse.redirect(new URL(`${config.basePath}/callback?error=missing_client_id&error_description=Auth+client+is+not+configured`, origin));\n }\n\n const basicAuth = Buffer.from(\n `${config.clientId}:${config.clientSecret ?? \"\"}`,\n ).toString(\"base64\");\n\n const cn = getCookieNames(config.cookiePrefix);\n const cookieStore = await cookies();\n const codeVerifier = cookieStore.get(cn.pkceVerifier)?.value;\n cookieStore.set(cn.pkceVerifier, \"\", { ...getCookieOptions(config), maxAge: 0 });\n\n const tokenBody = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: resolveRedirectUri(config, request),\n });\n if (codeVerifier) tokenBody.set(\"code_verifier\", codeVerifier);\n\n const response = await fetch(createUrl(config.issuer, \"/auth/token\"), {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n authorization: `Basic ${basicAuth}`,\n },\n body: tokenBody,\n cache: \"no-store\",\n });\n\n const data = (await response.json().catch(() => ({}))) as TokenLikeResponse & { error?: string; error_description?: string };\n if (!response.ok) {\n const error = encodeURIComponent((data.error as string | undefined) ?? \"token_exchange_failed\");\n const desc = encodeURIComponent((data.error_description as string | undefined) ?? `Token exchange failed with status ${response.status}`);\n return NextResponse.redirect(new URL(`${config.basePath}/callback?error=${error}&error_description=${desc}`, origin));\n }\n\n await saveAccountToList(tokenFromResponse(data));\n\n let redirectTo = sanitizeRedirectTo(config.afterSignInRedirectTo);\n if (state) {\n try {\n const parsed = JSON.parse(Buffer.from(state, \"base64url\").toString(\"utf8\")) as { redirectTo?: string };\n redirectTo = sanitizeRedirectTo(parsed.redirectTo);\n } catch {\n // ignore malformed state\n }\n }\n\n return NextResponse.redirect(new URL(redirectTo, origin));\n }\n\n function mapLocalPathToApiPath(route: string) {\n if (route === \"/me\") return \"/auth/me\";\n if (route === \"/accounts/switch\") return \"/auth/accounts/switch\";\n if (route === \"/organizations/active\") return \"/auth/organizations/active\";\n if (route === \"/permissions/check\") return \"/auth/permissions/check\";\n if (route === \"/login/password\") return \"/auth/login/password\";\n if (route === \"/register/password\") return \"/auth/register/password\";\n if (route === \"/passwordless/link\") return \"/auth/passwordless/link\";\n return route;\n }\n\n async function handleAccountsLocal(): Promise<NextResponse> {\n const [accounts, activeIdx] = await Promise.all([getAccountsList(), getActiveIndex()]);\n\n return NextResponse.json({\n accounts: accounts.map((a, i) => ({\n id: a.id,\n sessionId: a.sessionId ?? a.id,\n isActive: i + 1 === activeIdx,\n user: {\n id: a.user.sub,\n name: a.user.name ?? null,\n email: a.user.email ?? null,\n imageUrl: a.user.picture ?? null,\n phone: a.user.phone ?? null,\n },\n })),\n });\n }\n\n async function handleOrganizationsLocal(): Promise<NextResponse> {\n const cookieStore = await cookies();\n const activeOrgId = cookieStore.get(cn.activeOrganizationId)?.value ?? null;\n try {\n const data = await apiRequest<unknown[]|{ organizations: unknown[] }>(\"/organizations\");\n const organizations = Array.isArray(data) ? data : (data as { organizations: unknown[] }).organizations;\n return NextResponse.json({ organizations, currentOrgId: activeOrgId });\n } catch {\n return NextResponse.json({ organizations: [], currentOrgId: activeOrgId });\n }\n }\n\n async function handleSwitchAccountLocal(request: NextRequest): Promise<NextResponse> {\n const body = await readBody(request);\n const targetId =\n body && typeof body === \"object\"\n ? String(\n (body as Record<string, unknown>).accountId ??\n (body as Record<string, unknown>).sessionId ??\n \"\",\n )\n : \"\";\n\n if (!targetId) {\n return NextResponse.json({ error: \"accountId required\" }, { status: 400 });\n }\n\n const switched = await switchAccount(targetId);\n if (!switched) {\n return NextResponse.json({ error: \"Account not found\" }, { status: 404 });\n }\n\n return NextResponse.json({ ok: true });\n }\n\n async function proxy(request: NextRequest, route: string) {\n const accessToken = await getAccessToken();\n const body = [\"GET\", \"HEAD\"].includes(request.method) ? undefined : await readBody(request);\n const url = new URL(appendSearchParams(createUrl(config.issuer, mapLocalPathToApiPath(route)), request));\n applyClientCredentials(url, config);\n const requestHeaders = new Headers();\n\n if (accessToken) requestHeaders.set(\"authorization\", `Bearer ${accessToken}`);\n if (body !== undefined) requestHeaders.set(\"content-type\", \"application/json\");\n\n let response = await fetch(url, {\n method: request.method,\n headers: requestHeaders,\n body: body === undefined ? undefined : typeof body === \"string\" ? body : JSON.stringify(body),\n cache: \"no-store\",\n });\n\n if (response.status === 401) {\n // Mesmo tratamento do apiRequest: tenta renovar uma vez e, se a sessão\n // já não existe (expirada ou revogada no painel), limpa os cookies. Sem\n // isso o cliente repetiria o mesmo token morto a cada chamada.\n const refreshed = await tryRefreshTokens();\n\n if (refreshed) {\n requestHeaders.set(\"authorization\", `Bearer ${refreshed}`);\n response = await fetch(url, {\n method: request.method,\n headers: requestHeaders,\n body:\n body === undefined\n ? undefined\n : typeof body === \"string\"\n ? body\n : JSON.stringify(body),\n cache: \"no-store\",\n });\n } else {\n await clearAllSessionCookies().catch(() => {});\n return NextResponse.json(\n { error: \"session_expired\" },\n { status: 401 },\n );\n }\n }\n\n const data = isJsonResponse(response) ? ((await response.json().catch(() => null)) as TokenLikeResponse | null) : null;\n if (data) {\n const tokens = tokenFromResponse(data);\n if (tokens.accessToken || tokens.refreshToken || tokens.idToken || tokens.sessionId) {\n await saveAccountToList(tokens);\n }\n return NextResponse.json(data, { status: response.status });\n }\n\n return responseFromApi(response);\n }\n\n async function handle(request: NextRequest) {\n const route = routeFromRequest(request, config.basePath);\n\n if (request.method === \"GET\" && route === \"/sign-in\") return createAuthorizeRedirect(request, \"login\");\n if (request.method === \"GET\" && route === \"/sign-up\") return createAuthorizeRedirect(request, \"register\");\n if (request.method === \"GET\" && route === \"/add-account\") return createAuthorizeRedirect(request, \"add-account\");\n if (request.method === \"GET\" && route === \"/login/google\") return createAuthorizeRedirect(request, \"google\");\n if (request.method === \"GET\" && route === \"/callback\") {\n const error = request.nextUrl.searchParams.get(\"error\");\n if (error) {\n const description = request.nextUrl.searchParams.get(\"error_description\") ?? request.nextUrl.searchParams.get(\"error_message\") ?? \"An authentication error occurred.\";\n return new NextResponse(\n `<!doctype html><html><head><meta charset=\"utf-8\"><title>Authentication Error</title></head><body style=\"font-family:sans-serif;max-width:480px;margin:80px auto;padding:0 16px\"><h2>Authentication Error</h2><p><strong>${escapeHtml(error)}</strong></p><p>${escapeHtml(description)}</p><a href=\"/\">Go back</a></body></html>`,\n { status: 400, headers: { \"content-type\": \"text/html; charset=utf-8\" } },\n );\n }\n return exchangeCode(request);\n }\n if (request.method === \"GET\" && route === \"/token\") {\n const accessToken = await getAccessToken();\n if (!accessToken) return NextResponse.json({ error: \"missing_token\" }, { status: 401 });\n return NextResponse.json({ accessToken });\n }\n\n\n if (request.method === \"GET\" && route === \"/accounts\") return handleAccountsLocal();\n if (request.method === \"POST\" && route === \"/accounts/switch\") return handleSwitchAccountLocal(request);\n if (request.method === \"GET\" && route === \"/organizations\") return handleOrganizationsLocal();\n\n if (request.method === \"POST\" && route === \"/organizations\") {\n const accessToken = await getAccessToken();\n const body = (await readBody(request)) as Record<string, unknown> | undefined;\n if (body && accessToken && !body.applicationId) {\n const claims = decodeJwtPayload(accessToken);\n const applicationId =\n (typeof claims?.application_id === \"string\" ? claims.application_id : null) ??\n (typeof claims?.client_id === \"string\" ? claims.client_id : null) ??\n (typeof claims?.applicationId === \"string\" ? claims.applicationId : null);\n if (applicationId) body.applicationId = applicationId;\n }\n const orgUrl = new URL(createUrl(config.issuer, \"/organizations\"));\n applyClientCredentials(orgUrl, config);\n const requestHeaders = new Headers();\n if (accessToken) requestHeaders.set(\"authorization\", `Bearer ${accessToken}`);\n if (body !== undefined) requestHeaders.set(\"content-type\", \"application/json\");\n const response = await fetch(orgUrl, {\n method: \"POST\",\n headers: requestHeaders,\n body: JSON.stringify(body),\n cache: \"no-store\",\n });\n return responseFromApi(response);\n }\n\n if (request.method === \"POST\" && route === \"/sign-out\") {\n await apiRequest(\"/auth/sign-out\", { method: \"POST\" }).catch(() => null);\n await removeActiveAccount();\n return NextResponse.json({ ok: true });\n }\n\n if (request.method === \"POST\" && route === \"/sign-out-all\") {\n await apiRequest(\"/auth/sign-out-all\", { method: \"POST\" }).catch(() => null);\n await clearAllSessionCookies();\n return NextResponse.json({ ok: true });\n }\n\n if (request.method === \"POST\" && route === \"/organizations/active\") {\n const body = await readBody(request);\n const organizationId =\n body && typeof body === \"object\" && \"organizationId\" in body\n ? (body as Record<string, unknown>).organizationId\n : null;\n const response = NextResponse.json({ ok: true });\n if (typeof organizationId === \"string\") {\n const cookieOpts = {\n httpOnly: true,\n sameSite: \"lax\" as const,\n path: \"/\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n };\n response.cookies.set(cn.activeOrganizationId, organizationId, cookieOpts);\n }\n return response;\n }\n\n return proxy(request, route);\n }\n\n return {\n handlers: {\n GET: handle,\n POST: handle,\n PATCH: handle,\n DELETE: handle,\n },\n GetSession: getSession,\n GetUser: getUser,\n GetUserById: getUserById,\n GetOrganizations: getOrganizations,\n SaveSession: saveAccountToList,\n GetAccessToken: getAccessToken,\n GetRefreshToken: getRefreshToken,\n IsAuthenticated: async () => (await getAccessToken()) !== null,\n TryRefreshTokens: tryRefreshTokens,\n RequireUser: requireUser,\n CreateAuthApiClient: createApiClient,\n cookiePrefix: config.cookiePrefix,\n VerifyToken: (token: string) => verifyToken(token, config.issuer),\n SignInUrl: async (redirectTo?: string) => {\n const configured = env(\"GEEKAPPS_APP_URL\");\n if (!configured) throw new Error(\"Cannot determine app origin. Set GEEKAPPS_APP_URL.\");\n const origin = configured.replace(/\\/$/, \"\");\n const url = new URL(`${origin}${config.basePath}/sign-in`);\n if (redirectTo) url.searchParams.set(\"redirectTo\", redirectTo);\n return url.toString();\n },\n };\n}\n\nexport function handlers(options?: GeekappsAuthConfig) {\n return configureGeekappsAuth(options).handlers;\n}\n\n/**\n * Returns true if the current request has a valid access token in cookies.\n * Safe to call in Server Components, Server Actions, and Route Handlers.\n */\nexport async function isAuthenticated(options?: GeekappsAuthConfig): Promise<boolean> {\n const { GetAccessToken } = configureGeekappsAuth(options);\n return (await GetAccessToken()) !== null;\n}\n"],"mappings":"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","names":["createHash","randomBytes","cookies","redirect","cn","env","randomBytes","cookies","createHash","redirect"]}
1
+ {"version":3,"sources":["../src/connections.ts","../src/server.ts"],"sourcesContent":["import { createHash, randomBytes } from \"node:crypto\";\nimport { buildModel, fetchRemoteCatalog, renderAugmentation, toRegistry } from \"@geekapps/auth-cli/lib\";\nimport { cookies } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport { GEEKAPPS_AUTH_SERVER_URL, configureGeekappsAuth } from \"./server\";\n\n/**\n * App Connections — chamar ações de negócio de OUTRA Application.\n *\n * Uma conexão liga um USUÁRIO desta app (X) a uma app alvo (Y). Ele a aprova\n * uma vez no consent, escolhendo as ações liberadas e a organização dentro do\n * Y sob a qual elas rodam. A chamada vai com o access token desse usuário (o\n * da sessão, por padrão): é ele que diz ao proxy qual conexão usar.\n *\n * Nada aqui fala com a API do Y diretamente: tudo passa pelo proxy do\n * auth-server, que valida a conexão e injeta a credencial. Esta app nunca vê\n * essa credencial — é esse o ponto do proxy.\n *\n * O catálogo tipado (`GeekappsConnections`) vem do arquivo gerado por\n * `npx geekapps-connections`.\n */\n\n/** Opções por chamada. Sem `userToken`, usa o access token do usuário logado na sessão. */\nexport type ConnectionCallOptions = { userToken?: string };\n\nexport type AppConnectionsConfig = {\n issuer?: string;\n /** client_id/secret desta app (a consumidora, X). */\n clientId?: string;\n clientSecret?: string;\n};\n\n/**\n * Preenchida por declaration merging no arquivo gerado\n * (`geekapps-connections.d.ts`). Vazia aqui de propósito: o SDK não sabe\n * quais apps existem — quem sabe é o auth-server, no momento da geração.\n */\nexport interface GeekappsConnections {}\n\n/** Erro de uma chamada de proxy — carrega o status HTTP para dar pra tratar. */\nexport class AppConnectionError extends Error {\n readonly status: number;\n readonly code: string | undefined;\n readonly body: unknown;\n\n constructor(message: string, status: number, code: string | undefined, body: unknown) {\n super(message);\n this.name = \"AppConnectionError\";\n this.status = status;\n this.code = code;\n this.body = body;\n }\n}\n\nfunction env(name: string) {\n const value = process.env[name];\n return value && value.trim().length > 0 ? value : undefined;\n}\n\nfunction resolveConfig(config: AppConnectionsConfig) {\n const issuer = (\n config.issuer ??\n env(\"GEEKAPPS_AUTH_SERVER_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_SERVER_URL\") ??\n GEEKAPPS_AUTH_SERVER_URL\n ).replace(/\\/$/, \"\");\n\n return {\n issuer,\n clientId: config.clientId ?? env(\"GEEKAPPS_AUTH_CLIENT_ID\") ?? \"\",\n clientSecret: config.clientSecret ?? env(\"GEEKAPPS_AUTH_CLIENT_SECRET\") ?? \"\",\n };\n}\n\n/**\n * A chamada crua do proxy, para quando não há catálogo gerado. `targetAppId` é\n * o client_id da app alvo e `actionKey` é a AppAction.key — o mesmo valor que\n * aparece como scope no consent.\n */\nexport async function callAppConnection<T = unknown>(params: {\n targetAppId: string;\n actionKey: string;\n payload?: unknown;\n /** Access token do usuário dono da conexão. Padrão: o do usuário logado. */\n userToken?: string;\n config?: AppConnectionsConfig;\n}): Promise<T> {\n const { issuer, clientId, clientSecret } = resolveConfig(params.config ?? {});\n if (!clientId || !clientSecret) {\n throw new Error(\n \"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID e GEEKAPPS_AUTH_CLIENT_SECRET — é com essas credenciais que o proxy identifica a app que está chamando.\",\n );\n }\n\n // A conexão é do usuário: sem o token dele o proxy não sabe qual usar.\n const userToken = params.userToken ?? (await configureGeekappsAuth().GetAccessToken());\n if (!userToken) {\n throw new AppConnectionError(\n \"App Connections: não há usuário logado — a conexão é do usuário, a chamada precisa do access token dele.\",\n 401,\n \"user_token_required\",\n null,\n );\n }\n\n const url = `${issuer}/connections/${encodeURIComponent(params.targetAppId)}/actions/${encodeURIComponent(params.actionKey)}`;\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n // Credenciais da app e token do usuário vão no corpo, não em headers.\n body: JSON.stringify({\n client_id: clientId,\n client_secret: clientSecret,\n user_token: userToken,\n ...(params.payload === undefined ? {} : { payload: params.payload }),\n }),\n cache: \"no-store\",\n });\n\n const body = await response.json().catch(() => null);\n\n if (!response.ok) {\n const code =\n body && typeof body === \"object\" && typeof (body as { error?: unknown }).error === \"string\"\n ? (body as { error: string }).error\n : undefined;\n throw new AppConnectionError(\n `App Connections: ${params.actionKey} falhou (${response.status}${code ? ` ${code}` : \"\"})`,\n response.status,\n code,\n body,\n );\n }\n\n return body as T;\n}\n\ntype ConnectionRegistryEntry = { appId: string; actions: Record<string, string> };\ntype Registry = Map<string, ConnectionRegistryEntry>;\n\n/** Registry de arquivos gerados no formato antigo (`registerConnections`). Mantido por compatibilidade. */\nconst _registry: Registry = new Map();\n\n/** Chamado por arquivos gerados no formato antigo. Não é necessário no fluxo automático. */\nexport function registerConnections(entries: Record<string, ConnectionRegistryEntry>) {\n for (const [name, entry] of Object.entries(entries)) _registry.set(name, entry);\n}\n\n// ─── Catálogo automático ────────────────────────────────────────────────────\n//\n// O SDK resolve `appConnections.<app>.<ação>` consultando o catálogo do\n// auth-server (cache em memória). Em desenvolvimento, também mantém um\n// `geekapps-connections.d.ts` na raiz do projeto que estende\n// `GeekappsConnections`: é isso que dá os tipos, sem o dev rodar nada.\n\nconst TYPES_MODULE = \"@geekapps/auth-nextjs/connections\";\nconst TYPES_FILE = \"geekapps-connections.d.ts\";\nconst REFRESH_MIN_INTERVAL_MS = 5_000;\n\nconst _remote = new Map<string, { at: number; registry: Registry }>();\nconst _inflight = new Map<string, Promise<Registry>>();\n\nasync function writeTypesInDev(model: ReturnType<typeof buildModel>) {\n if (process.env.NODE_ENV !== \"development\" || process.env.GEEKAPPS_CONNECTIONS_TYPES === \"off\") return;\n try {\n const { existsSync, readFileSync, writeFileSync } = await import(\"node:fs\");\n const { resolve } = await import(\"node:path\");\n const file = resolve(process.cwd(), TYPES_FILE);\n const content = renderAugmentation(model, TYPES_MODULE);\n if (existsSync(file) && readFileSync(file, \"utf-8\") === content) return;\n writeFileSync(file, content, \"utf-8\");\n } catch {\n // Os tipos são conveniência de desenvolvimento: nunca derrubam a chamada.\n }\n}\n\nasync function loadRemoteRegistry(config: AppConnectionsConfig, force = false): Promise<Registry> {\n const { issuer, clientId, clientSecret } = resolveConfig(config);\n if (!clientId || !clientSecret) {\n throw new Error(\n \"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID e GEEKAPPS_AUTH_CLIENT_SECRET — é com essas credenciais que o SDK descobre as apps conectáveis.\",\n );\n }\n\n const cacheKey = `${issuer}|${clientId}`;\n const ttl = process.env.NODE_ENV === \"development\" ? 30_000 : 5 * 60_000;\n const cached = _remote.get(cacheKey);\n const age = cached ? Date.now() - cached.at : Infinity;\n if (cached && (force ? age < REFRESH_MIN_INTERVAL_MS : age < ttl)) return cached.registry;\n\n const pending = _inflight.get(cacheKey);\n if (pending) return pending;\n\n const request = (async () => {\n try {\n const model = buildModel(await fetchRemoteCatalog({ issuer, clientId, clientSecret }));\n const registry: Registry = new Map(Object.entries(toRegistry(model)));\n _remote.set(cacheKey, { at: Date.now(), registry });\n void writeTypesInDev(model);\n return registry;\n } catch (error) {\n // Com um catálogo antigo em cache, é melhor continuar com ele do que falhar.\n if (cached) return cached.registry;\n throw new AppConnectionError(`App Connections: ${(error as Error).message}`, 502, \"catalog_unavailable\", null);\n } finally {\n _inflight.delete(cacheKey);\n }\n })();\n _inflight.set(cacheKey, request);\n return request;\n}\n\ntype RegistryProvider = (force?: boolean) => Promise<Registry>;\n\nasync function resolveTarget(provider: RegistryProvider, appName: string, actionName: string) {\n for (const force of [false, true]) {\n const registry = await provider(force);\n const entry = registry.get(appName);\n const key = entry?.actions[actionName];\n // Não achou? Pode ser app/ação nova: refaz a busca uma vez antes de desistir.\n if (entry && key) return { appId: entry.appId, key };\n }\n\n throw new Error(\n `App Connections: \"${appName}.${actionName}\" não existe no catálogo. Confira se a app alvo cadastrou a ação (geekapps-actions sync).`,\n );\n}\n\n/**\n * Proxy de dois níveis: `appConnections.<app>.<ação>(payload)`. Usa Proxy\n * porque os nomes das apps e das ações vêm do catálogo, não do código.\n */\nfunction createCatalog(config: AppConnectionsConfig, provider: RegistryProvider): unknown {\n return new Proxy(Object.create(null) as Record<string, unknown>, {\n get(_target, appName: string | symbol) {\n if (typeof appName !== \"string\") return undefined;\n\n return new Proxy(Object.create(null) as Record<string, unknown>, {\n get(_t, actionName: string | symbol) {\n if (typeof actionName !== \"string\") return undefined;\n\n return async (payload?: unknown, options?: ConnectionCallOptions) => {\n const target = await resolveTarget(provider, appName, actionName);\n return callAppConnection({\n targetAppId: target.appId,\n actionKey: target.key,\n payload,\n userToken: options?.userToken,\n config,\n });\n };\n },\n });\n },\n });\n}\n\n/**\n * Sem tipos gerados (primeira execução), qualquer `app.ação` é aceita. Assim\n * que o SDK escreve `geekapps-connections.d.ts`, a interface estendida passa a\n * valer e o TypeScript confere payload e retorno.\n */\nexport type AppConnectionsClient = keyof GeekappsConnections extends never\n ? Record<string, Record<string, (payload?: unknown, options?: ConnectionCallOptions) => Promise<unknown>>>\n : GeekappsConnections;\n\nconst _devRefresh = new Set<string>();\n\n/**\n * Em desenvolvimento, consulta o catálogo ao subir e a cada 30s, para que\n * `geekapps-connections.d.ts` acompanhe a app alvo mesmo sem nenhuma chamada.\n */\nfunction startDevRefresh(config: AppConnectionsConfig) {\n if (process.env.NODE_ENV !== \"development\") return;\n const { issuer, clientId, clientSecret } = resolveConfig(config);\n if (!clientId || !clientSecret) return;\n const key = `${issuer}|${clientId}`;\n if (_devRefresh.has(key)) return;\n _devRefresh.add(key);\n\n const tick = () => void loadRemoteRegistry(config, true).catch(() => undefined);\n tick();\n setInterval(tick, 30_000).unref?.();\n}\n\n/** Cliente com config explícita — para quem não usa as env vars padrão. */\nexport function createAppConnections(config: AppConnectionsConfig = {}): AppConnectionsClient {\n startDevRefresh(config);\n const provider: RegistryProvider = async (force) => {\n const remote = await loadRemoteRegistry(config, force);\n // Entradas do formato antigo (registerConnections) continuam valendo.\n return new Map([..._registry, ...remote]);\n };\n return createCatalog(config, provider) as AppConnectionsClient;\n}\n\n/** Catálogo explícito, como o gerado por `npx geekapps-connections` (`geekappsConnectionsCatalog`). */\nexport type ConnectionsCatalog = Record<string, { readonly appId: string; readonly actions: Readonly<Record<string, string>> }>;\n\n/**\n * Opcional: usa um catálogo fixo em vez de consultar o auth-server. Útil em\n * testes ou quando a app não pode falar com o servidor em runtime.\n *\n * const connections = defineAppConnections<GeekappsConnections>(geekappsConnectionsCatalog);\n */\nexport function defineAppConnections<T>(catalog: ConnectionsCatalog, config: AppConnectionsConfig = {}): T {\n const registry: Registry = new Map(Object.entries(catalog as Record<string, ConnectionRegistryEntry>));\n return createCatalog(config, async () => registry) as T;\n}\n\n/** Cliente padrão, lendo GEEKAPPS_AUTH_CLIENT_ID / _SECRET do ambiente. */\nexport const appConnections: AppConnectionsClient = createAppConnections();\n\n// ─── Conectar esta app a outra (consent) ────────────────────────────────────\n//\n// O admin aprova UMA vez, no consent do auth-server, quais ações esta app\n// poderá chamar na app alvo. `connectApp` abre esse consent e\n// `completeAppConnection` fecha o fluxo no callback. Depois disso, o catálogo\n// (`npx geekapps-connections`) já enxerga a conexão.\n\nconst CONNECT_COOKIES = {\n verifier: \"gk_conn_pkce\",\n state: \"gk_conn_state\",\n returnTo: \"gk_conn_return\",\n redirectUri: \"gk_conn_redirect\",\n} as const;\n\nexport type ConnectAppParams = {\n /** client_id da app ALVO (a que expõe as ações). */\n targetAppId: string;\n /** AppAction.key das ações pedidas — as mesmas que aparecem no consent. */\n actions: string[];\n /** URL desta app que recebe o retorno do consent (rota que chama `completeAppConnection`). Precisa estar nos redirect URIs desta app. */\n redirectUri: string;\n /** Para onde `completeAppConnection` manda o usuário depois (padrão \"/\"). */\n returnTo?: string;\n /** Nome desta app exibido no consent. */\n displayName?: string;\n config?: AppConnectionsConfig;\n};\n\n/**\n * Inicia a conexão desta app com `targetAppId`: guarda PKCE/state em cookies\n * httpOnly e redireciona para o consent. Chame de um Server Action ou Route\n * Handler — não retorna (o `redirect` do Next interrompe a execução).\n */\nexport async function connectApp(params: ConnectAppParams): Promise<never> {\n const { issuer, clientId } = resolveConfig(params.config ?? {});\n if (!clientId) {\n throw new Error(\"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID — é o client_id desta app, a que pede a conexão.\");\n }\n if (params.actions.length === 0) {\n throw new Error(\"App Connections: informe ao menos uma ação em `actions`.\");\n }\n\n const codeVerifier = randomBytes(64).toString(\"base64url\");\n const state = randomBytes(24).toString(\"base64url\");\n\n const store = await cookies();\n const options = { httpOnly: true, secure: true, sameSite: \"lax\" as const, path: \"/\", maxAge: 600 };\n store.set(CONNECT_COOKIES.verifier, codeVerifier, options);\n store.set(CONNECT_COOKIES.state, state, options);\n store.set(CONNECT_COOKIES.returnTo, params.returnTo ?? \"/\", options);\n store.set(CONNECT_COOKIES.redirectUri, params.redirectUri, options);\n\n const url = new URL(`${issuer}/authorize`);\n url.searchParams.set(\"client_id\", clientId);\n url.searchParams.set(\"redirect_uri\", params.redirectUri);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"scope\", `openid ${params.actions.join(\" \")}`);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", createHash(\"sha256\").update(codeVerifier).digest(\"base64url\"));\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"target_app_id\", params.targetAppId);\n // O servidor já exige isso para conexões; pedir explícito deixa a intenção clara.\n url.searchParams.set(\"prompt\", \"select_account consent\");\n if (params.displayName) url.searchParams.set(\"connection_display_name\", params.displayName);\n\n redirect(url.toString());\n}\n\n/**\n * Fecha o fluxo de `connectApp`. Chame no callback com o `code` e o `state`\n * da query; devolve o `returnTo` para você redirecionar. Lança\n * AppConnectionError se o state não bater ou o auth-server recusar.\n */\nexport async function completeAppConnection(params: {\n code: string;\n state: string;\n config?: AppConnectionsConfig;\n}): Promise<{ returnTo: string }> {\n const { issuer, clientId, clientSecret } = resolveConfig(params.config ?? {});\n if (!clientId || !clientSecret) {\n throw new Error(\"App Connections: defina GEEKAPPS_AUTH_CLIENT_ID e GEEKAPPS_AUTH_CLIENT_SECRET.\");\n }\n\n const store = await cookies();\n const read = (name: string) => store.get(name)?.value;\n const expectedState = read(CONNECT_COOKIES.state);\n const codeVerifier = read(CONNECT_COOKIES.verifier);\n const redirectUri = read(CONNECT_COOKIES.redirectUri);\n const returnTo = read(CONNECT_COOKIES.returnTo) ?? \"/\";\n\n for (const name of Object.values(CONNECT_COOKIES)) store.set(name, \"\", { maxAge: 0, path: \"/\" });\n\n if (!expectedState || !codeVerifier || !redirectUri || params.state !== expectedState) {\n throw new AppConnectionError(\"App Connections: estado inválido — inicie a conexão novamente.\", 400, \"invalid_state\", null);\n }\n\n const response = await fetch(`${issuer}/oauth/token`, {\n method: \"POST\",\n headers: {\n authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString(\"base64\")}`,\n \"content-type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"authorization_code\",\n code: params.code,\n redirect_uri: redirectUri,\n code_verifier: codeVerifier,\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) {\n const body = await response.json().catch(() => null);\n const code = body && typeof body.error === \"string\" ? body.error : undefined;\n throw new AppConnectionError(\n `App Connections: não foi possível concluir a conexão (${response.status}${code ? ` ${code}` : \"\"})`,\n response.status,\n code,\n body,\n );\n }\n\n return { returnTo };\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { cookies, headers } from \"next/headers\";\nimport { redirect } from \"next/navigation\";\nimport { NextResponse, type NextRequest } from \"next/server\";\nimport { createRemoteJWKSet, jwtVerify, type JWTPayload } from \"jose\";\n\n/**\n * A sessão não vale mais: expirou, foi revogada no painel ou o refresh token\n * foi invalidado. Os cookies já foram limpos quando este erro é lançado, então\n * o tratamento normal é redirecionar para o login.\n */\nexport class GeekappsSessionExpiredError extends Error {\n readonly code = \"session_expired\" as const;\n\n constructor(message = \"A sessão expirou ou foi revogada. Entre novamente.\") {\n super(message);\n this.name = \"GeekappsSessionExpiredError\";\n }\n}\n\n/**\n * Fixed URL of the Geekapps Auth Server (OIDC issuer + API). This never\n * changes per-environment, so it is hardcoded rather than read from env.\n */\nexport const GEEKAPPS_AUTH_SERVER_URL = \"https://accounts-api.geekapps.com.br\";\n\nexport type GeekappsAuthConfig = {\n /**\n * Auth Server (OIDC) issuer URL. Defaults to GEEKAPPS_AUTH_SERVER_URL and\n * should not need overriding in normal use.\n *\n * Deprecated (still supported as a fallback): GEEKAPPS_AUTH_SERVER_ISSUER,\n * GEEKAPPS_AUTH_ISSUER, GEEKAPPS_AUTH_SERVER_URL env, GEEKAPPS_AUTH_API_URL\n */\n issuer?: string;\n\n /**\n * OAuth client id. Optional when GEEKAPPS_AUTH_CLIENT_ID is defined.\n */\n clientId?: string;\n\n /**\n * OAuth client secret for confidential clients. Optional when\n * GEEKAPPS_AUTH_CLIENT_SECRET is defined.\n */\n clientSecret?: string;\n\n /**\n * Callback URL. Optional when GEEKAPPS_AUTH_REDIRECT_URI is defined.\n * If omitted, it is inferred from the current request origin + basePath/callback.\n */\n redirectUri?: string;\n\n scopes?: string[];\n basePath?: string;\n /**\n * @deprecated cookiePrefix is now auto-derived from clientId.\n * This field is kept for backwards compatibility but is ignored.\n */\n cookiePrefix?: string;\n secureCookies?: boolean;\n\n /**\n * Friendly alias used by apps. Same as afterSignInRedirectTo.\n */\n redirectTo?: string;\n\n afterSignInRedirectTo?: string;\n afterSignOutRedirectTo?: string;\n};\n\ntype ResolvedGeekappsAuthConfig = GeekappsAuthConfig & {\n issuer: string;\n clientId: string;\n basePath: string;\n cookiePrefix: string;\n};\n\nexport type SessionTokens = {\n accessToken: string | null;\n refreshToken: string | null;\n idToken: string | null;\n sessionId: string | null;\n};\n\nexport type StoredAccount = {\n /** Stable identifier — `sub` from id_token or fallback to sessionId. */\n id: string;\n accessToken: string;\n refreshToken: string | null;\n idToken: string | null;\n sessionId: string | null;\n user: {\n sub: string;\n name?: string | null;\n email?: string | null;\n picture?: string | null;\n phone?: string | null;\n };\n};\n\nexport type ServerAuthApiClient = {\n get: <T>(path: string) => Promise<T>;\n post: <T>(path: string, body?: unknown) => Promise<T>;\n patch: <T>(path: string, body?: unknown) => Promise<T>;\n put: <T>(path: string, body?: unknown) => Promise<T>;\n delete: <T>(path: string) => Promise<T>;\n};\n\ntype JsonObject = Record<string, unknown>;\n\ntype TokenLikeResponse = JsonObject & {\n access_token?: string;\n accessToken?: string;\n refresh_token?: string;\n refreshToken?: string;\n id_token?: string;\n idToken?: string;\n session_id?: string;\n sessionId?: string;\n tokens?: {\n access_token?: string;\n accessToken?: string;\n refresh_token?: string;\n refreshToken?: string;\n id_token?: string;\n idToken?: string;\n session_id?: string;\n sessionId?: string;\n };\n};\n\nconst MAX_ACCOUNTS = 8;\n\nfunction normalizeBaseUrl(url: string) {\n return url.replace(/\\/$/, \"\");\n}\n\nfunction normalizeBasePath(path = \"/api/auth\") {\n if (!path.startsWith(\"/\")) return `/${path}`;\n return path.replace(/\\/$/, \"\");\n}\n\nfunction createUrl(baseUrl: string, path: string) {\n if (/^https?:\\/\\//.test(path)) return path;\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n return `${normalizeBaseUrl(baseUrl)}${normalizedPath}`;\n}\n\nfunction env(name: string) {\n const value = process.env[name];\n return value && value.trim().length > 0 ? value : undefined;\n}\n\nfunction resolveIssuer(input: GeekappsAuthConfig) {\n return normalizeBaseUrl(\n input.issuer ??\n env(\"GEEKAPPS_AUTH_SERVER_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_SERVER_URL\") ??\n // Deprecated: kept for backwards compatibility during the auth-server rename.\n env(\"GEEKAPPS_AUTH_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_API_URL\") ??\n GEEKAPPS_AUTH_SERVER_URL,\n );\n}\n\nfunction resolveClientId(input: GeekappsAuthConfig) {\n return input.clientId ?? env(\"GEEKAPPS_AUTH_CLIENT_ID\") ?? \"\";\n}\n\nfunction resolveClientSecret(input: GeekappsAuthConfig) {\n return input.clientSecret ?? env(\"GEEKAPPS_AUTH_CLIENT_SECRET\");\n}\n\nfunction applyClientCredentials(url: URL, config: ResolvedGeekappsAuthConfig) {\n if (!config.clientId || !config.clientSecret) return;\n url.searchParams.set(\"client_id\", config.clientId);\n url.searchParams.set(\"client_secret\", config.clientSecret);\n}\n\nfunction resolveConfiguredRedirectUri(input: GeekappsAuthConfig) {\n return input.redirectUri ?? env(\"GEEKAPPS_AUTH_REDIRECT_URI\");\n}\n\n/**\n * Derives a short stable 8-char hex hash from a clientId string.\n * Uses a simple djb2-style hash — no crypto dependency needed.\n */\nfunction hashClientId(clientId: string): string {\n let h = 5381;\n for (let i = 0; i < clientId.length; i++) {\n h = ((h << 5) + h) ^ (clientId.charCodeAt(i) & 0xff);\n h = h >>> 0; // keep unsigned 32-bit\n }\n return h.toString(16).padStart(8, \"0\");\n}\n\n/**\n * Auto-derives the cookie prefix from clientId.\n * Format: `gk_{8-char-hash}` — guaranteed unique per OAuth client.\n * Falls back to `gk` when clientId is empty (dev/test environments).\n */\nfunction deriveCookiePrefix(clientId: string): string {\n if (!clientId) return \"gk\";\n return `gk_${hashClientId(clientId)}`;\n}\n\n// GEEKAPPS_APP_URL é o override de produção: em prod o app roda atrás de\n// Docker sem proxy setando x-forwarded-host/x-forwarded-proto, então nem o\n// header Host nem request.nextUrl.origin são confiáveis (refletem o host\n// INTERNO do container, não o domínio público real) — por isso, quando\n// configurada, essa env var sempre vence. Sem ela (dev local, onde não está\n// setada no .env), deriva do próprio request — em localhost sem proxy o\n// Host já é localhost:PORTA mesmo, então funciona sem precisar de override.\nfunction requestOrigin(request: NextRequest) {\n const configured = env(\"GEEKAPPS_APP_URL\");\n if (configured) return configured.replace(/\\/$/, \"\");\n\n if (request.nextUrl?.origin) return request.nextUrl.origin;\n\n throw new Error(\n \"Cannot determine app origin. Set GEEKAPPS_APP_URL or ensure request.nextUrl is available.\",\n );\n}\n\nfunction resolveRedirectUri(config: ResolvedGeekappsAuthConfig, request: NextRequest) {\n return config.redirectUri ?? `${requestOrigin(request)}${config.basePath}/callback`;\n}\n\nfunction tokenFromResponse(data: TokenLikeResponse): SessionTokens {\n return {\n accessToken: data.accessToken ?? data.access_token ?? data.tokens?.accessToken ?? data.tokens?.access_token ?? null,\n refreshToken:\n data.refreshToken ?? data.refresh_token ?? data.tokens?.refreshToken ?? data.tokens?.refresh_token ?? null,\n idToken: data.idToken ?? data.id_token ?? data.tokens?.idToken ?? data.tokens?.id_token ?? null,\n sessionId: data.sessionId ?? data.session_id ?? data.tokens?.sessionId ?? data.tokens?.session_id ?? null,\n };\n}\n\n/** Decode a JWT payload without verifying signature (safe for client-visible claims). */\nfunction decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split(\".\");\n if (parts.length < 2) return null;\n const payload = parts[1];\n if (!payload) return null;\n return JSON.parse(Buffer.from(payload, \"base64url\").toString(\"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction parseAccountFromJwt(tokens: SessionTokens): StoredAccount | null {\n if (!tokens.accessToken) return null;\n\n const jwtToParse = tokens.idToken ?? tokens.accessToken;\n const payload = decodeJwtPayload(jwtToParse);\n if (!payload) return null;\n\n const sub = typeof payload.sub === \"string\" ? payload.sub : null;\n const id = sub ?? tokens.sessionId;\n if (!id) return null;\n\n return {\n id,\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n idToken: tokens.idToken ?? null,\n sessionId: tokens.sessionId,\n user: {\n sub: id,\n name: typeof payload.name === \"string\" ? payload.name : null,\n email: typeof payload.email === \"string\" ? payload.email : null,\n picture: typeof payload.picture === \"string\" ? payload.picture : null,\n phone: typeof payload.phone_number === \"string\" ? payload.phone_number : null,\n },\n };\n}\n\n/**\n * Cookie name scheme — 3 cookies per slot, each well under 4096 bytes:\n *\n * {prefix}_m{n} — metadata blob (base64url JSON): { id, sid?, n?, e?, p? }\n * Claims extracted from id_token at login. Never stores tokens.\n * {prefix}_at{n} — access token (httpOnly). ~1-2 KB.\n * {prefix}_rt{n} — refresh token (httpOnly). ~1 KB.\n * {prefix}_active — active slot index (\"1\", \"2\", …)\n * {prefix}_count — total stored slots\n * {prefix}_ao — active org id for this app\n * {prefix}_tp — non-httpOnly copy of active access token for client-side axios\n *\n * id_token is NOT stored in cookies — claims are extracted at login and cached in\n * the metadata cookie. This is the key size saving.\n */\nfunction getCookieNames(prefix: string) {\n return {\n active: `${prefix}_active`,\n count: `${prefix}_count`,\n activeOrganizationId: `${prefix}_ao`,\n tokenPub: `${prefix}_tp`,\n pkceVerifier: `${prefix}_pkce`,\n slotMeta: (n: number) => `${prefix}_m${n}`,\n slotAt: (n: number) => `${prefix}_at${n}`,\n slotRt: (n: number) => `${prefix}_rt${n}`,\n };\n}\n\nfunction generateCodeVerifier(): string {\n return randomBytes(64).toString(\"base64url\");\n}\n\nfunction createCodeChallenge(codeVerifier: string): string {\n return createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n}\n\ntype SlotMeta = {\n id: string;\n sid?: string;\n n?: string;\n e?: string;\n p?: string;\n};\n\nfunction encodeMeta(account: StoredAccount): string {\n const m: SlotMeta = { id: account.id };\n if (account.sessionId) m.sid = account.sessionId;\n if (account.user.name) m.n = account.user.name;\n if (account.user.email) m.e = account.user.email;\n if (account.user.picture) m.p = account.user.picture;\n return Buffer.from(JSON.stringify(m), \"utf8\").toString(\"base64url\");\n}\n\nfunction decodeMeta(value: string): SlotMeta | null {\n try {\n const m = JSON.parse(Buffer.from(value, \"base64url\").toString(\"utf8\")) as SlotMeta;\n return m.id ? m : null;\n } catch {\n return null;\n }\n}\n\nfunction getCookieOptions(config: ResolvedGeekappsAuthConfig) {\n return {\n httpOnly: true,\n secure: config.secureCookies ?? process.env.NODE_ENV === \"production\",\n sameSite: \"lax\" as const,\n path: \"/\",\n };\n}\n\nasync function readBody(request: NextRequest) {\n const text = await request.text();\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction appendSearchParams(url: string, request: NextRequest) {\n const target = new URL(url);\n request.nextUrl.searchParams.forEach((value, key) => {\n target.searchParams.set(key, value);\n });\n return target.toString();\n}\n\nfunction routeFromRequest(request: NextRequest, basePath: string) {\n const pathname = request.nextUrl.pathname;\n if (!pathname.startsWith(basePath)) return pathname;\n const route = pathname.slice(basePath.length);\n return route || \"/\";\n}\n\nfunction isJsonResponse(response: Response) {\n return response.headers.get(\"content-type\")?.includes(\"application/json\");\n}\n\nasync function responseFromApi(response: Response) {\n if (response.status === 204) return new NextResponse(null, { status: 204 });\n const body = isJsonResponse(response) ? await response.json().catch(() => null) : await response.text();\n return NextResponse.json(body, { status: response.status });\n}\n\nconst _remoteJWKSCache = new Map<string, ReturnType<typeof createRemoteJWKSet>>();\n\ntype ServiceTokenCache = { token: string; expiresAt: number };\nconst _serviceTokenCache = new Map<string, ServiceTokenCache>();\n\nasync function fetchServiceToken(issuer: string, clientId: string, clientSecret: string): Promise<string | null> {\n const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString(\"base64\");\n try {\n const res = await fetch(createUrl(issuer, \"/auth/token\"), {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n authorization: `Basic ${credentials}`,\n },\n body: \"grant_type=service_account\",\n cache: \"no-store\",\n });\n if (!res.ok) return null;\n const data = (await res.json()) as { access_token?: string };\n return data.access_token ?? null;\n } catch {\n return null;\n }\n}\n\nasync function getServiceToken(issuer: string, clientId: string, clientSecret: string): Promise<string | null> {\n const key = `${issuer}:${clientId}`;\n const now = Date.now();\n const cached = _serviceTokenCache.get(key);\n if (cached && cached.expiresAt - 30_000 > now) return cached.token;\n const token = await fetchServiceToken(issuer, clientId, clientSecret);\n if (!token) return null;\n _serviceTokenCache.set(key, { token, expiresAt: now + 420_000 });\n return token;\n}\n\ntype ServiceAccountConfig = {\n issuer?: string;\n clientId?: string;\n clientSecret?: string;\n};\n\n/**\n * Returns a service account access token.\n * The issuer is always the Geekapps Auth Server (GEEKAPPS_AUTH_SERVER_URL) —\n * it does not need to be configured. Reads GEEKAPPS_SERVICE_ACCOUNT_CLIENT_ID,\n * GEEKAPPS_SERVICE_ACCOUNT_CLIENT_SECRET by default.\n * Any field can be overridden via the optional config argument.\n * Tokens are cached per client and auto-renewed before expiry (~7 min TTL).\n */\nexport function getServiceAccountToken(override: ServiceAccountConfig = {}): Promise<string | null> {\n const issuer = normalizeBaseUrl(\n override.issuer ??\n // Deprecated: kept for backwards compatibility during the auth-server rename.\n env(\"GEEKAPPS_AUTH_ISSUER\") ??\n env(\"GEEKAPPS_AUTH_API_URL\") ??\n GEEKAPPS_AUTH_SERVER_URL,\n );\n const clientId = override.clientId ?? env(\"GEEKAPPS_SERVICE_ACCOUNT_CLIENT_ID\") ?? \"\";\n const clientSecret = override.clientSecret ?? env(\"GEEKAPPS_SERVICE_ACCOUNT_CLIENT_SECRET\") ?? \"\";\n if (!clientId || !clientSecret) return Promise.resolve(null);\n return getServiceToken(issuer, clientId, clientSecret);\n}\n\nfunction getRemoteJWKS(issuer: string) {\n if (!_remoteJWKSCache.has(issuer)) {\n _remoteJWKSCache.set(issuer, createRemoteJWKSet(new URL(`${issuer}/.well-known/jwks.json`)));\n }\n return _remoteJWKSCache.get(issuer)!;\n}\n\nexport async function verifyToken(\n token: string,\n issuer: string,\n): Promise<JWTPayload | null> {\n try {\n const { payload } = await jwtVerify(token, getRemoteJWKS(issuer), {\n algorithms: [\"RS256\"],\n issuer,\n });\n return payload;\n } catch {\n return null;\n }\n}\n\nexport function configureGeekappsAuth(input: GeekappsAuthConfig = {}) {\n const clientId = resolveClientId(input);\n const config: ResolvedGeekappsAuthConfig = {\n ...input,\n issuer: resolveIssuer(input),\n clientId,\n clientSecret: resolveClientSecret(input),\n redirectUri: resolveConfiguredRedirectUri(input),\n afterSignInRedirectTo:\n input.afterSignInRedirectTo ?? input.redirectTo ?? \"/\",\n basePath: normalizeBasePath(input.basePath),\n cookiePrefix: deriveCookiePrefix(clientId),\n };\n\n const cn = getCookieNames(config.cookiePrefix);\n\n // ── Slot helpers ──────────────────────────────────────────────────────────\n\n async function getCount(): Promise<number> {\n const cookieStore = await cookies();\n const raw = cookieStore.get(cn.count)?.value;\n const n = raw ? Number.parseInt(raw, 10) : 0;\n return Number.isNaN(n) ? 0 : n;\n }\n\n async function getActiveIndex(): Promise<number> {\n const cookieStore = await cookies();\n const raw = cookieStore.get(cn.active)?.value;\n if (!raw) return 0;\n const n = Number.parseInt(raw, 10);\n return Number.isNaN(n) ? 0 : n;\n }\n\n function readSlot(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n n: number,\n ): StoredAccount | null {\n const at = cookieStore.get(cn.slotAt(n))?.value;\n if (!at) return null;\n const meta = decodeMeta(cookieStore.get(cn.slotMeta(n))?.value ?? \"\");\n if (!meta) return null;\n return {\n id: meta.id,\n accessToken: at,\n refreshToken: cookieStore.get(cn.slotRt(n))?.value ?? null,\n idToken: null, // not stored in cookies; claims are in meta\n sessionId: meta.sid ?? null,\n user: {\n sub: meta.id,\n name: meta.n ?? null,\n email: meta.e ?? null,\n picture: meta.p ?? null,\n },\n };\n }\n\n function writeSlot(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n n: number,\n account: StoredAccount,\n ) {\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n cookieStore.set(cn.slotMeta(n), encodeMeta(account), opts);\n cookieStore.set(cn.slotAt(n), account.accessToken, opts);\n if (account.refreshToken) cookieStore.set(cn.slotRt(n), account.refreshToken, opts);\n }\n\n function clearSlot(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n n: number,\n ) {\n const clear = { ...getCookieOptions(config), maxAge: 0 };\n cookieStore.set(cn.slotMeta(n), \"\", clear);\n cookieStore.set(cn.slotAt(n), \"\", clear);\n cookieStore.set(cn.slotRt(n), \"\", clear);\n }\n\n // ── Public account helpers ─────────────────────────────────────────────────\n\n async function getAccountsList(): Promise<StoredAccount[]> {\n const [cookieStore, count] = await Promise.all([cookies(), getCount()]);\n const accounts: StoredAccount[] = [];\n for (let i = 1; i <= count; i++) {\n const slot = readSlot(cookieStore, i);\n if (slot) accounts.push(slot);\n }\n return accounts;\n }\n\n async function getActiveAccount(): Promise<StoredAccount | null> {\n const [cookieStore, activeIdx, count] = await Promise.all([cookies(), getActiveIndex(), getCount()]);\n if (count === 0) return null;\n if (activeIdx >= 1 && activeIdx <= count) {\n const slot = readSlot(cookieStore, activeIdx);\n if (slot) return slot;\n }\n // Fall back to slot 1\n return readSlot(cookieStore, 1);\n }\n\n async function getAccessToken() {\n // Prefer the token injected by the middleware via request header (same-request refresh)\n try {\n const hdrs = await headers();\n const auth = hdrs.get(\"authorization\");\n if (auth?.startsWith(\"Bearer \")) return auth.slice(7);\n } catch {}\n const active = await getActiveAccount();\n return active?.accessToken ?? null;\n }\n\n async function getRefreshToken() {\n const active = await getActiveAccount();\n return active?.refreshToken ?? null;\n }\n\n async function getSession(): Promise<SessionTokens | null> {\n const active = await getActiveAccount();\n if (!active) return null;\n return {\n accessToken: active.accessToken,\n refreshToken: active.refreshToken,\n idToken: active.idToken,\n sessionId: active.sessionId,\n };\n }\n\n async function getUser(): Promise<StoredAccount[\"user\"] | null> {\n const active = await getActiveAccount();\n return active?.user ?? null;\n }\n\n async function getUserById(userId: string, applicationId?: string): Promise<unknown | null> {\n const qs = new URLSearchParams({ ...(applicationId ? { applicationId } : {}) });\n try {\n return await apiRequest<unknown>(`/users/${userId}?${qs}`);\n } catch {\n return null;\n }\n }\n\n async function getOrganizations(): Promise<{ organizations: unknown[]; currentOrgId: string | null }> {\n const cookieStore = await cookies();\n const currentOrgId = cookieStore.get(cn.activeOrganizationId)?.value ?? null;\n try {\n const data = await apiRequest<unknown[] | { organizations: unknown[] }>(\"/organizations\");\n const organizations = Array.isArray(data) ? data : (data as { organizations: unknown[] }).organizations;\n return { organizations, currentOrgId };\n } catch {\n return { organizations: [], currentOrgId };\n }\n }\n\n function clearPublicTokenCookie(\n cookieStore: Awaited<ReturnType<typeof cookies>>,\n ) {\n // Clear legacy _tp cookie if present\n if (cookieStore.get(cn.tokenPub)?.value) {\n cookieStore.set(cn.tokenPub, \"\", { httpOnly: false, maxAge: 0, path: \"/\" });\n }\n }\n\n async function saveAccountToList(tokens: SessionTokens) {\n const account = parseAccountFromJwt(tokens);\n if (!account) return;\n\n const cookieStore = await cookies();\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n const count = await getCount();\n\n // Find existing slot for this account id\n let targetSlot = 0;\n for (let i = 1; i <= count; i++) {\n const existing = readSlot(cookieStore, i);\n if (existing?.id === account.id) {\n targetSlot = i;\n break;\n }\n }\n\n if (targetSlot === 0) {\n if (count >= MAX_ACCOUNTS) return;\n targetSlot = count + 1;\n cookieStore.set(cn.count, String(targetSlot), opts);\n }\n\n writeSlot(cookieStore, targetSlot, account);\n cookieStore.set(cn.active, String(targetSlot), opts);\n clearPublicTokenCookie(cookieStore);\n }\n\n // Alias for backwards compat\n const setSessionCookies = saveAccountToList;\n\n async function switchAccount(accountId: string): Promise<boolean> {\n const [cookieStore, count] = await Promise.all([cookies(), getCount()]);\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n\n for (let i = 1; i <= count; i++) {\n const slot = readSlot(cookieStore, i);\n if (slot && (slot.id === accountId || slot.sessionId === accountId)) {\n cookieStore.set(cn.active, String(i), opts);\n clearPublicTokenCookie(cookieStore);\n return true;\n }\n }\n return false;\n }\n\n async function removeActiveAccount() {\n const [cookieStore, activeIdx, count] = await Promise.all([cookies(), getActiveIndex(), getCount()]);\n const opts = { ...getCookieOptions(config), maxAge: 60 * 60 * 24 * 30 };\n const clear = { ...getCookieOptions(config), maxAge: 0 };\n\n if (count === 0) return;\n\n const remaining: StoredAccount[] = [];\n for (let i = 1; i <= count; i++) {\n if (i === activeIdx) continue;\n const slot = readSlot(cookieStore, i);\n if (slot) remaining.push(slot);\n }\n\n for (let i = 1; i <= count; i++) {\n clearSlot(cookieStore, i);\n }\n\n if (remaining.length === 0) {\n cookieStore.set(cn.count, \"0\", clear);\n cookieStore.set(cn.active, \"0\", clear);\n await clearPublicTokenCookie(cookieStore);\n return;\n }\n\n // Re-compact remaining accounts into slots 1..n\n for (let i = 0; i < remaining.length; i++) {\n await writeSlot(cookieStore, i + 1, remaining[i]!);\n }\n cookieStore.set(cn.count, String(remaining.length), opts);\n cookieStore.set(cn.active, \"1\", opts);\n clearPublicTokenCookie(cookieStore);\n }\n\n async function clearAllSessionCookies() {\n const [cookieStore, count] = await Promise.all([cookies(), getCount()]);\n const clear = { ...getCookieOptions(config), maxAge: 0 };\n for (let i = 1; i <= count; i++) {\n clearSlot(cookieStore, i);\n }\n cookieStore.set(cn.count, \"0\", clear);\n cookieStore.set(cn.active, \"0\", clear);\n clearPublicTokenCookie(cookieStore);\n }\n\n async function tryRefreshTokens(): Promise<string | null> {\n const refreshToken = await getRefreshToken();\n if (!refreshToken || !config.clientId) return null;\n\n const basicAuth = Buffer.from(`${config.clientId}:${config.clientSecret ?? \"\"}`).toString(\"base64\");\n\n const response = await fetch(createUrl(config.issuer, \"/auth/token\"), {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n authorization: `Basic ${basicAuth}`,\n },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: refreshToken,\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) return null;\n\n const data = (await response.json().catch(() => null)) as TokenLikeResponse | null;\n if (!data) return null;\n\n const tokens = tokenFromResponse(data);\n if (!tokens.accessToken) return null;\n\n await saveAccountToList(tokens);\n return tokens.accessToken;\n }\n\n async function apiRequest<T>(path: string, init: RequestInit = {}): Promise<T> {\n const accessToken = await getAccessToken();\n const requestHeaders = new Headers(init.headers);\n\n if (accessToken) requestHeaders.set(\"authorization\", `Bearer ${accessToken}`);\n if (init.body !== undefined && !requestHeaders.has(\"content-type\")) {\n requestHeaders.set(\"content-type\", \"application/json\");\n }\n\n const url = new URL(createUrl(config.issuer, path));\n applyClientCredentials(url, config);\n\n const response = await fetch(url, {\n ...init,\n headers: requestHeaders,\n cache: \"no-store\",\n });\n\n if (response.status === 401) {\n const newAccessToken = await tryRefreshTokens();\n\n if (!newAccessToken) {\n // Sem renovar depois de um 401, a sessão acabou: expirou, foi revogada\n // no painel ou o refresh token caiu. Os cookies apontam para algo que\n // não existe mais, então saem — senão toda requisição seguinte repete\n // o mesmo ciclo. Quem chamou recebe um erro que dá para tratar, em vez\n // de \"Auth API error 401\" vindo do fundo da pilha.\n await clearAllSessionCookies().catch(() => {});\n throw new GeekappsSessionExpiredError();\n }\n\n if (newAccessToken) {\n const retryHeaders = new Headers(init.headers);\n retryHeaders.set(\"authorization\", `Bearer ${newAccessToken}`);\n if (init.body !== undefined && !retryHeaders.has(\"content-type\")) {\n retryHeaders.set(\"content-type\", \"application/json\");\n }\n const retryUrl = new URL(createUrl(config.issuer, path));\n applyClientCredentials(retryUrl, config);\n const retryResponse = await fetch(retryUrl, {\n ...init,\n headers: retryHeaders,\n cache: \"no-store\",\n });\n if (!retryResponse.ok) {\n const error = await retryResponse.json().catch(() => null);\n throw new Error(error?.error_description ?? error?.error ?? error?.message ?? `Auth API error ${retryResponse.status}`);\n }\n if (retryResponse.status === 204) return null as T;\n return (await retryResponse.json()) as T;\n }\n }\n\n if (!response.ok) {\n const error = await response.json().catch(() => null);\n throw new Error(error?.error_description ?? error?.error ?? error?.message ?? `Auth API error ${response.status}`);\n }\n\n if (response.status === 204) return null as T;\n return (await response.json()) as T;\n }\n\n function createApiClient(): ServerAuthApiClient {\n return {\n get: (path) => apiRequest(path),\n post: (path, body) => apiRequest(path, { method: \"POST\", body: body === undefined ? undefined : JSON.stringify(body) }),\n patch: (path, body) => apiRequest(path, { method: \"PATCH\", body: body === undefined ? undefined : JSON.stringify(body) }),\n put: (path, body) => apiRequest(path, { method: \"PUT\", body: body === undefined ? undefined : JSON.stringify(body) }),\n delete: (path) => apiRequest(path, { method: \"DELETE\" }),\n };\n }\n\n async function requireUser(options: { redirectTo?: string } = {}) {\n const accessToken = await getAccessToken();\n if (!accessToken) {\n redirect(options.redirectTo ?? \"/\");\n }\n return accessToken;\n }\n\n function escapeHtml(str: string): string {\n return str.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\");\n }\n\n function sanitizeRedirectTo(value: string | null | undefined): string {\n const raw = value ?? \"/\";\n // Never redirect back into the auth basePath — that would loop or replay a stale code.\n if (raw.startsWith(config.basePath)) return \"/\";\n // Only allow relative paths to prevent open-redirect.\n if (raw.startsWith(\"/\") && !raw.startsWith(\"//\")) return raw;\n return \"/\";\n }\n\n async function createAuthorizeRedirect(request: NextRequest, mode: \"login\" | \"register\" | \"add-account\" | \"google\") {\n const redirectTo = sanitizeRedirectTo(request.nextUrl.searchParams.get(\"redirectTo\") ?? config.afterSignInRedirectTo);\n const flowId = request.nextUrl.searchParams.get(\"flow_id\");\n const url = new URL(createUrl(config.issuer, mode === \"google\" ? \"/auth/google\" : \"/authorize\"));\n\n if (!config.clientId) {\n return NextResponse.json(\n { error: \"missing_client_id\", message: \"Missing GEEKAPPS_AUTH_CLIENT_ID or clientId.\" },\n { status: 500 },\n );\n }\n\n url.searchParams.set(\"client_id\", config.clientId);\n url.searchParams.set(\"redirect_uri\", resolveRedirectUri(config, request));\n url.searchParams.set(\"response_type\", \"code\");\n const scopes = config.scopes ?? [\"openid\", \"profile\", \"email\"];\n if (!scopes.includes(\"offline_access\")) scopes.push(\"offline_access\");\n url.searchParams.set(\"scope\", scopes.join(\" \"));\n url.searchParams.set(\"state\", Buffer.from(JSON.stringify({ redirectTo, mode })).toString(\"base64url\"));\n if (mode === \"register\") url.searchParams.set(\"screen_hint\", \"signup\");\n if (mode === \"add-account\") {\n // Adding an account always needs a fresh login, regardless of any existing session.\n url.searchParams.set(\"prompt\", \"login\");\n } else {\n // `prompt` (login | select_account | none | consent) is forwarded as-is to\n // the IDP — see OidcPrompt in client.tsx for what each value does.\n const prompt = request.nextUrl.searchParams.get(\"prompt\");\n // Legacy fallback: silentLogin=false is equivalent to prompt=login.\n const silentLogin = request.nextUrl.searchParams.get(\"silentLogin\");\n const resolvedPrompt = prompt ?? (silentLogin === \"false\" ? \"login\" : null);\n if (resolvedPrompt) url.searchParams.set(\"prompt\", resolvedPrompt);\n }\n if (flowId) url.searchParams.set(\"flow_id\", flowId);\n\n const codeVerifier = generateCodeVerifier();\n url.searchParams.set(\"code_challenge\", createCodeChallenge(codeVerifier));\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n const response = NextResponse.redirect(url);\n const cn = getCookieNames(config.cookiePrefix);\n response.cookies.set(cn.pkceVerifier, codeVerifier, {\n ...getCookieOptions(config),\n maxAge: 60 * 10,\n });\n return response;\n }\n\n async function exchangeCode(request: NextRequest) {\n const code = request.nextUrl.searchParams.get(\"code\");\n const state = request.nextUrl.searchParams.get(\"state\");\n\n const origin = requestOrigin(request);\n\n if (!code) {\n const err = request.nextUrl.searchParams.get(\"error\") ?? \"missing_code\";\n const desc = request.nextUrl.searchParams.get(\"error_description\") ?? request.nextUrl.searchParams.get(\"error_message\") ?? \"No authorization code received\";\n return NextResponse.redirect(new URL(`${config.basePath}/callback?error=${encodeURIComponent(err)}&error_description=${encodeURIComponent(desc)}`, origin));\n }\n\n if (!config.clientId) {\n return NextResponse.redirect(new URL(`${config.basePath}/callback?error=missing_client_id&error_description=Auth+client+is+not+configured`, origin));\n }\n\n const basicAuth = Buffer.from(\n `${config.clientId}:${config.clientSecret ?? \"\"}`,\n ).toString(\"base64\");\n\n const cn = getCookieNames(config.cookiePrefix);\n const cookieStore = await cookies();\n const codeVerifier = cookieStore.get(cn.pkceVerifier)?.value;\n cookieStore.set(cn.pkceVerifier, \"\", { ...getCookieOptions(config), maxAge: 0 });\n\n const tokenBody = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: resolveRedirectUri(config, request),\n });\n if (codeVerifier) tokenBody.set(\"code_verifier\", codeVerifier);\n\n const response = await fetch(createUrl(config.issuer, \"/auth/token\"), {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/x-www-form-urlencoded\",\n authorization: `Basic ${basicAuth}`,\n },\n body: tokenBody,\n cache: \"no-store\",\n });\n\n const data = (await response.json().catch(() => ({}))) as TokenLikeResponse & { error?: string; error_description?: string };\n if (!response.ok) {\n const error = encodeURIComponent((data.error as string | undefined) ?? \"token_exchange_failed\");\n const desc = encodeURIComponent((data.error_description as string | undefined) ?? `Token exchange failed with status ${response.status}`);\n return NextResponse.redirect(new URL(`${config.basePath}/callback?error=${error}&error_description=${desc}`, origin));\n }\n\n await saveAccountToList(tokenFromResponse(data));\n\n let redirectTo = sanitizeRedirectTo(config.afterSignInRedirectTo);\n if (state) {\n try {\n const parsed = JSON.parse(Buffer.from(state, \"base64url\").toString(\"utf8\")) as { redirectTo?: string };\n redirectTo = sanitizeRedirectTo(parsed.redirectTo);\n } catch {\n // ignore malformed state\n }\n }\n\n return NextResponse.redirect(new URL(redirectTo, origin));\n }\n\n function mapLocalPathToApiPath(route: string) {\n if (route === \"/me\") return \"/auth/me\";\n if (route === \"/accounts/switch\") return \"/auth/accounts/switch\";\n if (route === \"/organizations/active\") return \"/auth/organizations/active\";\n if (route === \"/permissions/check\") return \"/auth/permissions/check\";\n if (route === \"/login/password\") return \"/auth/login/password\";\n if (route === \"/register/password\") return \"/auth/register/password\";\n if (route === \"/passwordless/link\") return \"/auth/passwordless/link\";\n return route;\n }\n\n async function handleAccountsLocal(): Promise<NextResponse> {\n const [accounts, activeIdx] = await Promise.all([getAccountsList(), getActiveIndex()]);\n\n return NextResponse.json({\n accounts: accounts.map((a, i) => ({\n id: a.id,\n sessionId: a.sessionId ?? a.id,\n isActive: i + 1 === activeIdx,\n user: {\n id: a.user.sub,\n name: a.user.name ?? null,\n email: a.user.email ?? null,\n imageUrl: a.user.picture ?? null,\n phone: a.user.phone ?? null,\n },\n })),\n });\n }\n\n async function handleOrganizationsLocal(): Promise<NextResponse> {\n const cookieStore = await cookies();\n const activeOrgId = cookieStore.get(cn.activeOrganizationId)?.value ?? null;\n try {\n const data = await apiRequest<unknown[]|{ organizations: unknown[] }>(\"/organizations\");\n const organizations = Array.isArray(data) ? data : (data as { organizations: unknown[] }).organizations;\n return NextResponse.json({ organizations, currentOrgId: activeOrgId });\n } catch {\n return NextResponse.json({ organizations: [], currentOrgId: activeOrgId });\n }\n }\n\n async function handleSwitchAccountLocal(request: NextRequest): Promise<NextResponse> {\n const body = await readBody(request);\n const targetId =\n body && typeof body === \"object\"\n ? String(\n (body as Record<string, unknown>).accountId ??\n (body as Record<string, unknown>).sessionId ??\n \"\",\n )\n : \"\";\n\n if (!targetId) {\n return NextResponse.json({ error: \"accountId required\" }, { status: 400 });\n }\n\n const switched = await switchAccount(targetId);\n if (!switched) {\n return NextResponse.json({ error: \"Account not found\" }, { status: 404 });\n }\n\n return NextResponse.json({ ok: true });\n }\n\n async function proxy(request: NextRequest, route: string) {\n const accessToken = await getAccessToken();\n const body = [\"GET\", \"HEAD\"].includes(request.method) ? undefined : await readBody(request);\n const url = new URL(appendSearchParams(createUrl(config.issuer, mapLocalPathToApiPath(route)), request));\n applyClientCredentials(url, config);\n const requestHeaders = new Headers();\n\n if (accessToken) requestHeaders.set(\"authorization\", `Bearer ${accessToken}`);\n if (body !== undefined) requestHeaders.set(\"content-type\", \"application/json\");\n\n let response = await fetch(url, {\n method: request.method,\n headers: requestHeaders,\n body: body === undefined ? undefined : typeof body === \"string\" ? body : JSON.stringify(body),\n cache: \"no-store\",\n });\n\n if (response.status === 401) {\n // Mesmo tratamento do apiRequest: tenta renovar uma vez e, se a sessão\n // já não existe (expirada ou revogada no painel), limpa os cookies. Sem\n // isso o cliente repetiria o mesmo token morto a cada chamada.\n const refreshed = await tryRefreshTokens();\n\n if (refreshed) {\n requestHeaders.set(\"authorization\", `Bearer ${refreshed}`);\n response = await fetch(url, {\n method: request.method,\n headers: requestHeaders,\n body:\n body === undefined\n ? undefined\n : typeof body === \"string\"\n ? body\n : JSON.stringify(body),\n cache: \"no-store\",\n });\n } else {\n await clearAllSessionCookies().catch(() => {});\n return NextResponse.json(\n { error: \"session_expired\" },\n { status: 401 },\n );\n }\n }\n\n const data = isJsonResponse(response) ? ((await response.json().catch(() => null)) as TokenLikeResponse | null) : null;\n if (data) {\n const tokens = tokenFromResponse(data);\n if (tokens.accessToken || tokens.refreshToken || tokens.idToken || tokens.sessionId) {\n await saveAccountToList(tokens);\n }\n return NextResponse.json(data, { status: response.status });\n }\n\n return responseFromApi(response);\n }\n\n async function handle(request: NextRequest) {\n const route = routeFromRequest(request, config.basePath);\n\n if (request.method === \"GET\" && route === \"/sign-in\") return createAuthorizeRedirect(request, \"login\");\n if (request.method === \"GET\" && route === \"/sign-up\") return createAuthorizeRedirect(request, \"register\");\n if (request.method === \"GET\" && route === \"/add-account\") return createAuthorizeRedirect(request, \"add-account\");\n if (request.method === \"GET\" && route === \"/login/google\") return createAuthorizeRedirect(request, \"google\");\n if (request.method === \"GET\" && route === \"/callback\") {\n const error = request.nextUrl.searchParams.get(\"error\");\n if (error) {\n const description = request.nextUrl.searchParams.get(\"error_description\") ?? request.nextUrl.searchParams.get(\"error_message\") ?? \"An authentication error occurred.\";\n return new NextResponse(\n `<!doctype html><html><head><meta charset=\"utf-8\"><title>Authentication Error</title></head><body style=\"font-family:sans-serif;max-width:480px;margin:80px auto;padding:0 16px\"><h2>Authentication Error</h2><p><strong>${escapeHtml(error)}</strong></p><p>${escapeHtml(description)}</p><a href=\"/\">Go back</a></body></html>`,\n { status: 400, headers: { \"content-type\": \"text/html; charset=utf-8\" } },\n );\n }\n return exchangeCode(request);\n }\n if (request.method === \"GET\" && route === \"/token\") {\n const accessToken = await getAccessToken();\n if (!accessToken) return NextResponse.json({ error: \"missing_token\" }, { status: 401 });\n return NextResponse.json({ accessToken });\n }\n\n\n if (request.method === \"GET\" && route === \"/accounts\") return handleAccountsLocal();\n if (request.method === \"POST\" && route === \"/accounts/switch\") return handleSwitchAccountLocal(request);\n if (request.method === \"GET\" && route === \"/organizations\") return handleOrganizationsLocal();\n\n if (request.method === \"POST\" && route === \"/organizations\") {\n const accessToken = await getAccessToken();\n const body = (await readBody(request)) as Record<string, unknown> | undefined;\n if (body && accessToken && !body.applicationId) {\n const claims = decodeJwtPayload(accessToken);\n const applicationId =\n (typeof claims?.application_id === \"string\" ? claims.application_id : null) ??\n (typeof claims?.client_id === \"string\" ? claims.client_id : null) ??\n (typeof claims?.applicationId === \"string\" ? claims.applicationId : null);\n if (applicationId) body.applicationId = applicationId;\n }\n const orgUrl = new URL(createUrl(config.issuer, \"/organizations\"));\n applyClientCredentials(orgUrl, config);\n const requestHeaders = new Headers();\n if (accessToken) requestHeaders.set(\"authorization\", `Bearer ${accessToken}`);\n if (body !== undefined) requestHeaders.set(\"content-type\", \"application/json\");\n const response = await fetch(orgUrl, {\n method: \"POST\",\n headers: requestHeaders,\n body: JSON.stringify(body),\n cache: \"no-store\",\n });\n return responseFromApi(response);\n }\n\n if (request.method === \"POST\" && route === \"/sign-out\") {\n await apiRequest(\"/auth/sign-out\", { method: \"POST\" }).catch(() => null);\n await removeActiveAccount();\n return NextResponse.json({ ok: true });\n }\n\n if (request.method === \"POST\" && route === \"/sign-out-all\") {\n await apiRequest(\"/auth/sign-out-all\", { method: \"POST\" }).catch(() => null);\n await clearAllSessionCookies();\n return NextResponse.json({ ok: true });\n }\n\n if (request.method === \"POST\" && route === \"/organizations/active\") {\n const body = await readBody(request);\n const organizationId =\n body && typeof body === \"object\" && \"organizationId\" in body\n ? (body as Record<string, unknown>).organizationId\n : null;\n const response = NextResponse.json({ ok: true });\n if (typeof organizationId === \"string\") {\n const cookieOpts = {\n httpOnly: true,\n sameSite: \"lax\" as const,\n path: \"/\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n };\n response.cookies.set(cn.activeOrganizationId, organizationId, cookieOpts);\n }\n return response;\n }\n\n return proxy(request, route);\n }\n\n return {\n handlers: {\n GET: handle,\n POST: handle,\n PATCH: handle,\n DELETE: handle,\n },\n GetSession: getSession,\n GetUser: getUser,\n GetUserById: getUserById,\n GetOrganizations: getOrganizations,\n SaveSession: saveAccountToList,\n GetAccessToken: getAccessToken,\n GetRefreshToken: getRefreshToken,\n IsAuthenticated: async () => (await getAccessToken()) !== null,\n TryRefreshTokens: tryRefreshTokens,\n RequireUser: requireUser,\n CreateAuthApiClient: createApiClient,\n cookiePrefix: config.cookiePrefix,\n VerifyToken: (token: string) => verifyToken(token, config.issuer),\n SignInUrl: async (redirectTo?: string) => {\n const configured = env(\"GEEKAPPS_APP_URL\");\n if (!configured) throw new Error(\"Cannot determine app origin. Set GEEKAPPS_APP_URL.\");\n const origin = configured.replace(/\\/$/, \"\");\n const url = new URL(`${origin}${config.basePath}/sign-in`);\n if (redirectTo) url.searchParams.set(\"redirectTo\", redirectTo);\n return url.toString();\n },\n };\n}\n\nexport function handlers(options?: GeekappsAuthConfig) {\n return configureGeekappsAuth(options).handlers;\n}\n\n/**\n * Returns true if the current request has a valid access token in cookies.\n * Safe to call in Server Components, Server Actions, and Route Handlers.\n */\nexport async function isAuthenticated(options?: GeekappsAuthConfig): Promise<boolean> {\n const { GetAccessToken } = configureGeekappsAuth(options);\n return (await GetAccessToken()) !== null;\n}\n"],"mappings":"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","names":["createHash","randomBytes","cookies","redirect","cn","env","randomBytes","cookies","createHash","redirect"]}