RhizzaDocs

Emissão de token no backend

Troque a credencial da integração por acesso curto, mínimo e vinculado ao usuário do seu host.

Abrir como Markdown

A credencial nunca atravessa a fronteira

createReportPlatformClient é server-only. A troca usa autenticação Basic entre servidores e a rota de emissão não aceita CORS de navegador. Entregue ao cliente somente accessToken, tokenType e expiresIn.

app/api/rhizzadocs/token/route.ts
import "server-only"

import { createReportPlatformClient } from "@rhizzalab/report-node"
import { NextResponse } from "next/server"

import { requireAuthenticatedUser } from "@/lib/auth"

export const runtime = "nodejs"

function requiredEnv(name: string): string {
  const value = process.env[name]
  if (!value) throw new Error("Variável ausente: " + name)
  return value
}

const reports = createReportPlatformClient({
  clientId: requiredEnv("RHIZZADOCS_CLIENT_ID"),
  clientSecret: requiredEnv("RHIZZADOCS_CLIENT_SECRET"),
  apiBaseUrl: process.env.RHIZZADOCS_API_URL,
})

export async function POST(request: Request) {
  // Esta função pertence ao seu host: valide a sessão antes da troca.
  const user = await requireAuthenticatedUser(request)

  const token = await reports.issueEditorToken({
    userId: user.id,
    workspaceId: user.companyId,
    reports: [
      {
        reportType: "acme.relatorio-mensal",
        scopes: ["editor:read", "templates:read", "export:pdf"],
      },
    ],
  })

  return NextResponse.json(token)
}

Derive identidade e acesso no host

  • userId: id estável do usuário autenticado no seu sistema, entre 1 e 255 caracteres.
  • workspaceId: contexto opcional do host, também entre 1 e 255 caracteres; não é autorização.
  • reports: lista não vazia de pares reportType + scopes.
  • scopes: somente capacidades que a tela realmente precisa naquele momento.

Renove sem refresh token

O token dura 10 minutos por padrão e nunca pode exceder 15 minutos. Quando o editor sinalizar AUTH_REQUIRED, chame novamente a sua rota autenticada e substitua o JWT em memória.

Se a sessão do próprio host expirou, não tente renovar em loop. Redirecione o usuário para o login do host e preserve a explicação de que a autenticação principal terminou.

Trate os erros do Node SDK

kindSignificadoAção típica
validationPedido inválido antes da redeCorrigir o mapeamento do host
apiAPI respondeu fora de 2xxUsar status, code, requestId e issues
networkTimeout, DNS, TLS ou fetch rejeitadoAplicar retry limitado e observabilidade
contractResposta 2xx fora do contratoInterromper e investigar incompatibilidade
ts
import { isReportNodeError } from "@rhizzalab/report-node"

try {
  return await reports.issueEditorToken(request)
} catch (error) {
  if (isReportNodeError(error)) {
    logger.warn({
      kind: error.kind,
      code: error.code,
      status: error.status,
      requestId: error.requestId,
    })
  }
  throw error
}