refactor: refresh token

This commit is contained in:
rodrigo goncalves 2023-01-31 14:38:39 -03:00
parent e58eaed8ee
commit 7bb7204cea
11 changed files with 45 additions and 27 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

16
package-lock.json generated
View file

@ -18,7 +18,8 @@
"knex": "^2.2.0", "knex": "^2.2.0",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"sqlite3": "^5.0.11", "sqlite3": "^5.0.11",
"swagger-ui-express": "^4.5.0" "swagger-ui-express": "^4.5.0",
"uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^2.0.19" "nodemon": "^2.0.19"
@ -2534,6 +2535,14 @@
"node": ">= 0.4.0" "node": ">= 0.4.0"
} }
}, },
"node_modules/uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/vary": { "node_modules/vary": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@ -4509,6 +4518,11 @@
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
}, },
"uuid": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
"integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg=="
},
"vary": { "vary": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

View file

@ -21,9 +21,10 @@
"knex": "^2.2.0", "knex": "^2.2.0",
"multer": "^1.4.5-lts.1", "multer": "^1.4.5-lts.1",
"sqlite3": "^5.0.11", "sqlite3": "^5.0.11",
"swagger-ui-express": "^4.5.0" "swagger-ui-express": "^4.5.0",
"uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^2.0.19" "nodemon": "^2.0.19"
} }
} }

BIN
src/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -23,14 +23,12 @@ class SessionsController {
const generateTokenProvider = new GenerateToken(); const generateTokenProvider = new GenerateToken();
const token = await generateTokenProvider.execute(user.id); const token = await generateTokenProvider.execute(user.id);
await knex("users_tokens").where({ user_id: user.id }).delete();
const generateRefreshToken = new GenerateRefreshToken(); const generateRefreshToken = new GenerateRefreshToken();
generateRefreshToken.execute(user.id, token); const refresh_token = await generateRefreshToken.execute(user.id);
delete user.password; delete user.password;
response.status(201).json({ token, user }); response.status(201).json({ user, token, refresh_token });
} }
} }

View file

@ -6,33 +6,33 @@ const dayjs = require("dayjs");
class UserRefreshToken { class UserRefreshToken {
async create(request, response) { async create(request, response) {
const { token } = request.body; const { refresh_token } = request.body;
if (!token) { if (!refresh_token) {
throw new AppError("Informe o token de autenticação.", 401); throw new AppError("Informe o token de autenticação.", 401);
} }
const userToken = await knex("users_tokens").where({ token }).first(); const refreshToken = await knex("refresh_token").where({ refresh_token }).first();
if (!userToken) { if (!refreshToken) {
throw new AppError("Refresh token não encontrado para este usuário.", 404); throw new AppError("Refresh token não encontrado para este usuário.", 401);
} }
const generateTokenProvider = new GenerateToken(); const generateTokenProvider = new GenerateToken();
const refreshToken = await generateTokenProvider.execute(userToken.user_id); const token = await generateTokenProvider.execute(refreshToken.user_id);
const refreshTokenExpired = dayjs().isAfter(dayjs.unix(userToken.expires_in)); const refreshTokenExpired = dayjs().isAfter(dayjs.unix(refreshToken.expires_in));
if (refreshTokenExpired) { if (refreshTokenExpired) {
await knex("users_tokens").where({ user_id: userToken.user_id }).delete(); await knex("refresh_token").where({ user_id: refreshToken.user_id }).delete();
const generateRefreshToken = new GenerateRefreshToken(); const generateRefreshToken = new GenerateRefreshToken();
await generateRefreshToken.execute(userToken.user_id, refreshToken); const newRefreshToken = await generateRefreshToken.execute(refreshToken.user_id, refresh_token);
return response.json({ token: refreshToken }); return response.json({ token, refresh_token: newRefreshToken });
} }
return response.json({ token }); return response.json({ token, refresh_token });
} }
} }

BIN
src/database/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

View file

@ -1,9 +1,9 @@
exports.up = knex => knex.schema.createTable("users_tokens", table => { exports.up = knex => knex.schema.createTable("refresh_token", table => {
table.increments("id"); table.increments("id");
table.integer("expires_in") table.integer("expires_in")
table.text("refresh_token")
table.integer("user_id").references("id").inTable("users"); table.integer("user_id").references("id").inTable("users");
table.text("token").notNullable();
table.timestamp("created_at").default(knex.fn.now()); table.timestamp("created_at").default(knex.fn.now());
}); });
exports.down = knex => knex.schema.dropTable("users_tokens"); exports.down = knex => knex.schema.dropTable("users_tokens");

View file

@ -9,7 +9,6 @@ async function ensureAuthenticated(request, response, next) {
throw new AppError("JWT token não informado", 401); throw new AppError("JWT token não informado", 401);
} }
const [, token] = authHeader.split(" "); const [, token] = authHeader.split(" ");
try { try {

View file

@ -1,15 +1,21 @@
const knex = require("../database"); const knex = require("../database");
const dayjs = require("dayjs"); const dayjs = require("dayjs");
const uuid = require('uuid')
class GenerateRefreshToken { class GenerateRefreshToken {
async execute(userId, newToken) { async execute(user_id) {
const expires_in = dayjs().add(15, "second").unix(); await knex("refresh_token").where({ user_id }).delete();
await knex("users_tokens").insert({ const expires_in = dayjs().add(15, "m").unix();
user_id: userId, const refresh_token = uuid.v4();
await knex("refresh_token").insert({
user_id,
expires_in, expires_in,
token: newToken refresh_token
}); });
return refresh_token;
} }
} }