jsonauthtoken 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -0
- package/index.js +84 -0
- package/lib/decoading.lib.js +14 -0
- package/lib/decryption.lib.js +18 -0
- package/lib/encoading.lib.js +7 -0
- package/lib/encryption.lib.js +15 -0
- package/lib/functions.lib.js +66 -0
- package/lib/signature.lib.js +26 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# jsonauthtoken
|
|
2
|
+
|
|
3
|
+
jsonauthtoken is a JavaScript library to secure authentication.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This project demonstrates the usage of the `jsonauthtoken` package to create and verify secure encrypted authentication tokens and store sensitive datas. Tokens are used to sign and encrypt data for secure communication. The `jsonauthtoken` library provides methods to generate and verify tokens with configurable expiration times, hashing algorithms, and payload data.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## Node.js (Install)
|
|
11
|
+
|
|
12
|
+
Requirements:
|
|
13
|
+
|
|
14
|
+
- Node.js
|
|
15
|
+
- npm (Node.js package manager)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install jsonauthtoken
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Usage
|
|
22
|
+
|
|
23
|
+
To create jsonauthtoken:
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
import jat from "jsonauthtoken";
|
|
27
|
+
|
|
28
|
+
// Create a token
|
|
29
|
+
let encToken = jat().create(
|
|
30
|
+
{
|
|
31
|
+
signKey: process.env.SIGN_KEY, // Signature key
|
|
32
|
+
encKey: process.env.ENC_KEY // Encryption key
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
expiresAt: '4MIN', // Token expiration time
|
|
36
|
+
algorithm: 'sha256' // Optional: Hash algorithms list ['sha256', 'sha384', 'sha512']
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
data: { // Data payload
|
|
40
|
+
status: true,
|
|
41
|
+
name:'Arpan Biswas'
|
|
42
|
+
dob: '15.11.2008'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
console.log("encToken: ", encToken);
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
To decrypt and verify jsonauthtoken:
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
import jat from "jsonauthtoken";
|
|
55
|
+
|
|
56
|
+
// Decrypt and verify jsonauthtoken
|
|
57
|
+
|
|
58
|
+
let token = 'your-token-here'; // Replace with your generated token
|
|
59
|
+
let datas = jat().verify(token, {
|
|
60
|
+
signKey: process.env.SIGN_KEY, // Signature key
|
|
61
|
+
encKey: process.env.ENC_KEY // Encryption key
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
console.log("Enc Data: ", datas);
|
|
65
|
+
|
|
66
|
+
```
|
package/index.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import encoading from './lib/encoading.lib.js'
|
|
2
|
+
import decoading from './lib/decoading.lib.js'
|
|
3
|
+
import signature from './lib/signature.lib.js'
|
|
4
|
+
import encryption from './lib/encryption.lib.js'
|
|
5
|
+
import decryption from './lib/decryption.lib.js'
|
|
6
|
+
import { algoMatching, parseExpiration, isExpired } from './lib/functions.lib.js'
|
|
7
|
+
|
|
8
|
+
function jat() {
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const algorithms = ['sha256', 'sha384', 'sha512']
|
|
12
|
+
|
|
13
|
+
/////////////////////--------------- create token ---------------------/////////////////////////
|
|
14
|
+
const create = (keys, headers = {}, payloads = {}) => {
|
|
15
|
+
|
|
16
|
+
let {signKey, encKey} = keys
|
|
17
|
+
if(!signKey) throw new Error("please provide signkey");
|
|
18
|
+
if(!encKey) throw new Error("please provide encKey");
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
let exp = ''
|
|
22
|
+
if (headers.expiresAt) exp = parseExpiration(headers.expiresAt)
|
|
23
|
+
else throw new Error("please provide token expire")
|
|
24
|
+
|
|
25
|
+
let algo = algoMatching(algorithms, 'sha512', headers.algo)
|
|
26
|
+
|
|
27
|
+
let header = encoading({
|
|
28
|
+
token: 'JAT',
|
|
29
|
+
algorithm: algo,
|
|
30
|
+
createAt: Math.floor(Date.now() / 1000),
|
|
31
|
+
expiresAt: exp,
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
if (typeof (payloads) != 'object') throw new Error("payload should be Object");
|
|
35
|
+
let payload = encoading(payloads)
|
|
36
|
+
|
|
37
|
+
let sign = signature().createSign(algo, signKey, header, payload)
|
|
38
|
+
|
|
39
|
+
let token = header + '.' + payload + '.' + sign
|
|
40
|
+
let encryptedToken = encryption(encKey, token)
|
|
41
|
+
return encryptedToken
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
/////////////////////--------------- verify token ---------------------/////////////////////////
|
|
46
|
+
const verify = (encryptedToken, keys) => {
|
|
47
|
+
let token = ''
|
|
48
|
+
let header = ''
|
|
49
|
+
let payload = ''
|
|
50
|
+
|
|
51
|
+
let {signKey, encKey} = keys
|
|
52
|
+
if(!signKey) throw new Error("please provide signkey");
|
|
53
|
+
if(!encKey) throw new Error("please provide encKey");
|
|
54
|
+
|
|
55
|
+
//decrypt token
|
|
56
|
+
try {
|
|
57
|
+
token = decryption(encryptedToken, encKey)
|
|
58
|
+
} catch (error) {
|
|
59
|
+
throw new Error('unable to decrypt token')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//verify token signature
|
|
63
|
+
let isSignVerified = signature().verifySign(token, signKey)
|
|
64
|
+
if (isSignVerified === false) {
|
|
65
|
+
throw new Error('Invalid signature')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
//
|
|
69
|
+
const [encodedHeader, encodedPayload, sign] = token.split('.');
|
|
70
|
+
|
|
71
|
+
header = decoading(encodedHeader)
|
|
72
|
+
if(isExpired(header.expiresAt)) throw new Error('token is expired')
|
|
73
|
+
|
|
74
|
+
payload = decoading(encodedPayload)
|
|
75
|
+
|
|
76
|
+
return {header,payload}
|
|
77
|
+
}
|
|
78
|
+
return { create, verify }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
export default jat
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const decoading = (str) => {
|
|
2
|
+
// Replace URL-safe characters with standard Base64 characters
|
|
3
|
+
const base64 = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
4
|
+
|
|
5
|
+
// Add padding if necessary
|
|
6
|
+
const padding = '='.repeat((4 - base64.length % 4) % 4);
|
|
7
|
+
|
|
8
|
+
// Decode the Base64 string
|
|
9
|
+
const decoded = Buffer.from(base64 + padding, 'base64').toString('utf8');
|
|
10
|
+
|
|
11
|
+
return JSON.parse(decoded);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default decoading
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import exp from 'constants';
|
|
2
|
+
import crypto from 'crypto'
|
|
3
|
+
|
|
4
|
+
function decryption(encryptedToken, password) {
|
|
5
|
+
const parts = encryptedToken.split(':');
|
|
6
|
+
const iv = Buffer.from(parts.shift(), 'hex'); // Get the IV
|
|
7
|
+
const encryptedTokenBuffer = Buffer.from(parts.join(':'), 'hex');
|
|
8
|
+
const key = crypto.scryptSync(password, 'salt', 32);
|
|
9
|
+
|
|
10
|
+
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
|
|
11
|
+
|
|
12
|
+
let decrypted = decipher.update(encryptedTokenBuffer, 'binary', 'utf8');
|
|
13
|
+
decrypted += decipher.final('utf8');
|
|
14
|
+
|
|
15
|
+
return decrypted;
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
export default decryption
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import crypto from 'crypto'
|
|
2
|
+
|
|
3
|
+
function encryption(password,token){
|
|
4
|
+
const iv = crypto.randomBytes(16); // Initialization vector
|
|
5
|
+
const key = crypto.scryptSync(password, 'salt', 32); // Key derivation
|
|
6
|
+
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
|
|
7
|
+
|
|
8
|
+
let encrypted = cipher.update(token, 'utf8', 'hex');
|
|
9
|
+
encrypted += cipher.final('hex');
|
|
10
|
+
|
|
11
|
+
// Return the IV and encrypted text
|
|
12
|
+
return iv.toString('hex') + ':' + encrypted;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default encryption
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function algoMatching(algorithms, defaultOutput, input) {
|
|
2
|
+
|
|
3
|
+
//check defaultOutput parameter
|
|
4
|
+
if (!defaultOutput) throw new Error('defaultOutput parameter can not be empty')
|
|
5
|
+
|
|
6
|
+
//find the correct algorithm name is given as 'input' or not , if is't return defaultOutput
|
|
7
|
+
for (let i in algorithms) {
|
|
8
|
+
if (String(algorithms[i]) === String(input)) defaultOutput = algorithms[i]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return defaultOutput
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
function parseExpiration(input) {
|
|
16
|
+
const regex = /^(\d+)([mhdMHDyY]|MIN)$/; // Regex to match number + unit
|
|
17
|
+
const match = input.match(regex);
|
|
18
|
+
|
|
19
|
+
if (!match) {
|
|
20
|
+
throw new Error('Invalid format. Use formats like 1M, 1Y, 1D, 1MIN.');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const amount = parseInt(match[1], 10);
|
|
24
|
+
const unit = match[2].toLowerCase(); // Normalize to lowercase
|
|
25
|
+
|
|
26
|
+
let seconds;
|
|
27
|
+
|
|
28
|
+
switch (unit) {
|
|
29
|
+
case 'y':
|
|
30
|
+
seconds = amount * 365 * 24 * 60 * 60; // Years to seconds
|
|
31
|
+
break;
|
|
32
|
+
case 'm':
|
|
33
|
+
seconds = amount * 30 * 24 * 60 * 60; // Months to seconds (approximation)
|
|
34
|
+
break;
|
|
35
|
+
case 'd':
|
|
36
|
+
seconds = amount * 24 * 60 * 60; // Days to seconds
|
|
37
|
+
break;
|
|
38
|
+
case 'h':
|
|
39
|
+
seconds = amount * 60 * 60; // Hours to seconds
|
|
40
|
+
break;
|
|
41
|
+
case 'min':
|
|
42
|
+
seconds = amount * 60; // Minutes to seconds
|
|
43
|
+
break;
|
|
44
|
+
default:
|
|
45
|
+
throw new Error('Unsupported time unit. Use M, Y, D, H, or MIN.');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
return Math.floor(Date.now() / 1000) + seconds; // Current time + expiration time
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
function isExpired(timeStamp) {
|
|
54
|
+
let currentTime = Math.floor(Date.now() / 1000)
|
|
55
|
+
if (timeStamp < currentTime) {
|
|
56
|
+
return true
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
export { algoMatching, parseExpiration, isExpired }
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import crypto from 'crypto'
|
|
2
|
+
import decoading from './decoading.lib.js';
|
|
3
|
+
|
|
4
|
+
const signature = () => {
|
|
5
|
+
|
|
6
|
+
const createSign = (algorithm, key, header, payload) => {
|
|
7
|
+
const signature = crypto
|
|
8
|
+
.createHmac(algorithm, key)
|
|
9
|
+
.update(header + '.' + payload)
|
|
10
|
+
.digest('base64url');
|
|
11
|
+
return signature
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const verifySign = (token,key) => {
|
|
15
|
+
const [encodedHeader, encodedPayload, signature] = token.split('.');
|
|
16
|
+
const header= decoading(encodedHeader)
|
|
17
|
+
|
|
18
|
+
let newSign=createSign(header.algorithm, key, encodedHeader, encodedPayload)
|
|
19
|
+
|
|
20
|
+
if(newSign == signature) return true
|
|
21
|
+
else return false
|
|
22
|
+
}
|
|
23
|
+
return { createSign, verifySign }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default signature
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jsonauthtoken",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "jsonauthtoken is a JavaScript library to secure authentication.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/iamAyanBiswas/jsonauthtoken"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"test": "node index.js"
|
|
13
|
+
},
|
|
14
|
+
"author": "Ayan Biswas",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"jat",
|
|
18
|
+
"jwt",
|
|
19
|
+
"jsonauthtoken",
|
|
20
|
+
"jsonwebtoken",
|
|
21
|
+
"auth",
|
|
22
|
+
"authentication",
|
|
23
|
+
"sha256",
|
|
24
|
+
"sha384",
|
|
25
|
+
"sha512"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
|