Autentique requisições com Functions
Proteja um bucket do Object Storage com uma função que valida um JSON Web Token e entrega o objeto somente a uma requisição autorizada.
Você pode colocar uma função na frente de um bucket do Object Storage, para que a função valide um JSON Web Token antes que qualquer objeto saia do bucket.
Uma requisição que carrega um token válido recebe o objeto com o seu content type. Toda outra requisição recebe HTTP 401 e o bucket nunca é lido. Um bucket que não precisa de token é servido por um connector e por uma regra do Rules Engine, o que Use um bucket como origem de uma aplicação cobre.
Pré-requisitos
- Uma conta Azion.
- A Azion CLI instalada e autorizada.
- Node.js versão 18 ou superior.
- Um bucket que guarda os objetos a proteger, com Workloads Access definido como Read Only ou Read & Write. Um bucket definido como Restricted não é lido por Azion Runtime, então a função não alcança nada nele. Consulte Criar um bucket.
- Um secret de assinatura para os tokens que a sua aplicação emite.
Como a verificação funciona
A função responde às requisições que uma regra roteia para ela. Ela lê o token do header Authorization ou do cookie auth_token, verifica a assinatura contra o secret compartilhado e chama Object Storage somente depois que a assinatura confere. Um bucket também é alcançável pelo endpoint S3 e por um connector, e nenhum desses caminhos pede um token; a função protege o caminho em que ela está.
O fluxo abaixo mostra as duas recusas e a única rota que alcança o bucket:
Crie o projeto da função
A Azion CLI cria a estrutura do projeto e o npm adiciona a biblioteca que verifica o token. Para configurar o projeto:
Nos prompts, defina Template como JavaScript e Runtime como Azion Runtime. A Azion CLI escreve o projeto em uma pasta my-auth-storage.
A biblioteca jose verifica JSON Web Tokens em runtimes JavaScript. O npm a adiciona ao package.json.
A pasta do projeto guarda o código do template e a dependência jose.
Escreva o handler
Abra o arquivo JavaScript principal do projeto e substitua o conteúdo dele por este handler:
Seis decisões estão no código:
- A key do objeto é o caminho da requisição com
/files/removido, então/files/image.pnglê a keyimage.png. Uma requisição que deixa a key vazia retorna400com o corpo{"error": "Object key required"}. - Uma requisição sem token retorna
401, carrega o headerWWW-Authenticate: Bearere nomeia os dois lugares aceitos no seu campomessage. - Um token que o secret não verifica retorna
401com o corpo{"error": "Invalid token"}e a mensagem quejoselevantou. - Um token verificado lê o objeto e o retorna com o content type que Object Storage armazenou, ou
application/octet-streamquando o objeto não carrega nenhum.Cache-Control: private, max-age=3600mantém a resposta fora de um cache compartilhado. - Uma key que não está no bucket retorna
404com o corpo{"error": "Object not found"}. Toda outra falha de armazenamento retorna500. console.errorescreveJWT verification failed:eStorage error:, e as duas linhas chegam aos logs da função.
O handler lê JWT_SECRET e BUCKET_NAME com Azion.env.get, então nenhum dos dois valores é escrito no código.
Configure as variáveis de ambiente
Crie um arquivo .env na raiz do projeto, com o bucket que o handler lê e o secret contra o qual ele verifica:
Configure o storage local para desenvolvimento
Azion Runtime responde a uma chamada local ao Object Storage a partir de uma pasta na sua máquina. Adicione um bloco storage ao azion.config para que storage.get resolva enquanto você desenvolve:
Substitua your-bucket-name, your-bucket-prefix e ./path/to/storage/files pelos valores do seu projeto. workloadsAccess é a grafia em camelCase que o arquivo de configuração usa para o nível de acesso do bucket, e read_only é suficiente para um handler que apenas lê.
Faça o deploy da função
O deploy envia o código e azion sync envia os valores que o código lê. Para colocar os dois na sua conta:
A Azion CLI faz o build do projeto e envia a função para a sua conta.
O handler lê BUCKET_NAME e JWT_SECRET em tempo de execução. Sem este passo, as variáveis existem apenas no seu arquivo .env e a função não as encontra.
A função roda na sua conta com o nome do bucket e o secret de assinatura de que ela precisa.
Verifique a configuração
Assine um token com o mesmo secret, depois requisite um objeto três vezes: com o header, com o cookie e sem nenhum dos dois. Para verificar a função:
Salve o script como sign-token.mjs na pasta do projeto, para que o Node.js o leia como um módulo, e rode com node sign-token.mjs:
O script imprime o token assinado. Defina secret com o valor que você armazenou em JWT_SECRET, ou a função recusa todo token que o script emite.
A resposta carrega o objeto e o content type que Object Storage armazenou para ele.
A resposta é a mesma, o que confirma o fallback do cookie.
A função recusa a requisição com HTTP 401:
Um token assinado retorna o objeto, e um token ausente ou não verificável retorna 401 sem alcançar o bucket.