@prairielearn/signed-token 2.0.17 → 2.0.19

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.19
4
+
5
+ ### Patch Changes
6
+
7
+ - c72a4b8: Upgrade dependencies
8
+
9
+ ## 2.0.18
10
+
11
+ ### Patch Changes
12
+
13
+ - f571b40: Upgrade all JavaScript dependencies
14
+
3
15
  ## 2.0.17
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ export function generateSignedToken(data, secretKey) {
9
9
  debug(`generateSignedToken(): secretKey = ${secretKey}`);
10
10
  const dataJSON = JSON.stringify(data);
11
11
  const dataString = base64url.default.encode(dataJSON);
12
- const dateString = new Date().getTime().toString(36);
12
+ const dateString = Date.now().toString(36);
13
13
  const checkString = dateString + sep + dataString;
14
14
  const signature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');
15
15
  const encodedSignature = base64url.default.encode(signature);
@@ -52,7 +52,7 @@ export function getCheckedSignedTokenData(token, secretKey, options = {}) {
52
52
  if (options.maxAge != null) {
53
53
  let tokenDate;
54
54
  try {
55
- tokenDate = new Date(parseInt(tokenDateString, 36));
55
+ tokenDate = new Date(Number.parseInt(tokenDateString, 36));
56
56
  }
57
57
  catch {
58
58
  debug(`getCheckedSignedTokenData(): FAIL - could not parse date: ${tokenDateString}`);
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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","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 (typeof token !== 'string') {\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 {\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 {\n debug(`getCheckedSignedTokenData(): FAIL - could not base64 decode: ${tokenDateString}`);\n return null;\n }\n try {\n tokenData = JSON.parse(tokenDataJSON);\n } catch {\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"]}
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 = Date.now().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 (typeof token !== 'string') {\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(Number.parseInt(tokenDateString, 36));\n } catch {\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 {\n debug(`getCheckedSignedTokenData(): FAIL - could not base64 decode: ${tokenDateString}`);\n return null;\n }\n try {\n tokenData = JSON.parse(tokenDataJSON);\n } catch {\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,6 @@
1
1
  {
2
2
  "name": "@prairielearn/signed-token",
3
- "version": "2.0.17",
3
+ "version": "2.0.19",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,13 +14,13 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "base64url": "^3.0.1",
17
- "debug": "^4.4.1",
17
+ "debug": "^4.4.3",
18
18
  "lodash": "^4.17.21"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@prairielearn/tsconfig": "^0.0.0",
22
22
  "@types/debug": "^4.1.12",
23
- "@types/node": "^22.17.0",
24
- "typescript": "^5.9.2"
23
+ "@types/node": "^22.18.8",
24
+ "typescript": "^5.9.3"
25
25
  }
26
26
  }
package/src/index.ts CHANGED
@@ -16,7 +16,7 @@ export function generateSignedToken(data: any, secretKey: string) {
16
16
  debug(`generateSignedToken(): secretKey = ${secretKey}`);
17
17
  const dataJSON = JSON.stringify(data);
18
18
  const dataString = base64url.default.encode(dataJSON);
19
- const dateString = new Date().getTime().toString(36);
19
+ const dateString = Date.now().toString(36);
20
20
  const checkString = dateString + sep + dataString;
21
21
  const signature = crypto.createHmac('sha256', secretKey).update(checkString).digest('hex');
22
22
  const encodedSignature = base64url.default.encode(signature);
@@ -71,7 +71,7 @@ export function getCheckedSignedTokenData(
71
71
  if (options.maxAge != null) {
72
72
  let tokenDate;
73
73
  try {
74
- tokenDate = new Date(parseInt(tokenDateString, 36));
74
+ tokenDate = new Date(Number.parseInt(tokenDateString, 36));
75
75
  } catch {
76
76
  debug(`getCheckedSignedTokenData(): FAIL - could not parse date: ${tokenDateString}`);
77
77
  return null;