DEV Community

João Neto for Guarapi

Posted on • Edited on

Implementando um Plugin de Autenticação para Guarapi

Olá!

Gostaria de compartilhar uma Prova de Conceito (POC) de um plugin de autenticação em desenvolvimento para o Guarapi. Este plugin visa oferecer funcionalidades de autenticação e renovação de tokens JWT.

Para mais informações e para colaborar, acesse nosso Discord Guarapi Development e confira o GitHub do Guarapi.

Aqui está uma breve amostra do código do plugin:

import { Plugin, Request } from 'guarapi';
import { Methods } from 'guarapi/dist/lib/router';
import { sign } from 'jsonwebtoken';

interface SingConfig<P extends { sub: string | number }> {
  route: string;
  getJWTPayload: (req: Request) => Promise<P>;
}

export interface GuarapiAuthPluginConfig<P extends { sub: string | number }> {
  signIn?: SingConfig<P>;
  refreshToken?: SingConfig<P>;
  salt: string;
  tokenExpiresIn: string;
  refreshTokenExpiresIn: string;
  issuer: string;
  audience: string;
}

export default function guarapiAuthPlugin<P extends { sub: string | number }>(
  guarapiAuthPluginConfig: GuarapiAuthPluginConfig<P>,
) {
  const { salt, audience, issuer, tokenExpiresIn, refreshTokenExpiresIn, signIn, refreshToken } =
    guarapiAuthPluginConfig;

  const routesMap: Record<string, SingConfig<P> | undefined> = {
    [signIn?.route || '']: signIn,
    [refreshToken?.route || '']: refreshToken,
  };

  async function getTokens(req: Request, route: SingConfig<P>) {
    const { sub, ...jwtPayload } = await route.getJWTPayload(req);

    return {
      token: sign({ sub, ...jwtPayload }, salt, {
        expiresIn: route === signIn ? tokenExpiresIn : refreshTokenExpiresIn,
        audience,
        issuer,
      }),

      refreshToken: sign({ sub, ...jwtPayload }, salt, {
        expiresIn: refreshTokenExpiresIn,
        audience,
        issuer,
      }),
    };
  }

  const plugin: Plugin = (app) => {
    app.use(async (req, res, next) => {
      const route = routesMap[req.url || ''];
      const method = req.method?.toLocaleLowerCase();

      if (route && method === Methods.POST) {
        const tokens = await getTokens(req, route);
        res.json(tokens);
        return;
      }

      next();
    });

    return {
      name: 'guarapiAuthPlugin',
    };
  };

  return plugin;
}
Enter fullscreen mode Exit fullscreen mode

Este plugin permite configurar rotas de autenticação e renovação de tokens JWT, adaptáveis às necessidades do projeto. Ele utiliza o pacote jsonwebtoken para gerar os tokens com base nas configurações fornecidas.

A configuração básica para este plugin é a seguinte:

import { Guarapi, bodyParserPlugin, middlewarePlugin } from 'guarapi';
import guarapiAuthPlugin, { GuarapiAuthPluginConfig } from './guarapi-auth-plugin';

interface PayloadRequest {
  userId: string;
}

export default async function initPlugins(app: Guarapi) {
  const authConfig: GuarapiAuthPluginConfig<{ sub: string; userId: string }> = {
    signIn: {
      route: '/auth/signin',
      getJWTPayload: async (req) =>
        Promise.resolve({ sub: 'teste', userId: (req.body as PayloadRequest)?.userId }),
    },
    refreshToken: {
      route: '/auth/refresh',
      getJWTPayload: async (req) =>
        Promise.resolve({ sub: 'teste', userId: (req.body as PayloadRequest)?.userId }),
    },
    audience: 'teste',
    issuer: 'issuer-1',
    salt: 'secret',
    refreshTokenExpiresIn: '24h',
    tokenExpiresIn: '1h',
  };

  app.plugin(bodyParserPlugin);
  app.plugin(middlewarePlugin);
  app.plugin(guarapiAuthPlugin(authConfig));
}
Enter fullscreen mode Exit fullscreen mode

Estou buscando feedback da comunidade sobre a estrutura, a lógica de funcionamento e possíveis melhorias que podem ser implementadas neste plugin. Sintam-se à vontade para discutir e compartilhar suas opiniões, sugestões ou dúvidas relacionadas a esta POC.

Agradeço antecipadamente por qualquer contribuição ou feedback que possam oferecer!

Nossas redes:

Plataforma Link
Reddit Guarapi Subreddit
Daily.dev Daily.dev Invite
Discord Discord Invite
Repositório Guarapi no GitHub

Top comments (0)