@prairielearn/signed-token 1.0.15 → 2.0.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @prairielearn/signed-token
2
2
 
3
+ ## 2.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 901fce8: Upgrade all JavaScript dependencies
8
+
9
+ ## 2.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - 4f30b7e: Publish as native ESM
14
+
3
15
  ## 1.0.15
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,24 +1,18 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.checkSignedToken = exports.getCheckedSignedTokenData = exports.generateSignedToken = void 0;
7
- const base64url_1 = __importDefault(require("base64url"));
8
- const debug_1 = __importDefault(require("debug"));
9
- const lodash_1 = __importDefault(require("lodash"));
10
- const node_crypto_1 = __importDefault(require("node:crypto"));
11
- const debug = (0, debug_1.default)('prairielearn:csrf');
1
+ import crypto from 'node:crypto';
2
+ import base64url from 'base64url';
3
+ import debugfn from 'debug';
4
+ import _ from 'lodash';
5
+ const debug = debugfn('prairielearn:csrf');
12
6
  const sep = '.';
13
- function generateSignedToken(data, secretKey) {
7
+ export function generateSignedToken(data, secretKey) {
14
8
  debug(`generateSignedToken(): data = ${JSON.stringify(data)}`);
15
9
  debug(`generateSignedToken(): secretKey = ${secretKey}`);
16
10
  const dataJSON = JSON.stringify(data);
17
- const dataString = base64url_1.default.encode(dataJSON);
11
+ const dataString = base64url.default.encode(dataJSON);
18
12
  const dateString = new Date().getTime().toString(36);
19
13
  const checkString = dateString + sep + dataString;
20
- const signature = node_crypto_1.default.createHmac('sha256', secretKey).update(checkString).digest('hex');
21
- const encodedSignature = base64url_1.default.encode(signature);
14
+ const signature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');
15
+ const encodedSignature = base64url.default.encode(signature);
22
16
  debug(`generateSignedToken(): ${JSON.stringify({
23
17
  dataString,
24
18
  dateString,
@@ -29,12 +23,11 @@ function generateSignedToken(data, secretKey) {
29
23
  debug(`generateSignedToken(): token = ${token}`);
30
24
  return token;
31
25
  }
32
- exports.generateSignedToken = generateSignedToken;
33
- function getCheckedSignedTokenData(token, secretKey, options = {}) {
26
+ export function getCheckedSignedTokenData(token, secretKey, options = {}) {
34
27
  debug(`getCheckedSignedTokenData(): token = ${token}`);
35
28
  debug(`getCheckedSignedTokenData(): secretKey = ${secretKey}`);
36
29
  debug(`getCheckedSignedTokenData(): options = ${JSON.stringify(options)}`);
37
- if (!lodash_1.default.isString(token)) {
30
+ if (!_.isString(token)) {
38
31
  debug(`getCheckedSignedTokenData(): FAIL - token is not string`);
39
32
  return null;
40
33
  }
@@ -49,8 +42,8 @@ function getCheckedSignedTokenData(token, secretKey, options = {}) {
49
42
  const tokenDataString = match[2];
50
43
  // check the signature
51
44
  const checkString = tokenDateString + sep + tokenDataString;
52
- const checkSignature = node_crypto_1.default.createHmac('sha256', secretKey).update(checkString).digest('hex');
53
- const encodedCheckSignature = base64url_1.default.encode(checkSignature);
45
+ const checkSignature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');
46
+ const encodedCheckSignature = base64url.default.encode(checkSignature);
54
47
  if (encodedCheckSignature !== tokenSignature) {
55
48
  debug(`getCheckedSignedTokenData(): FAIL - signature mismatch: checkSig=${encodedCheckSignature} != tokenSig=${tokenSignature}`);
56
49
  return null;
@@ -75,7 +68,7 @@ function getCheckedSignedTokenData(token, secretKey, options = {}) {
75
68
  // get the data
76
69
  let tokenDataJSON, tokenData;
77
70
  try {
78
- tokenDataJSON = base64url_1.default.decode(tokenDataString);
71
+ tokenDataJSON = base64url.default.decode(tokenDataString);
79
72
  }
80
73
  catch (e) {
81
74
  debug(`getCheckedSignedTokenData(): FAIL - could not base64 decode: ${tokenDateString}`);
@@ -91,8 +84,7 @@ function getCheckedSignedTokenData(token, secretKey, options = {}) {
91
84
  debug(`getCheckedSignedTokenData(): tokenData = ${tokenData}`);
92
85
  return tokenData;
93
86
  }
94
- exports.getCheckedSignedTokenData = getCheckedSignedTokenData;
95
- function checkSignedToken(token, data, secretKey, options = {}) {
87
+ export function checkSignedToken(token, data, secretKey, options = {}) {
96
88
  debug(`checkSignedToken(): token = ${token}`);
97
89
  debug(`checkSignedToken(): data = ${JSON.stringify(data)}`);
98
90
  debug(`checkSignedToken(): secretKey = ${secretKey}`);
@@ -102,9 +94,8 @@ function checkSignedToken(token, data, secretKey, options = {}) {
102
94
  debug(`checkSignedToken(): tokenData = ${JSON.stringify(tokenData)}`);
103
95
  if (tokenData == null)
104
96
  return false;
105
- if (!lodash_1.default.isEqual(data, tokenData))
97
+ if (!_.isEqual(data, tokenData))
106
98
  return false;
107
99
  return true;
108
100
  }
109
- exports.checkSignedToken = checkSignedToken;
110
101
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from 'node:crypto';\n\nimport base64url from 'base64url';\nimport debugfn from 'debug';\nimport _ from 'lodash';\n\nconst debug = debugfn('prairielearn:csrf');\nconst sep = '.';\n\ninterface CheckOptions {\n maxAge?: number;\n}\n\nexport function generateSignedToken(data: any, secretKey: string) {\n debug(`generateSignedToken(): data = ${JSON.stringify(data)}`);\n debug(`generateSignedToken(): secretKey = ${secretKey}`);\n const dataJSON = JSON.stringify(data);\n const dataString = base64url.default.encode(dataJSON);\n const dateString = new Date().getTime().toString(36);\n const checkString = dateString + sep + dataString;\n const signature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');\n const encodedSignature = base64url.default.encode(signature);\n debug(\n `generateSignedToken(): ${JSON.stringify({\n dataString,\n dateString,\n checkString,\n encodedSignature,\n })}`,\n );\n const token = encodedSignature + sep + checkString;\n debug(`generateSignedToken(): token = ${token}`);\n return token;\n}\n\nexport function getCheckedSignedTokenData(\n token: string,\n secretKey: string,\n options: CheckOptions = {},\n) {\n debug(`getCheckedSignedTokenData(): token = ${token}`);\n debug(`getCheckedSignedTokenData(): secretKey = ${secretKey}`);\n debug(`getCheckedSignedTokenData(): options = ${JSON.stringify(options)}`);\n if (!_.isString(token)) {\n debug(`getCheckedSignedTokenData(): FAIL - token is not string`);\n return null;\n }\n\n // break token apart into the three components\n const match = token.split(sep);\n if (match == null) {\n debug(`getCheckedSignedTokenData(): FAIL - could not split token`);\n return null;\n }\n const tokenSignature = match[0];\n const tokenDateString = match[1];\n const tokenDataString = match[2];\n\n // check the signature\n const checkString = tokenDateString + sep + tokenDataString;\n const checkSignature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');\n const encodedCheckSignature = base64url.default.encode(checkSignature);\n if (encodedCheckSignature !== tokenSignature) {\n debug(\n `getCheckedSignedTokenData(): FAIL - signature mismatch: checkSig=${encodedCheckSignature} != tokenSig=${tokenSignature}`,\n );\n return null;\n }\n\n // check the age if we have the maxAge parameter\n if (options.maxAge != null) {\n let tokenDate;\n try {\n tokenDate = new Date(parseInt(tokenDateString, 36));\n } catch (e) {\n debug(`getCheckedSignedTokenData(): FAIL - could not parse date: ${tokenDateString}`);\n return null;\n }\n const currentTime = Date.now();\n const elapsedTime = currentTime - tokenDate.getTime();\n if (elapsedTime > options.maxAge) {\n debug(\n `getCheckedSignedTokenData(): FAIL - too old: elapsedTime=${elapsedTime} > maxAge=${options.maxAge}`,\n );\n return null;\n }\n }\n\n // get the data\n let tokenDataJSON, tokenData;\n try {\n tokenDataJSON = base64url.default.decode(tokenDataString);\n } catch (e) {\n debug(`getCheckedSignedTokenData(): FAIL - could not base64 decode: ${tokenDateString}`);\n return null;\n }\n try {\n tokenData = JSON.parse(tokenDataJSON);\n } catch (e) {\n debug(`getCheckedSignedTokenData(): FAIL - could not parse JSON: ${tokenDataJSON}`);\n return null;\n }\n debug(`getCheckedSignedTokenData(): tokenData = ${tokenData}`);\n return tokenData;\n}\n\nexport function checkSignedToken(\n token: string,\n data: any,\n secretKey: string,\n options: CheckOptions = {},\n) {\n debug(`checkSignedToken(): token = ${token}`);\n debug(`checkSignedToken(): data = ${JSON.stringify(data)}`);\n debug(`checkSignedToken(): secretKey = ${secretKey}`);\n debug(`checkSignedToken(): options = ${JSON.stringify(options)}`);\n debug(`checkSignedToken(): data = ${JSON.stringify(data)}`);\n const tokenData = getCheckedSignedTokenData(token, secretKey, options);\n debug(`checkSignedToken(): tokenData = ${JSON.stringify(tokenData)}`);\n if (tokenData == null) return false;\n if (!_.isEqual(data, tokenData)) return false;\n return true;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@prairielearn/signed-token",
3
- "version": "1.0.15",
3
+ "version": "2.0.1",
4
+ "type": "module",
4
5
  "main": "dist/index.js",
5
6
  "repository": {
6
7
  "type": "git",
@@ -14,9 +15,9 @@
14
15
  "devDependencies": {
15
16
  "@prairielearn/tsconfig": "*",
16
17
  "@types/debug": "^4.1.12",
17
- "@types/node": "^20.12.2",
18
+ "@types/node": "^20.12.11",
18
19
  "mocha": "^10.4.0",
19
- "typescript": "^5.4.3"
20
+ "typescript": "^5.4.5"
20
21
  },
21
22
  "dependencies": {
22
23
  "base64url": "^3.0.1",
package/src/index.ts CHANGED
@@ -1,9 +1,10 @@
1
+ import crypto from 'node:crypto';
2
+
1
3
  import base64url from 'base64url';
2
- import debugModule from 'debug';
4
+ import debugfn from 'debug';
3
5
  import _ from 'lodash';
4
- import crypto from 'node:crypto';
5
6
 
6
- const debug = debugModule('prairielearn:csrf');
7
+ const debug = debugfn('prairielearn:csrf');
7
8
  const sep = '.';
8
9
 
9
10
  interface CheckOptions {
@@ -14,11 +15,11 @@ export function generateSignedToken(data: any, secretKey: string) {
14
15
  debug(`generateSignedToken(): data = ${JSON.stringify(data)}`);
15
16
  debug(`generateSignedToken(): secretKey = ${secretKey}`);
16
17
  const dataJSON = JSON.stringify(data);
17
- const dataString = base64url.encode(dataJSON);
18
+ const dataString = base64url.default.encode(dataJSON);
18
19
  const dateString = new Date().getTime().toString(36);
19
20
  const checkString = dateString + sep + dataString;
20
21
  const signature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');
21
- const encodedSignature = base64url.encode(signature);
22
+ const encodedSignature = base64url.default.encode(signature);
22
23
  debug(
23
24
  `generateSignedToken(): ${JSON.stringify({
24
25
  dataString,
@@ -58,7 +59,7 @@ export function getCheckedSignedTokenData(
58
59
  // check the signature
59
60
  const checkString = tokenDateString + sep + tokenDataString;
60
61
  const checkSignature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');
61
- const encodedCheckSignature = base64url.encode(checkSignature);
62
+ const encodedCheckSignature = base64url.default.encode(checkSignature);
62
63
  if (encodedCheckSignature !== tokenSignature) {
63
64
  debug(
64
65
  `getCheckedSignedTokenData(): FAIL - signature mismatch: checkSig=${encodedCheckSignature} != tokenSig=${tokenSignature}`,
@@ -88,7 +89,7 @@ export function getCheckedSignedTokenData(
88
89
  // get the data
89
90
  let tokenDataJSON, tokenData;
90
91
  try {
91
- tokenDataJSON = base64url.decode(tokenDataString);
92
+ tokenDataJSON = base64url.default.decode(tokenDataString);
92
93
  } catch (e) {
93
94
  debug(`getCheckedSignedTokenData(): FAIL - could not base64 decode: ${tokenDateString}`);
94
95
  return null;