Ao final deste guia, sua função rejeitará requisições sem um token válido.
Quick start
Ative a autenticação na sua função
import { define , z } from "@jelou/functions" ;
export default define ({
description: "Protected API" ,
input: z . object ({ query: z . string () }) ,
auth: true ,
handler : async ( input , ctx ) => {
return { results: [], authenticated: ctx . auth ?. authenticated };
} ,
}) ;
Configure o secret
jelou secrets set my-function AUTH_SECRET=my-secret-token
Quando você usa auth: true, a plataforma procura automaticamente um secret chamado AUTH_SECRET.
Faça a chamada com o token
curl -X POST https://my-function.fn.jelou.ai \
-H "Authorization: Bearer my-secret-token" \
-H "Content-Type: application/json" \
-d '{"query": "test"}'
Resposta com sucesso: { "results" : [], "authenticated" : true }
Sem token ou com token incorreto: { "error" : "Unauthorized" }
Variantes de auth
Valor Comportamento trueProcura o secret AUTH_SECRET. Rejeita com 401 se ausente ou incorreto. falseSem autenticação (valor padrão). { secret: "API_TOKEN" }Procura um secret com esse nome específico. { secret: ["API_TOKEN", "API_TOKEN_OLD"] }Aceita qualquer um dos secrets (útil para rotação de chaves). { secret: "API_TOKEN", required: false }Auth opcional — nunca retorna 401.
ctx.auth
Resultado da verificação de autenticação disponível dentro do handler.
Campo Tipo Descrição ctx.authAuthResult | nullnull quando auth não está ativa ou é opcional sem tokenctx.auth.authenticatedbooleantrue se o token foi verificado
Cenário Resultado Token válido Handler executa, ctx.auth = { authenticated: true } Token inválido ou ausente 401 Unauthorized + header WWW-Authenticate: BearerSecret não configurado no env Falha com 500 (nunca permite acesso se o secret não existir) Trigger cron Auth é ignorada — crons têm sua própria assinatura criptográfica Token > 4 KB Rejeitado com 401
Fail-closed : se você esquecer de configurar o secret com jelou secrets set, a plataforma retorna 500 em vez de permitir acesso. Isso é intencional — nunca degrada para “sem auth”.
Rotação de chaves
Aceite o token antigo e o novo simultaneamente durante a migração:
export default define ({
description: "API with key rotation" ,
input: z . object ({ id: z . string () }) ,
auth: { secret: [ "API_TOKEN" , "API_TOKEN_OLD" ] } ,
handler : async ( input , ctx ) => {
return { id: input . id };
} ,
}) ;
jelou secrets set my-function API_TOKEN=new-token-v2
jelou secrets set my-function API_TOKEN_OLD=previous-token-v1
Assim que todos os clientes usarem o novo token, remova API_TOKEN_OLD do array e do secret.
Auth opcional
Endpoints públicos com acesso premium opcional:
export default define ({
description: "Catalog with optional premium pricing" ,
input: z . object ({ category: z . string () }) ,
auth: { secret: "API_TOKEN" , required: false } ,
handler : async ( input , ctx ) => {
const products = await searchProducts ( input . category );
if ( ctx . auth ?. authenticated ) {
return { products , prices: await wholesalePrices ( products ) };
}
return { products };
} ,
}) ;
Com required: false:
Token válido → ctx.auth = { authenticated: true }
Sem token → ctx.auth = null, handler executa normalmente
Token inválido → ctx.auth = null (não retorna 401)
Auth em app()
Auth global
import { app , define , z } from "@jelou/functions" ;
export default app ({
config: { auth: { secret: "API_TOKEN" } } ,
tools: {
search: define ({
description: "Search records" ,
input: z . object ({ q: z . string () }),
handler : async ( input ) => ({ results: [] }),
}),
create: define ({
description: "Create record" ,
input: z . object ({ name: z . string () }),
handler : async ( input ) => ({ id: "abc-123" }),
}),
} ,
}) ;
Todas as ferramentas herdam a auth global.
Auth por ferramenta + opt-out
export default app ({
config: { auth: { secret: "API_TOKEN" } } ,
tools: {
healthCheck: define ({
description: "Public health check" ,
input: z . object ({}),
auth: false ,
handler : async () => ({ status: "ok" }),
}),
admin: define ({
description: "Admin operation" ,
input: z . object ({ action: z . string () }),
auth: { secret: "ADMIN_TOKEN" },
handler : async ( input ) => ({ done: true }),
}),
} ,
}) ;
Ferramenta Auth healthCheckSem auth (auth: false sobrescreve o global) adminUsa ADMIN_TOKEN em vez do global
Bypass de cron : triggers de cron nunca passam pela auth. Se sua função usa isCron, verifique a lógica de negócio internamente.
Nunca codifique secrets no código. Sempre use jelou secrets set.
Fail-closed : um secret ausente causa 500, não acesso aberto.
Testes
import { assertEquals } from "jsr:@std/assert" ;
import {
createMockAuthContext ,
createMockAuthRequest ,
createMockContext ,
createMockRequest ,
} from "@jelou/functions/testing" ;
Deno . test ( "handler receives auth when token is valid" , async () => {
const ctx = createMockAuthContext ();
const req = createMockAuthRequest ( "my-secret-token" , { query: "test" });
const result = await fn . handler ({ query: "test" }, ctx , req );
assertEquals ( result . authenticated , true );
});
Deno . test ( "handler without auth returns ctx.auth null" , async () => {
const ctx = createMockContext ({ auth: null });
const req = createMockRequest ({ query: "test" });
const result = await fn . handler ({ query: "test" }, ctx , req );
assertEquals ( result . authenticated , undefined );
});
createMockAuthContext() Referência completa para mocks de autenticação.