Skip to content

Commit

Permalink
Merge pull request #17 from barseghyanartur/dev
Browse files Browse the repository at this point in the history
Add signURL, update docs and changelog (#16)
  • Loading branch information
barseghyanartur committed Nov 28, 2023
2 parents 8b9e54d + 9ee9897 commit b4e8b7a
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GITHUB_TOKEN
COVERALLS_REPO_TOKEN
28 changes: 22 additions & 6 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ name: Node.js CI

on:
push:
branches: [ master ]
branches: [ main, dev ]
pull_request:
branches: [ master ]
branches: [ main, dev ]

jobs:
build:
Expand All @@ -17,17 +17,33 @@ jobs:
strategy:
matrix:
node-version: [
# 12.x,
14.x,
16.x
16.x,
18.x
]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
- name: Coveralls GitHub Action
uses: coverallsapp/github-action@v2
with:
parallel: true
flag-name: run-${{ join(matrix.*, '-') }}

finish:
needs: build
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
carryforward: "run-14.x,run-16.x,run-18.x"
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ major.minor[.revision]
0.3.4 to 0.4).
- All backwards incompatible changes are mentioned in this document.

## 0.1.3

2023-11-28

- Add `signURL` functionality.

## 0.1.2

2021-11-19
Expand Down
33 changes: 28 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ validating) dictionaries.
[![NPM Version](https://img.shields.io/npm/v/skajs.svg)](https://www.npmjs.com/package/skajs)
[![Supported NodeJS versions](https://img.shields.io/node/v/skajs.svg)](https://www.npmjs.com/package/skajs)
[![Build Status](https://github.com/barseghyanartur/skajs/actions/workflows/node.js.yml/badge.svg)](https://github.com/barseghyanartur/skajs/actions)
[![Coverage Status](https://coveralls.io/repos/github/barseghyanartur/skajs/badge.svg?branch=main)](https://coveralls.io/github/barseghyanartur/skajs?branch=main)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/barseghyanartur/skajs/#License)

## Key concepts
Expand Down Expand Up @@ -38,6 +39,7 @@ Secret Key. It's being checked whether signature is valid and not expired.

## Features

- Sign URLs.
- Sign dictionaries.
- Validate signed dictionaries.

Expand Down Expand Up @@ -82,25 +84,25 @@ node examples.mjs

#### Sender side

Signing dictionaries is as simple as follows.
Signing dictionaries and URLs is as simple as follows.

##### Required imports.

**CommonJS**

```javascript
const { signatureToDict } = require("skajs");
const { signatureToDict, signURL } = require("skajs");
```

**ESM**

```javascript
import { signatureToDict } from "skajs";
import { signatureToDict, signURL } from "skajs";
```

##### Sign data

**Sample usage:**
**Sample usage, sign a dictionary:**

```javascript
const signatureDict = signatureToDict("user", "your-secret_key");
Expand Down Expand Up @@ -144,6 +146,18 @@ const signatureDict = signatureToDict(
last_name: 'Doe',
}
```

**Sample usage, sign a URL:**

```javascript
const signedURL = signURL("user", "your-secret_key", "http://e.com/api/");
```

**Sample output:**

```javascript
'http://e.com/api/?valid_until=1378045287.0&auth_user=user&signature=YlZpLFsjUKBalL4x5trhkeEgqE8%3D'
```
**Options and defaults:**

The `signatureToDict` function accepts an optional `options` argument.
Expand Down Expand Up @@ -227,7 +241,16 @@ import { validateSignedRequestData } from "skajs";
##### Validate signed requests

Validating the signed request data. Note, that `data` value is expected to
be a dictionary; `request.GET` is given as an example.
be a dictionary; `request.POST` is given as an example.

```javascript
validationResult = validateSignedRequestData(
request.POST, // Note, that ``request.POST`` is given as example.
"your-secret_key"
);
```

In case of signed URLs, it could look as follows:

```javascript
validationResult = validateSignedRequestData(
Expand Down
118 changes: 118 additions & 0 deletions commonjs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ const DEFAULT_VALID_UNTIL_PARAM = "valid_until";
*/
const DEFAULT_EXTRA_PARAM = "extra";

/**
* Suffix to add after the ``url`` and before the appended
* signature params when using ``signURL`` function/method.
*/
const DEFAULT_URL_SUFFIX = "?";

/**
* *******************************************
* *************** Helpers *****************
Expand Down Expand Up @@ -89,6 +95,33 @@ function defaultValueDumper(value) {
return value;
}

/**
* `urlencode`.
*
* @param {Object} data
* @param {boolean} quoted
* @param {Function} valueDumper
* @returns {string}
*/
function urlEncode(data, quoted = true, valueDumper = defaultValueDumper) {
console.log("data: ");
console.log(data);

let orderedData = data;
console.log("orderedData: ");
console.log(orderedData);

let _sorted = [];
for (const [key, value] of Object.entries(orderedData)) {
_sorted.push(`${key}=${valueDumper(value)}`);
}
let _res = _sorted.join("&");
if (quoted) {
_res = encodeURIComponent(_res);
}
return _res;
}

/**
* Sorted `urlencode`.
*
Expand Down Expand Up @@ -495,6 +528,36 @@ class RequestHelper {
this.signatureCls = signatureCls;
}

/**
* Signature to URL.
*
* @param {AbstractSignature} signature
* @param {string} url
* @param {string} suffix
* @param {Function} valueDumper
* @returns {{}}
*/
signatureToURL(
signature,
url,
suffix = DEFAULT_URL_SUFFIX,
valueDumper = defaultValueDumper,
) {
let data = {};

data[this.signatureParam] = signature.signature;
data[this.authUserParam] = signature.authUser;
data[this.validUntilParam] = signature.validUntil;
data[this.extraParam] = dictKeys(signature.extra, true);

let combined = {
...data,
...signature.extra,
};

return `${url}${suffix}${sortedURLEncode(combined, false, valueDumper)}`;
}

/**
* Signature to dict.
*
Expand Down Expand Up @@ -717,6 +780,58 @@ function getSignatureToDictDefaults(lifetime = null) {
};
}

/**
* Sign URL.
*
* @param {string} authUser
* @param {string} secretKey
* @param {string} url
* @param {Object} extra
* @param {Object} options
* @returns {{}}
*/
function signURL(
authUser,
secretKey,
url,
extra = null,
options = {}
) {
let lifetime = options["lifetime"] ?? SIGNATURE_LIFETIME;
let defaults = getSignatureToDictDefaults(lifetime);
options = {
...defaults,
...options
};
let validUntil = options["validUntil"];
let signatureParam = options["signatureParam"];
let authUserParam = options["authUserParam"];
let validUntilParam = options["validUntilParam"];
let extraParam = options["extraParam"];
let valueDumper = options["valueDumper"];
let signatureCls = options["signatureCls"];

let signature = generateSignature(
authUser,
secretKey,
validUntil,
lifetime,
extra,
valueDumper,
signatureCls,
);

const requestHelper = new RequestHelper(
signatureParam,
authUserParam,
validUntilParam,
extraParam,
signatureCls
);

return requestHelper.signatureToURL(signature, url);
}

/**
* Signature to dict.
*
Expand Down Expand Up @@ -828,7 +943,9 @@ exports.DEFAULT_SIGNATURE_PARAM = DEFAULT_SIGNATURE_PARAM;
exports.DEFAULT_AUTH_USER_PARAM = DEFAULT_AUTH_USER_PARAM;
exports.DEFAULT_VALID_UNTIL_PARAM = DEFAULT_VALID_UNTIL_PARAM;
exports.DEFAULT_EXTRA_PARAM = DEFAULT_EXTRA_PARAM;
exports.DEFAULT_URL_SUFFIX = DEFAULT_URL_SUFFIX;
exports.isObject = isObject;
exports.urlEncode = urlEncode;
exports.sortedURLEncode = sortedURLEncode;
exports.convertNumberToHex = convertNumberToHex;
exports.encodeValue = encodeValue;
Expand All @@ -847,6 +964,7 @@ exports.unixTimestampToDate = unixTimestampToDate;
exports.getBase = getBase;
exports.makeHash = makeHash;
exports.generateSignature = generateSignature;
exports.signURL = signURL;
exports.signatureToDict = signatureToDict;
exports.validateSignedRequestData = validateSignedRequestData;
exports.SignatureValidationResult = SignatureValidationResult;
Expand Down
Loading

0 comments on commit b4e8b7a

Please sign in to comment.