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)