Files
bigwo/test2/server/lib/token.js
2026-03-12 12:47:56 +08:00

172 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright 2025 Beijing Volcano Engine Technology Co., Ltd. All Rights Reserved.
* SPDX-license-identifier: BSD-3-Clause
*
* 火山引擎 RTC AccessToken 生成器
* 来源https://github.com/volcengine/rtc-aigc-demo/blob/main/Server/token.js
*/
var crypto = require('crypto');
var randomInt = Math.floor(Math.random() * 0xFFFFFFFF);
const VERSION = "001";
const VERSION_LENGTH = 3;
const APP_ID_LENGTH = 24;
privileges = {
PrivPublishStream: 0,
// not exported, do not use directly
privPublishAudioStream: 1,
privPublishVideoStream: 2,
privPublishDataStream: 3,
PrivSubscribeStream: 4,
};
module.exports.privileges = privileges;
// Initializes token struct by required parameters.
var AccessToken = function (appID, appKey, roomID, userID) {
let token = this;
this.appID = appID;
this.appKey = appKey;
this.roomID = roomID;
this.userID = userID;
this.issuedAt = Math.floor(new Date() / 1000);
this.nonce = randomInt;
this.expireAt = 0;
this.privileges = {};
// AddPrivilege adds permission for token with an expiration.
this.addPrivilege = function (privilege, expireTimestamp) {
if (token.privileges === undefined) {
token.privileges = {}
}
token.privileges[privilege] = expireTimestamp;
if (privilege === privileges.PrivPublishStream) {
token.privileges[privileges.privPublishVideoStream] = expireTimestamp;
token.privileges[privileges.privPublishAudioStream] = expireTimestamp;
token.privileges[privileges.privPublishDataStream] = expireTimestamp;
}
};
// ExpireTime sets token expire time, won't expire by default.
// The token will be invalid after expireTime no matter what privilege's expireTime is.
this.expireTime = function (expireTimestamp) {
token.expireAt = expireTimestamp;
};
this.packMsg = function () {
var bufM = new ByteBuf();
bufM.putUint32(token.nonce);
bufM.putUint32(token.issuedAt);
bufM.putUint32(token.expireAt);
bufM.putString(token.roomID);
bufM.putString(token.userID);
bufM.putTreeMapUInt32(token.privileges);
return bufM.pack()
};
// Serialize generates the token string
this.serialize = function () {
var bytesM = this.packMsg();
var signature = encodeHMac(token.appKey, bytesM);
var content = new ByteBuf().putBytes(bytesM).putBytes(signature).pack();
return (VERSION + token.appID + content.toString('base64'));
};
// Verify checks if this token valid, called by server side.
this.verify = function (key) {
if (token.expireAt > 0 && Math.floor(new Date() / 1000) > token.expireAt) {
return false
}
token.appKey = key;
return encodeHMac(token.appKey, this.packMsg()).toString() === token.signature;
}
};
module.exports.version = VERSION;
module.exports.AccessToken = AccessToken;
var encodeHMac = function (key, message) {
return crypto.createHmac('sha256', key).update(message).digest();
};
var ByteBuf = function () {
var that = {
buffer: Buffer.alloc(1024)
, position: 0
};
that.pack = function () {
var out = Buffer.alloc(that.position);
that.buffer.copy(out, 0, 0, out.length);
return out;
};
that.putUint16 = function (v) {
that.buffer.writeUInt16LE(v, that.position);
that.position += 2;
return that;
};
that.putUint32 = function (v) {
that.buffer.writeUInt32LE(v, that.position);
that.position += 4;
return that;
};
that.putBytes = function (bytes) {
that.putUint16(bytes.length);
bytes.copy(that.buffer, that.position);
that.position += bytes.length;
return that;
};
that.putString = function (str) {
return that.putBytes(Buffer.from(str));
};
that.putTreeMap = function (map) {
if (!map) {
that.putUint16(0);
return that;
}
that.putUint16(Object.keys(map).length);
for (var key in map) {
that.putUint16(key);
that.putString(map[key]);
}
return that;
};
that.putTreeMapUInt32 = function (map) {
if (!map) {
that.putUint16(0);
return that;
}
that.putUint16(Object.keys(map).length);
for (var key in map) {
that.putUint16(key);
that.putUint32(map[key]);
}
return that;
};
return that;
};