Commit 8e0eb571 by Percy Quispe Huarcaya

feat: Adding token creator and a parser

parent a23863a3
import type { Config } from 'jest';
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
globals: {
'ts-jest': {
tsconfig: 'tsconfig.json', // Asegúrate de que este archivo existe
},
},
};
export default config;
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
"name": "security-ndjs-lib", "name": "security-ndjs-lib",
"version": "1.0.0", "version": "1.0.0",
"description": "Library to manage tokens using js", "description": "Library to manage tokens using js",
"main": "src/util/token.js", "type": "module",
"types": "types/index.d.ts", "main": "src/util/token.ts",
"types": "types/security-ndjs-lib.d.ts",
"scripts": { "scripts": {
"test": "jest" "test": "jest --config jest.config.ts"
}, },
"keywords": [], "keywords": [],
"author": "poqh", "author": "poqh",
...@@ -15,6 +16,12 @@ ...@@ -15,6 +16,12 @@
"jsonwebtoken": "^9.0.2" "jsonwebtoken": "^9.0.2"
}, },
"devDependencies": { "devDependencies": {
"jest": "^29.7.0" "@types/dotenv": "^6.1.1",
} "@types/jest": "^29.5.14",
"@types/jsonwebtoken": "^9.0.7",
"jest": "^29.7.0",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript": "^4.9.5"
}
} }
const os = require('os'); import os from 'os';
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
const DEFAULT_UNIX = '/opt/dotenv/'; const DEFAULT_UNIX = '/opt/dotenv/';
// Helper function to detect the operating system // Helper function to detect the operating system
const getOperatingSystemType = () => { export const getOperatingSystemType = (): string => {
const platform = os.platform(); const platform = os.platform();
switch (platform) { switch (platform) {
case 'darwin': case 'darwin':
...@@ -20,7 +20,7 @@ const getOperatingSystemType = () => { ...@@ -20,7 +20,7 @@ const getOperatingSystemType = () => {
}; };
// Helper function for Windows-specific path check // Helper function for Windows-specific path check
const findWindowsPath = (projectName) => { export const findWindowsPath = (projectName: string): string | null => {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split(''); const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
for (const letter of alphabet) { for (const letter of alphabet) {
const winPath = `${letter}:/dotenv/${projectName}`; const winPath = `${letter}:/dotenv/${projectName}`;
...@@ -32,7 +32,7 @@ const findWindowsPath = (projectName) => { ...@@ -32,7 +32,7 @@ const findWindowsPath = (projectName) => {
}; };
// Main function to get the default project path // Main function to get the default project path
const getDefaultPath = (projectName, ...customPath) => { export const getDefaultPath = (projectName: string, ...customPath: string[]): string => {
const detectedOs = getOperatingSystemType(); const detectedOs = getOperatingSystemType();
if (!projectName) { if (!projectName) {
...@@ -59,9 +59,3 @@ const getDefaultPath = (projectName, ...customPath) => { ...@@ -59,9 +59,3 @@ const getDefaultPath = (projectName, ...customPath) => {
throw new Error(`Unsupported OS: ${detectedOs}`); throw new Error(`Unsupported OS: ${detectedOs}`);
} }
}; };
// Export the functions for use in other files
module.exports = {
getOperatingSystemType,
getDefaultPath,
};
const jwt = require('jsonwebtoken');
const { getDefaultPath } = require('./osutils')
require('dotenv').config({path: getDefaultPath('global') + "/.env"});
const apiKey = process.env.API_KEY;
const tokenAlgorithm = process.env.TOKEN_ALGORITHM
createJWT = (id, subject, ...time) => {
return createToken(id, "oliverpqh@gmail.com", subject, time);
}
createToken = (id, issuer, subject, ...time) => {
const ttlMillis = time[0] || process.env.VIGENCIA_TOKEN || 3600000 ; // Time in ms (1 hour default)
const now = Date.now();
const signingKey = Buffer.from(apiKey, 'base64');
// JWT payload (claims)
const payload = {
id: id, // JWT ID
issuedAt: Math.floor(now / 1000), // Issued at (in seconds)
subject: subject, // Subject (the user or object the token represents)
issuer: issuer // Issuer (who issued the token)
};
// Set expiration if provided
const options = {
algorithm: tokenAlgorithm
};
if (ttlMillis >= 0) {
const exp = Math.floor((now + ttlMillis) / 1000); // Expiration time in seconds
options.expiresIn = exp;
}
// Create and sign the JWT with the given payload and secret
const token = jwt.sign(payload, signingKey, options);
return token; // Return the signed JWT
}
parseJWT = (token, ...id) => {
try {
// Verify and decode the token using token and private key
const decoded = jwt.verify(token, Buffer.from(apiKey, 'base64'), {
algorithms: [tokenAlgorithm] // Ensure it matches the algorithm used when creating the token
});
/* // if one day we want to validate the id
if(id[0]){
if(decoded.payload.id !== id[0]){
throw "EL ID NO ES VALIDO";
}
}
*/
return decoded; // This will return the token's claims (payload)
} catch (err) {
console.error('Invalid token:', err.message);
throw err;
}
}
module.exports = {
createJWT,
parseJWT
};
\ No newline at end of file
import jwt, { Algorithm } from 'jsonwebtoken';
import { getDefaultPath } from './osutils';
import dotenv from 'dotenv';
// Cargar las variables de entorno desde el archivo .env
dotenv.config({ path: getDefaultPath('global') + '/.env' });
const apiKey = process.env.API_KEY;
const tokenAlgorithm = process.env.TOKEN_ALGORITHM as Algorithm;
export const createJWT = (id: string, subject: object, ...time: number[]): string => {
return createToken(id, "oliverpqh@gmail.com", subject, ...time);
}
export const createToken = (id: string, issuer: string, subject: object, ...time: number[]) => {
const ttlMillis = time[0] || Number(process.env.VIGENCIA_TOKEN) || 3600000; // Default to 1 hour
const now = Date.now();
if (!apiKey) {
throw new Error('API_KEY is required but not defined in environment variables.');
}
const signingKey = Buffer.from(apiKey, 'base64');
// JWT payload
const payload = {
id: id,
issuedAt: Math.floor(now / 1000),
subject: subject,
issuer: issuer
};
const options = {
algorithm: tokenAlgorithm,
expiresIn: ttlMillis >= 0 ? Math.floor((now + ttlMillis) / 1000) : undefined
};
// Create and sign the JWT
const token = jwt.sign(payload, signingKey, options);
return token;
};
export const parseJWT = (token: string, ...id: string[]) => {
try {
// Ensure apiKey is defined
if (!apiKey) {
throw new Error('API_KEY is required but not defined in environment variables.');
}
const decoded = jwt.verify(token, Buffer.from(apiKey, 'base64'), {
algorithms: [tokenAlgorithm]
});
return decoded;
} catch (err) {
throw err;
}
};
const {createJWT, parseJWT} = require('../src/util/token'); import { createJWT, parseJWT } from 'security-ndjs-lib';
describe('Token', () => { describe('Token', () => {
test('should generate and validate a token sending duration time', () => { test('should generate and validate a token sending duration time', () => {
//id, issuer, subject // id, issuer, subject
const id = 'trismegistro'; const id = 'trismegistro';
const subject = {"usuarioId": 395}; const subject = { usuarioId: 395 };
const unixTime = 3600000; // 1 hour validity const unixTime = 3600000; // 1 hour validity
const token = createJWT(id, subject, unixTime); const token = createJWT(id, subject, unixTime);
const test = parseJWT(token); const test = parseJWT(token);
console.log("------------------------>") console.log("------------------------>");
console.log(test) console.log(test);
const payload = test.subject; const payload = test.subject;
expect(payload.usuarioId).toBe(395); expect(payload.usuarioId).toBe(395);
}); });
test('should generate and validate a token without sending duration time', () => { test('should generate and validate a token without sending duration time', () => {
//id, issuer, subject // id, issuer, subject
const id = 'trismegistro'; const id = 'trismegistro';
const subject = {"usuarioId": 395}; const subject = { usuarioId: 395 };
const token = createJWT(id, subject); const token = createJWT(id, subject);
const test = parseJWT(token); const test = parseJWT(token);
const payload = test.subject; const payload = test.subject;
...@@ -33,4 +33,3 @@ describe('Token', () => { ...@@ -33,4 +33,3 @@ describe('Token', () => {
expect(() => parseJWT('invalidToken')).toThrow('jwt malformed'); expect(() => parseJWT('invalidToken')).toThrow('jwt malformed');
}); });
}); });
{
"compilerOptions": {
"target": "ES2017",
"module": "ESNext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"typeRoots": ["./node_modules/@types", "./types"] // Include your custom types folder
},
"include": ["src/**/*", "types/**/*"], // Include both src and types
"exclude": ["node_modules"]
}
\ No newline at end of file
interface TokenModel { interface TokenModel {
id: string; id: string;
issuedAt: number; issuedAt: number;
subject: object; subject: any;
issuer: string; issuer: string;
iat: number; iat: number;
exp: number; exp: number;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment