Skip to content

Commit a6dc2a2

Browse files
author
productioncoder
committed
add RSA support
1 parent 71f82f8 commit a6dc2a2

File tree

6 files changed

+109
-40
lines changed

6 files changed

+109
-40
lines changed

config/index.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
1+
const fs = require("fs");
2+
3+
function loadKey(path) {
4+
if (!path) {
5+
return null;
6+
}
7+
try {
8+
return fs.readFileSync(path);
9+
} catch (err) {
10+
console.error(err);
11+
// don't use process.exit in prod
12+
// rather do a graceful
13+
process.exit(1);
14+
}
15+
}
16+
117
module.exports = {
218
partnerServerHost: "localhost",
319
partnerServerPort: process.env.PARTNER_SERVER_PORT,
4-
partnerServerName: process.env.PARTNER_SERVER_NAME,
20+
partnerRSAPublicKey: loadKey(process.env.PARTNER_JWT_RSA_PUBLIC_KEY),
521

622
hostname: "localhost",
723
serverName: process.env.SERVER_NAME,
824
port: process.env.PORT,
25+
rsaPrivateKey: loadKey(process.env.JWT_RSA_PRIVATE_KEY),
926

1027
// in prod, use a stronger secret
11-
tokenSecret: 'mysecret',
28+
hmacSecret: process.env.HMAC_SECRET,
1229
};

controller/producer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ async function produce(req, res) {
66
const tokenPayload = {
77
tokenOrigin: `this token was created by ${config.serverName}`,
88
};
9-
const token = tokenService.buildToken(config.partnerServerName, tokenPayload);
9+
const token = tokenService.buildToken(config.serverName, tokenPayload);
1010

1111
const reqConfig = {
1212
headers: {

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
"main": "index.js",
66
"scripts": {
77
"dev-single": "nodemon index.js",
8-
"serverA": "PORT=3000 PARTNER_SERVER_PORT=8080 SERVER_NAME=serverA PARTNER_SERVER_NAME=serverB nodemon index.js",
9-
"serverB": "PORT=8080 PARTNER_SERVER_PORT=3000 SERVER_NAME=serverB PARTNER_SERVER_NAME=serverA nodemon index.js",
8+
"serverA": "PORT=3000 PARTNER_SERVER_PORT=8080 SERVER_NAME=serverA PARTNER_SERVER_NAME=serverB HMAC_SECRET=myscret nodemon index.js",
9+
"serverB": "PORT=8080 PARTNER_SERVER_PORT=3000 SERVER_NAME=serverB PARTNER_SERVER_NAME=serverA HMAC_SECRET=mysecret nodemon index.js",
10+
"rsaServerA": "PORT=3000 JWT_RSA_PRIVATE_KEY=./serverA-private.key PARTNER_JWT_RSA_PUBLIC_KEY=./serverB-public.key PARTNER_SERVER_PORT=8080 SERVER_NAME=serverA PARTNER_SERVER_NAME=serverB nodemon index.js",
11+
"rsaServerB": "PORT=8080 JWT_RSA_PRIVATE_KEY=./serverB-private.key PARTNER_JWT_RSA_PUBLIC_KEY=./serverA-public.key PARTNER_SERVER_PORT=3000 SERVER_NAME=serverB PARTNER_SERVER_NAME=serverA nodemon index.js",
1012
"test": "echo \"Error: no test specified\" && exit 1"
1113
},
1214
"keywords": [],

service/token.js

Lines changed: 0 additions & 35 deletions
This file was deleted.

service/token/index.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const tokenConfig = require('./token-config');
2+
const jwt = require("jsonwebtoken");
3+
4+
function buildToken(subject, payload = {}) {
5+
const {options, secret} = tokenConfig.getSigningConfig(subject);
6+
return jwt.sign(payload, secret, options);
7+
}
8+
9+
function verifyToken(token) {
10+
const {options, secret} = tokenConfig.getVerifyConfig();
11+
try {
12+
return jwt.verify(token, secret, options);
13+
} catch (err) {
14+
// in prod, don't use console.log because it is synchronous
15+
console.log(err);
16+
return null;
17+
}
18+
}
19+
20+
module.exports = {
21+
buildToken,
22+
verifyToken,
23+
};

service/token/token-config.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const config = require('../../config');
2+
3+
const defaultSignOptions = {
4+
expiresIn: 15 * 60, // expires in 15min
5+
issuer: config.serverName,
6+
audience: `${config.partnerServerHost}:${config.partnerServerPort}`,
7+
};
8+
9+
const hmacSignOptions = {
10+
algorithm: 'HS256',
11+
...defaultSignOptions
12+
}
13+
14+
const hmacVerifyOptions = {
15+
algorithms: ["HS256"], // only allow HMAC with SHA256
16+
// audience: `${config.hostname}:${config.port}`,
17+
// issuer: config.partnerServerName,
18+
};
19+
20+
const rsaVerifyOptions = {
21+
// only allow RSA + SHA256
22+
algorithms: ["RS256"],
23+
}
24+
25+
const rsaSignOptions = {
26+
algorithm: 'RS256',
27+
...defaultSignOptions
28+
}
29+
30+
function getSigningConfig(subject) {
31+
if (config.rsaPrivateKey) {
32+
return {
33+
options: {...rsaSignOptions, subject},
34+
secret: config.rsaPrivateKey
35+
};
36+
}
37+
return {
38+
options: {...hmacSignOptions, subject},
39+
secret: config.hmacSecret,
40+
}
41+
}
42+
43+
function getVerifyConfig(subject) {
44+
if (config.rsaPrivateKey) {
45+
return {
46+
options: rsaVerifyOptions,
47+
secret: config.partnerRSAPublicKey,
48+
};
49+
}
50+
return {
51+
options: hmacVerifyOptions,
52+
secret: config.hmacSecret,
53+
}
54+
}
55+
56+
module.exports = {
57+
getVerifyConfig,
58+
getSigningConfig,
59+
}
60+
61+
62+

0 commit comments

Comments
 (0)