Usando API routes do NextJs como proxy para seu backend.
Contexto
Recentemente precisei desenvolver um frontend em Next. O projeto utiliza Auth0 para lidar com autenticação. Assim, o backend precisa receber um access token assinado pelo Auth0 para autorizar as requisições, e o front precisa enviar esse dado e saber quando o usuário está logado ou não.
Existem diversas maneiras de fazer isso, inclusive ja utilizei muito o NextAuth, ou em casos mais simples somente Context API.
No entanto, como o projeto está fortemente atrelado ao Auth0 e o respectivo SDK v2 para next saiu do beta recentemente, optei por utilizá-lo.
A ferramente é muito fácil de se utilizar e com certeza me poupou várias linhas de código.
Porém, o SDK para Next não permite que eu obtenha o access token no lado do cliente - por uma questão de arquitetura - e na própria documentação é recomendado que se utilize as API Routes como proxy para o backend.
Solução
A documentação me instrui a criar uma rota api no next para cada rota do meu backend. Em projetos extremamente pequenos, pode ser que isso faça sentido, mas no meu caso o backend dispõe MUITOS endpoints, e queria uma forma de aplicar o proxy para todos eles.
Então fiz o seguinte
// src/pages/api/projeto/[...projeto].ts
import { withApiAuthRequired, getAccessToken } from '@auth0/nextjs-auth0';
import axios, { AxiosError } from 'axios';
export default withApiAuthRequired(async function shows(req, res) {
try {
const endpoint = (req.query.projeto as string[]).reduce((acc, val) => acc + '/' + val,'');
const { accessToken } = await getAccessToken(req, res, {
scopes: ['openid','profile', 'email', 'offline_access'],
});
const response = await axios.request({
method: req.method,
data: req.body,
params: req.query,
headers: {
Authorization: 'Bearer ' + accessToken
},
url: process.env.API_URL + endpoint
});
return res.status(response.status).json(response.data);
} catch (error: any) {
let status = 500;
let body = {
message: 'Internal Server Error'
}
if (error instanceof AxiosError) {
status = error.response?.status!;
body = error.response?.data!;
}
return res.status(status).json(body);
}
});
Agora quando eu quero fazer uma requisição que será disparada no lado do cliente, basta eu chamar /api/projeto/{endpoint do backend}
.
Um código simples que me salvou um bom tempo e esforço.
Vale lembrar que o ponto aqui não é falar sobre a SDK do Auth0, somente sobre essa estratégia, que acredito que pode ser útil para diversos outros casos.
Se alguém quiser posso fazer um post mostrando com mais detalhes a integração com o Auth0.
Se souber algum problema com essa abordagem, comenta aí abaixo.