UNPKG

2.3 kBJavaScriptView Raw
1/**
2 * Authorization Token
3 * @module auth_token
4 */
5
6const crypto = require('crypto');
7const config = require('./config');
8
9function digest(message, key) {
10 return crypto.createHmac("sha256", new Buffer(key, "hex")).update(message).digest('hex');
11}
12
13/**
14 * Escape url using lowercase hex code
15 * @param {string} url a url string
16 * @return {string} escaped url
17 */
18function escapeToLower(url) {
19 return encodeURIComponent(url).replace(/%../g, function(match) {
20 return match.toLowerCase();
21 });
22}
23
24/**
25 * Auth token options
26 * @typedef {object} authTokenOptions
27 * @property {string} [token_name="__cld_token__"] The name of the token.
28 * @property {string} key The secret key required to sign the token.
29 * @property {string} ip The IP address of the client.
30 * @property {number} start_time=now The start time of the token in seconds from epoch.
31 * @property {string} expiration The expiration time of the token in seconds from epoch.
32 * @property {string} duration The duration of the token (from start_time).
33 * @property {string} acl The ACL for the token.
34 * @property {string} url The URL to authentication in case of a URL token.
35 *
36 */
37
38/**
39 * Generate an authorization token
40 * @param {authTokenOptions} options
41 * @returns {string} the authorization token
42 */
43module.exports = function(options) {
44 const tokenName = options.token_name ? options.token_name : "__cld_token__";
45 if (options.expiration == null) {
46 if (options.duration != null) {
47 let start = options.start_time != null ? options.start_time : Math.round(Date.now() / 1000);
48 options.expiration = start + options.duration;
49 } else {
50 throw new Error("Must provide either expiration or duration");
51 }
52 }
53 let tokenParts = [];
54 if (options.ip != null) {
55 tokenParts.push(`ip=${options.ip}`);
56 }
57 if (options.start_time != null) {
58 tokenParts.push(`st=${options.start_time}`);
59 }
60 tokenParts.push(`exp=${options.expiration}`);
61 if (options.acl != null) {
62 tokenParts.push(`acl=${escapeToLower(options.acl)}`);
63 }
64 let toSign = [...tokenParts];
65 if (options.url) {
66 let url = escapeToLower(options.url);
67 toSign.push(`url=${url}`);
68 }
69 let auth = digest(toSign.join("~"), options.key);
70 tokenParts.push(`hmac=${auth}`);
71 return `${tokenName}=${tokenParts.join('~')}`;
72};