Skip to content
295 changes: 164 additions & 131 deletions README.md

Large diffs are not rendered by default.

99 changes: 99 additions & 0 deletions examples/express-refresh-auth/server.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
require('dotenv').config();

const express = require('express');
const cookieParser = require('cookie-parser');
const {
jwt,
password,
middleware,
cookies,
} = require('@devflow-modules/jwt-auth');

const app = express();
app.use(express.json());
app.use(cookieParser());

const users = new Map();

async function seedUser() {
const passwordHash = await password.hashPassword('password123');

users.set('demo@example.com', {
id: 'user-123',
email: 'demo@example.com',
role: 'admin',
passwordHash,
});
}

app.post('/login', async (req, res) => {
const { email, password: plainPassword } = req.body;
const user = users.get(email);

if (!user) {
return res.status(401).json({ message: 'Invalid credentials.' });
}

const isPasswordValid = await password.comparePassword(
plainPassword,
user.passwordHash
);

if (!isPasswordValid) {
return res.status(401).json({ message: 'Invalid credentials.' });
}

const payload = {
id: user.id,
email: user.email,
role: user.role,
};

const accessToken = jwt.signToken(payload);
const refreshToken = jwt.signRefreshToken({ id: user.id });

cookies.setTokenCookie(res, accessToken);

return res.json({
accessToken,
refreshToken,
});
});

app.post('/refresh', (req, res) => {
const { refreshToken } = req.body;

if (!refreshToken) {
return res.status(400).json({ message: 'Refresh token is required.' });
}

try {
const decoded = jwt.verifyRefreshToken(refreshToken);
const accessToken = jwt.signToken({ id: decoded.id });

return res.json({ accessToken });
} catch {
return res.status(401).json({ message: 'Invalid refresh token.' });
}
});

app.get('/private-bearer', middleware.protectRoute, (req, res) => {
return res.json({
message: 'Bearer-token route access granted.',
user: req.user,
});
});

app.get('/private-cookie', middleware.protectRouteFromCookie, (req, res) => {
return res.json({
message: 'Cookie-based route access granted.',
user: req.user,
});
});

seedUser().then(() => {
app.listen(3000, () => {
console.log('Example API running at http://localhost:3000');
console.log('Demo user: demo@example.com / password123');
});
});
41 changes: 23 additions & 18 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
// JWT: Funções para geração e verificação de access/refresh tokens
const { signToken } = require('./jwt/signToken');
const { verifyToken } = require('./jwt/verifyToken');
const { signRefreshToken } = require('./jwt/signRefreshToken');
const { verifyRefreshToken } = require('./jwt/verifyRefreshToken');
// JWT: access/refresh token helpers
const { signToken } = require('./jwt/signToken.cjs');
const { verifyToken } = require('./jwt/verifyToken.cjs');
const { signRefreshToken } = require('./jwt/signRefreshToken.cjs');
const { verifyRefreshToken } = require('./jwt/verifyRefreshToken.cjs');

// Senhas: Hash e comparação de senhas com bcrypt
const { hashPassword } = require('./password/hashPassword');
const { comparePassword } = require('./password/comparePassword');
// Password helpers
const { hashPassword } = require('./password/hashPassword.cjs');
const { comparePassword } = require('./password/comparePassword.cjs');

// Middlewares: Proteção de rotas com verificação de token (Header ou Cookie)
const { protectRoute } = require('./middleware/protectRoute');
const { protectRouteFromCookie } = require('./middleware/protectRouteFromCookie');
// Express middlewares
const { protectRoute } = require('./middleware/protectRoute.cjs');
const { protectRouteFromCookie } = require('./middleware/protectRouteFromCookie.cjs');
const { protectWithRoles } = require('./middleware/protectWithRoles.cjs');

// Cookies: Utilitários para manipulação de token via cookies HTTP-only
const { setTokenCookie } = require('./cookies/setTokenCookie');
const { getTokenFromCookie } = require('./cookies/getTokenFromCookie');
// Cookie helpers
const { setTokenCookie } = require('./cookies/setTokenCookie.cjs');
const { getTokenFromCookie } = require('./cookies/getTokenFromCookie.cjs');

/**
* Exporta as funcionalidades organizadas em namespaces.
* Isso permite importar apenas o necessário com clareza:
* Public package API grouped by namespace.
*
* const { jwt, password, middleware } = require('@devflow-modules/jwt-auth');
* jwt.signToken(...), password.hashPassword(...), middleware.protectRoute(...)
* Example:
*
* const { jwt, password, middleware, cookies } = require('@devflow-modules/jwt-auth');
* jwt.signToken(...)
* password.hashPassword(...)
* middleware.protectRoute(...)
*/

module.exports = {
Expand All @@ -38,6 +42,7 @@ module.exports = {
middleware: {
protectRoute,
protectRouteFromCookie,
protectWithRoles,
},
cookies: {
setTokenCookie,
Expand Down
2 changes: 1 addition & 1 deletion src/jwt/signRefreshToken.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const jwt = require('jsonwebtoken');
const { JWT_REFRESH_SECRET, JWT_REFRESH_EXPIRES_IN } = require('../utils/env');
const { JWT_REFRESH_SECRET, JWT_REFRESH_EXPIRES_IN } = require('../utils/env.cjs');

/**
* Gera um Refresh Token JWT.
Expand Down
2 changes: 1 addition & 1 deletion src/jwt/signToken.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const {
JWT_SECRET,
JWT_EXPIRES_IN = '1h',
JWT_PRIVATE_KEY_PATH,
} = require('../utils/env');
} = require('../utils/env.cjs');

/**
* Gera um Access Token JWT com suporte a algoritmos simétricos (HS256/HS512)
Expand Down
2 changes: 1 addition & 1 deletion src/jwt/verifyRefreshToken.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const jwt = require('jsonwebtoken');
const { JWT_REFRESH_SECRET } = require('../utils/env');
const { JWT_REFRESH_SECRET } = require('../utils/env.cjs');

/**
* Verifica e decodifica um Refresh Token JWT.
Expand Down
4 changes: 2 additions & 2 deletions src/jwt/verifyToken.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const {
JWT_ALGORITHM = 'HS256',
JWT_SECRET,
JWT_PUBLIC_KEY_PATH,
} = require('../utils/env');
} = require('../utils/env.cjs');

/**
* Verifica e decodifica um token JWT com suporte a algoritmos simétricos e assimétricos.
Expand Down Expand Up @@ -46,4 +46,4 @@ function verifyToken(token, options = {}) {
});
}

module.exports = { verifyToken };
module.exports = { verifyToken };
2 changes: 1 addition & 1 deletion src/middleware/protectRoute.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { verifyToken } = require('../jwt/verifyToken');
const { verifyToken } = require('../jwt/verifyToken.cjs');

/**
* Middleware para proteger rotas autenticadas.
Expand Down
4 changes: 2 additions & 2 deletions src/middleware/protectRouteFromCookie.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { verifyToken } = require('../jwt/verifyToken');
const { getTokenFromCookie } = require('../cookies/getTokenFromCookie');
const { verifyToken } = require('../jwt/verifyToken.cjs');
const { getTokenFromCookie } = require('../cookies/getTokenFromCookie.cjs');

/**
* Middleware para proteger rotas autenticadas usando token JWT em cookies.
Expand Down
Loading