Executando verificação de segurança...
1

[Dúvida] Cuidados para tomar com uma API Rest

Olá turma, sou desenvolvedor iOS a alguns anos. Esse ano resolvi estudar um pouco de backend para implementar uma API e poder lançar um produto de fato, de ponta a ponta.

Acabei decidindo por usar Node, TS, Express, Prisma, Jest, Docker, S3, e, futuramente, fazer o deploy na AWS. Pesquisei muito por boas práticas de uma API porém ainda sigo com algumas dúvidas em relação a segurança.

Dei uma olhada no projeto do tabnews porém gostaria de dicas para desempenho e segurança da minha API. Também, aceito sugestões de tutorias para deploy na AWS.

Obrigado desde já.

Carregando publicação patrocinada...
1

Eu sou dev PHP, e já montei várias APIs usando Laravel. Mas não vou falar de linguagem ou tecnologia, apenas de conceito.

Uma coisa que é bem importante e eu não consigo desenvolver uma API sem isso, é autenticação por tokens JWT. Se você tiver funcionalidades restritas na sua API (ex.: gerenciamento de usuários), um jeito simples de fazer autenticação e validação dos usuários é com tokens JWT. Dá uma pesquisada sobre isso, é bem simples de entender, usar e implementar. E, com certeza, deve ter algum pacote pronto pra usar no Express (se já não tiver algo nativo rs).

Outra boa prática é se atentar bem aos códigos de status de retorno (200, 201, 400, 404, 422, 500 etc) para as respostas das chamadas na sua API, e também aos métodos usados para fazer as chamadas (GET, POST, PUT, PATCH e DELETE). Com esses dois "recursos" bem implementados, a validação dos retornos no front-end vai ser muito simples (e bonita), e documentações (seja uma collection no Postman ou uma interface com Swagger) vão ser bem mais simples de entender.

Espero que tenha contribuído com alguma coisa :)

1

Com certeza contribuiu algo. Sim, estou usando jwt para autenticação. Trazendo um exemplo:

Tenho uma rota DELETE /users/{userID}, a melhor forma de garantir que o usuário só pode deletar ele mesmo é checar o id do jwt com o id recebido como parametro?

Sobre os retornos, sim estou prezando bastante pelos códigos corretos. Retornar erro com 200 é triste kkkkkkkkk Acharia uma boa ter um padrão de retornar sempre no JSON a mensagem, o status (código), e o dado (data) ou somente retornar status e mensagem em caso de erro?

1

Sempre aconselhável fazer uma função handler de response. Eu curto sempre usar o HATEOAS para tornar a RESTful de fato... Pesquisa sobre error handler left/right, muito bom para os retornos e tratamentos de exceções.

1

eu gosto de retornar o código do status da requisição, para facilitar na chamada no front, e em algums tipos de requisição, como um post, gosto de retornar um json com um retorno, nem que seja um OK

1

Eu vejo em muitos lugares o retorno da própria entidade em caso de sucesso, inclusive já desenvolvi assim, mas nunca achei um consenso na comunidade sobre esse caso, qual a sua opinião?

1

Sobre o DELETE, eu faria exatamente como você mencionou, comparando o ID do usuário do JWT com o ID enviado na URL. Já vi pessoas com receio desse tipo de comparação por conta do JWT ser "visível" para o usuário (não diretamente, mas um curioso consegue ver ele no localStorage ou nas chamadas às APIs pelo DevTools do Chrome, por exemplo), mas como a estrutura dele envolve assinatura e etc, acaba sendo mais difícil de realmente comprometer a integridade dele, mesmo se alguém mudar o payload que é um simples base64. Se o seu back-end faz a validação certa do JWT, pode pegar as informações dele sem medo. Então, no seu caso, particularmente eu acho válido comparar o ID que vem no JWT com o ID informado na URL pra saber se o usuário tá fazendo "usuarisse" ou não kk

Sobre o código de retorno, eu particularmente não costumo retornar ele no corpo da resposta, justamente porque ele já vem informado nos cabeçalhos das respostas (por exemplo, usando alguma biblioteca de ajax - como Axios, ou até mesmo a Fetch API, que não é uma biblioteca mas tem tudo que é necessário -, já é possível validar o código de status de uma request), então seria um tipo de redundância. Assim, você pode deixar o corpo da resposta somente com o dado que precisar retornar. E, em casos de erro, por exemplo, eu costumo retornar apenas um objeto{message:"Mensagem descrevendo o erro"} no body, assim posso mostrar alguma informação útil para o usuário, e não preciso deixar regra de negócio (como validar o motivo do erro) no front-end, porque o próprio back-end já vai me trazer uma mensagem descrevendo o que deu errado.

1

Eu particulamente gosto de devolver um json padronizado com algumas informações relevantes, como status da requisição, campo de erros, informações sbre paginação e outras informações relevantes. Uma boa API facilita muito a vida do front, geralmente, faço algo como o exemplo abaixo, imaginando um endpoint que devolveria uma lista de livros:

{
    "data": [
        {
            "id": 1,
            "nome": "Entendendo algoritmos",
        } ...
    ],
    "meta": {
        "total": 1,
        "perPage": 10,
        "currentPage": 0,
        "nextPage": 1,
        "lastPage": null,
        "nextPageUrl": ... 
    },
    "error" : {
        "message": (alguma mensagem significativa para poder ser exibida no front),
        "debugMessage": (alguma mensagem que ajudasse a compreender a raíz do erro),
        "subErrors": [(em caso de múltiplos erros)],
    }
}
1