Initial commit

This commit is contained in:
talksik
2021-12-29 01:57:42 -08:00
commit ce39a60b42
4634 changed files with 997667 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
# How to use
## Install
```shell
npm i agora-access-token
```
## Import
```javascript
const {RtcTokenBuilder, RtmTokenBuilder, RtcRole, RtmRole} = require('agora-access-token')
```
### Generate
```javascript
// Rtc Examples
const appID = '<Your app ID>';
const appCertificate = '<Your app certificate>';
const channelName = '<The channel this token is generated for>';
const uid = 2882341273;
const account = "2882341273";
const role = RtcRole.PUBLISHER;
const expirationTimeInSeconds = 3600
const currentTimestamp = Math.floor(Date.now() / 1000)
const privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds
// IMPORTANT! Build token with either the uid or with the user account. Comment out the option you do not want to use below.
// Build token with uid
const tokenA = RtcTokenBuilder.buildTokenWithUid(appID, appCertificate, channelName, uid, role, privilegeExpiredTs);
console.log("Token With Integer Number Uid: " + tokenA);
// Build token with user account
const tokenB = RtcTokenBuilder.buildTokenWithAccount(appID, appCertificate, channelName, account, role, privilegeExpiredTs);
console.log("Token With UserAccount: " + tokenB);
```
+89
View File
@@ -0,0 +1,89 @@
export namespace RtcRole {
export const PUBLISHER: number;
export const SUBSCRIBER: number;
}
export namespace RtcTokenBuilder {
/**
* Builds an RTC token using an Integer uid.
* @param {*} appID The App ID issued to you by Agora.
* @param {*} appCertificate Certificate of the application that you registered in the Agora Dashboard.
* @param {*} channelName The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are:
* - The 26 lowercase English letters: a to z.
* - The 26 uppercase English letters: A to Z.
* - The 10 digits: 0 to 9.
* - The space.
* - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
* @param {*} uid User ID. A 32-bit unsigned integer with a value ranging from 1 to (2^32-1).
* @param {*} role See #userRole.
* - Role.PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
* - Role.SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in). In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
* @param {*} privilegeExpiredTs represented by the number of seconds elapsed since 1/1/1970. If, for example, you want to access the Agora Service within 10 minutes after the token is generated, set expireTimestamp as the current timestamp + 600 (seconds).
* @return The new Token.
*/
export function buildTokenWithUid(appID: string, appCertificate: string, channelName: string, uid: number, role: number, privilegeExpiredTs: number): string;
/**
* Builds an RTC token using an Integer uid.
* @param {*} appID The App ID issued to you by Agora.
* @param {*} appCertificate Certificate of the application that you registered in the Agora Dashboard.
* @param {*} channelName The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are:
* - The 26 lowercase English letters: a to z.
* - The 26 uppercase English letters: A to Z.
* - The 10 digits: 0 to 9.
* - The space.
* - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
* @param {*} account The user account.
* @param {*} role See #userRole.
* - Role.PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
* - Role.SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in). In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
* @param {*} privilegeExpiredTs represented by the number of seconds elapsed since 1/1/1970. If, for example, you want to access the Agora Service within 10 minutes after the token is generated, set expireTimestamp as the current timestamp + 600 (seconds).
* @return The new Token.
*/
export function buildTokenWithAccount(appID: string, appCertificate: string, channelName: string, account: string, role: number, privilegeExpiredTs: number): string;
}
export namespace RtmTokenBuilder {
/**
* @param {*} appID: The App ID issued to you by Agora. Apply for a new App ID from
* Agora Dashboard if it is missing from your kit. See Get an App ID.
* @param {*} appCertificate: Certificate of the application that you registered in
* the Agora Dashboard. See Get an App Certificate.
* @param {*} account: The user account.
* @param {*} role : Role_Publisher = 1: A broadcaster (host) in a live-broadcast profile.
* Role_Subscriber = 2: (Default) A audience in a live-broadcast profile.
* @param {*} privilegeExpiredTs : represented by the number of seconds elapsed since
* 1/1/1970. If, for example, you want to access the
* Agora Service within 10 minutes after the token is
* generated, set expireTimestamp as the current
* @return token
*/
export function buildToken(appID: string, appCertificate: string, account: string | number, role: number, privilegeExpiredTs: number): string;
}
export namespace RtmRole {
export const Rtm_User: number;
}
export namespace RtmTokenBuilder {
/**
* @param {*} appID: The App ID issued to you by Agora. Apply for a new App ID from
* Agora Dashboard if it is missing from your kit. See Get an App ID.
* @param {*} appCertificate: Certificate of the application that you registered in
* the Agora Dashboard. See Get an App Certificate.
* @param {*} account: The user account.
* @param {*} role : Role_Publisher = 1: A broadcaster (host) in a live-broadcast profile.
* Role_Subscriber = 2: (Default) A audience in a live-broadcast profile.
* @param {*} privilegeExpiredTs : represented by the number of seconds elapsed since
* 1/1/1970. If, for example, you want to access the
* Agora Service within 10 minutes after the token is
* generated, set expireTimestamp as the current
* @return token
*/
export function buildToken(appID: string, appCertificate: string, account: string | number, role: number, privilegeExpiredTs: number): string;
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
RtcTokenBuilder: require('./src/RtcTokenBuilder').RtcTokenBuilder,
RtcRole: require('./src/RtcTokenBuilder').Role,
RtmTokenBuilder: require('./src/RtmTokenBuilder').RtmTokenBuilder,
RtmRole: require('./src/RtmTokenBuilder').Role
}
+43
View File
@@ -0,0 +1,43 @@
{
"_from": "agora-access-token",
"_id": "[email protected]",
"_inBundle": false,
"_integrity": "sha512-RtOIvi4PqV1ok3rdnopMZeVwiUqZgG9Pp56kqxJc5cU/+ljRBzs1Al+IThD5ahm528dGsdY1TyP1bJdqmgBCbQ==",
"_location": "/agora-access-token",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "agora-access-token",
"name": "agora-access-token",
"escapedName": "agora-access-token",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/agora-access-token/-/agora-access-token-2.0.4.tgz",
"_shasum": "6a6d5996011f6000035d923342296c2594d94f82",
"_spec": "agora-access-token",
"_where": "/Users/talksik/Development/nirvana-server",
"author": "",
"bundleDependencies": false,
"dependencies": {
"crc-32": "1.2.0",
"cuint": "0.2.2"
},
"deprecated": false,
"description": "```shell npm i agora-access-token ```",
"homepage": "https://github.com/AgoraIO/Tools/tree/master/DynamicKey/AgoraDynamicKey/nodejs",
"license": "ISC",
"main": "index.js",
"name": "agora-access-token",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"types": "index.d.ts",
"version": "2.0.4"
}
+46
View File
@@ -0,0 +1,46 @@
const {RtcTokenBuilder, RtmTokenBuilder, RtcRole, RtmRole} = require('./index')
const generateRtcToken = () => {
// Rtc Examples
const appID = '970CA35de60c44645bbae8a215061b33';
const appCertificate = '5CFd2fd1755d40ecb72977518be15d3b';
const channelName = '7d72365eb983485397e3e3f9d460bdda';
const uid = 2882341273;
const account = "2882341273";
const role = RtcRole.PUBLISHER;
const expirationTimeInSeconds = 3600
const currentTimestamp = Math.floor(Date.now() / 1000)
const privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds
// IMPORTANT! Build token with either the uid or with the user account. Comment out the option you do not want to use below.
// Build token with uid
const tokenA = RtcTokenBuilder.buildTokenWithUid(appID, appCertificate, channelName, uid, role, privilegeExpiredTs);
console.log("Token With Integer Number Uid: " + tokenA);
// Build token with user account
const tokenB = RtcTokenBuilder.buildTokenWithAccount(appID, appCertificate, channelName, account, role, privilegeExpiredTs);
console.log("Token With UserAccount: " + tokenB);
}
const generateRtmToken = () => {
// Rtm Examples
const appID = "970CA35de60c44645bbae8a215061b33";
const appCertificate = "5CFd2fd1755d40ecb72977518be15d3b";
const account = "test_user_id";
const expirationTimeInSeconds = 3600
const currentTimestamp = Math.floor(Date.now() / 1000)
const privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds
const token = RtmTokenBuilder.buildToken(appID, appCertificate, account, RtmRole, privilegeExpiredTs);
console.log("Rtm Token: " + token);
}
generateRtcToken()
generateRtmToken()
+12
View File
@@ -0,0 +1,12 @@
- **RtcTokenBuilder.js**: Source code for generating a token for the following SDKs:
- Agora Native SDK v2.1+
- Agora Web SDK v2.4+
- Agora Recording SDK v2.1+
- Agora RTSA SDK
> The Agora RTSA SDK supports joining multiple channels. If you join multiple channels at the same time, then you MUST generate a specific token for each channel you join.
- **RtmTokenBuilder.js**: Source code for generating a token for the Agora RTM SDK.
- **AccessToken.js**: Implements all the underlying algorithms for generating a token. Both **RtcTokenBuilder.js** and **RtmTokenBuilder.js** are a wrapper of **AccessToken.js** and have much easier-to-use APIs. We recommend using **RtcTokenBuilder.js** for generating an RTC token or **RtmTokenBuilder.js** for an RTM token.
+25
View File
@@ -0,0 +1,25 @@
const RtcTokenBuilder = require('../src/RtcTokenBuilder').RtcTokenBuilder;
const RtcRole = require('../src/RtcTokenBuilder').Role;
const appID = '970CA35de60c44645bbae8a215061b33';
const appCertificate = '5CFd2fd1755d40ecb72977518be15d3b';
const channelName = '7d72365eb983485397e3e3f9d460bdda';
const uid = 2882341273;
const account = "2882341273";
const role = RtcRole.PUBLISHER;
const expirationTimeInSeconds = 3600
const currentTimestamp = Math.floor(Date.now() / 1000)
const privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds
// IMPORTANT! Build token with either the uid or with the user account. Comment out the option you do not want to use below.
// Build token with uid
const tokenA = RtcTokenBuilder.buildTokenWithUid(appID, appCertificate, channelName, uid, role, privilegeExpiredTs);
console.log("Token With Integer Number Uid: " + tokenA);
// Build token with user account
const tokenB = RtcTokenBuilder.buildTokenWithAccount(appID, appCertificate, channelName, account, role, privilegeExpiredTs);
console.log("Token With UserAccount: " + tokenB);
+14
View File
@@ -0,0 +1,14 @@
const RtmTokenBuilder = require('../src/RtmTokenBuilder').RtmTokenBuilder;
const RtmRole = require('../src/RtmTokenBuilder').Role;
const Priviledges = require('../src/AccessToken').priviledges;
const appID = "970CA35de60c44645bbae8a215061b33";
const appCertificate = "5CFd2fd1755d40ecb72977518be15d3b";
const account = "test_user_id";
const expirationTimeInSeconds = 3600
const currentTimestamp = Math.floor(Date.now() / 1000)
const privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds
const token = RtmTokenBuilder.buildToken(appID, appCertificate, account, RtmRole, privilegeExpiredTs);
console.log("Rtm Token: " + token);
+66
View File
@@ -0,0 +1,66 @@
//var fs = require('fs');
//var https = require('https');
var http = require('http');
var express = require('express');
var {RtcTokenBuilder, RtmTokenBuilder, RtcRole, RtmRole} = require('agora-access-token')
var PORT = 8080;
// Fill the appID and appCertificate key given by Agora.io
var appID = "<YOUR APP ID>";
var appCertificate = "<YOUR APP CERTIFICATE>";
// token expire time, hardcode to 3600 seconds = 1 hour
var expirationTimeInSeconds = 3600
var role = RtcRole.PUBLISHER
var app = express();
app.disable('x-powered-by');
app.set('port', PORT);
app.use(express.favicon());
app.use(app.router);
var generateRtcToken = function(req, resp) {
var currentTimestamp = Math.floor(Date.now() / 1000)
var privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds
var channelName = req.query.channelName;
// use 0 if uid is not specified
var uid = req.query.uid || 0
if (!channelName) {
return resp.status(400).json({ 'error': 'channel name is required' }).send();
}
var key = RtcTokenBuilder.buildTokenWithUid(appID, appCertificate, channelName, uid, role, privilegeExpiredTs);
resp.header("Access-Control-Allow-Origin", "*")
//resp.header("Access-Control-Allow-Origin", "http://ip:port")
return resp.json({ 'key': key }).send();
};
var generateRtmToken = function(req, resp) {
var currentTimestamp = Math.floor(Date.now() / 1000)
var privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds
var account = req.query.account;
if (!account) {
return resp.status(400).json({ 'error': 'account is required' }).send();
}
var key = RtmTokenBuilder.buildToken(appID, appCertificate, account, RtmRole, privilegeExpiredTs);
resp.header("Access-Control-Allow-Origin", "*")
//resp.header("Access-Control-Allow-Origin", "http://ip:port")
return resp.json({ 'key': key }).send();
};
app.get('/rtcToken', generateRtcToken);
app.get('/rtmToken', generateRtmToken);
http.createServer(app).listen(app.get('port'), function() {
console.log('AgoraSignServer starts at ' + app.get('port'));
});
//https.createServer(credentials, app).listen(app.get('port') + 1, function() {
// console.log('AgoraSignServer starts at ' + (app.get('port') + 1));
//});
+26
View File
@@ -0,0 +1,26 @@
# How to use
## Fill in your vendor information
Open *DemoServer.js* and replace <YOUR APP ID> and <YOUR APP CERTIFICATE> with your value
```
// Fill the appID and appCertificate key given by Agora.io
var appID = "<YOUR APP ID>";
var appCertificate = "<YOUR APP CERTIFICATE>";
```
## Install Dependencies
```shell
npm i
node DemoServer.js
```
## Generate Token
### Generate RTC Token
```shell
curl http://localhost:8080/rtcToken?channelName=test
```
### Generate RTM Token
```shell
curl http://localhost:8080/rtmToken?account=testAccount
```
+14
View File
@@ -0,0 +1,14 @@
{
"name": "agora_sign_server",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"agora-access-token": "^2.0.1",
"express": "3.4.8"
},
"main": "DemoServer.js",
"author": "agora"
}
+258
View File
@@ -0,0 +1,258 @@
var crypto = require('crypto');
var crc32 = require('crc-32');
var UINT32 = require('cuint').UINT32;
var version = "006";
var randomInt = Math.floor(Math.random() * 0xFFFFFFFF);
const VERSION_LENGTH = 3;
const APP_ID_LENGTH = 32;
var AccessToken = function (appID, appCertificate, channelName, uid) {
let token = this;
this.appID = appID;
this.appCertificate = appCertificate;
this.channelName = channelName;
this.messages = {};
this.salt = randomInt;
this.ts = Math.floor(new Date() / 1000) + (24 * 3600);
if (uid === 0) {
this.uid = "";
} else {
this.uid = `${uid}`;
}
this.build = function () {
var m = Message({
salt: token.salt
, ts: token.ts
, messages: token.messages
}).pack();
var toSign = Buffer.concat(
[Buffer.from(token.appID, 'utf8'),
Buffer.from(token.channelName, 'utf8'),
Buffer.from(token.uid, 'utf8'),
m]);
var signature = encodeHMac(token.appCertificate, toSign);
var crc_channel = UINT32(crc32.str(token.channelName)).and(UINT32(0xffffffff)).toNumber();
var crc_uid = UINT32(crc32.str(token.uid)).and(UINT32(0xffffffff)).toNumber();
var content = AccessTokenContent({
signature: signature,
crc_channel: crc_channel,
crc_uid: crc_uid,
m: m
}).pack();
return (version + token.appID + content.toString('base64'));
}
this.addPriviledge = function (priviledge, expireTimestamp) {
token.messages[priviledge] = expireTimestamp;
};
this.fromString = function (originToken) {
try {
originVersion = originToken.substr(0, VERSION_LENGTH);
if(originVersion != version) {
return false;
}
var originAppID = originToken.substr(VERSION_LENGTH, (VERSION_LENGTH + APP_ID_LENGTH));
var originContent = originToken.substr((VERSION_LENGTH + APP_ID_LENGTH));
var originContentDecodedBuf = Buffer.from(originContent, 'base64');
var content = unPackContent(originContentDecodedBuf);
this.signature = content.signature;
this.crc_channel_name = content.crc_channel_name;
this.crc_uid = content.crc_uid;
this.m = content.m;
var msgs = unPackMessages(this.m);
this.salt = msgs.salt;
this.ts = msgs.ts;
this.messages = msgs.messages;
} catch (err) {
console.log(err);
return false;
}
return true;
};
};
module.exports.version = version;
module.exports.AccessToken = AccessToken;
module.exports.priviledges = {
kJoinChannel: 1,
kPublishAudioStream: 2,
kPublishVideoStream: 3,
kPublishDataStream: 4,
kPublishAudiocdn: 5,
kPublishVideoCdn: 6,
kRequestPublishAudioStream: 7,
kRequestPublishVideoStream: 8,
kRequestPublishDataStream: 9,
kInvitePublishAudioStream: 10,
kInvitePublishVideoStream: 11,
kInvitePublishDataStream: 12,
kAdministrateChannel: 101,
kRtmLogin: 1000
};
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.buffer.fill(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;
}
var ReadByteBuf = function(bytes) {
var that = {
buffer: bytes
, position: 0
};
that.getUint16 = function () {
var ret = that.buffer.readUInt16LE(that.position);
that.position += 2;
return ret;
};
that.getUint32 = function () {
var ret = that.buffer.readUInt32LE(that.position);
that.position += 4;
return ret;
};
that.getString = function () {
var len = that.getUint16();
var out = Buffer.alloc(len);
that.buffer.copy(out, 0, that.position, (that.position + len));
that.position += len;
return out;
};
that.getTreeMapUInt32 = function () {
var map = {};
var len = that.getUint16();
for( var i = 0; i < len; i++) {
var key = that.getUint16();
var value = that.getUint32();
map[key] = value;
}
return map;
};
return that;
}
var AccessTokenContent = function (options) {
options.pack = function () {
var out = new ByteBuf();
return out.putString(options.signature)
.putUint32(options.crc_channel)
.putUint32(options.crc_uid)
.putString(options.m).pack();
}
return options;
}
var Message = function (options) {
options.pack = function () {
var out = new ByteBuf();
var val = out
.putUint32(options.salt)
.putUint32(options.ts)
.putTreeMapUInt32(options.messages).pack();
return val;
}
return options;
}
var unPackContent = function(bytes) {
var readbuf = new ReadByteBuf(bytes);
return AccessTokenContent({
signature: readbuf.getString(),
crc_channel_name: readbuf.getUint32(),
crc_uid: readbuf.getUint32(),
m: readbuf.getString()
});
}
var unPackMessages = function(bytes) {
var readbuf = new ReadByteBuf(bytes);
return Message({
salt: readbuf.getUint32(),
ts: readbuf.getUint32(),
messages: readbuf.getTreeMapUInt32()
});
}
+173
View File
@@ -0,0 +1,173 @@
var crypto = require('crypto');
var version = "005";
var noUpload = "0";
var audioVideoUpload = "3";
var generatePublicSharingKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
channelName=channelName.toString();
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, PUBLIC_SHARING_SERVICE);
};
var generateRecordingKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
channelName=channelName.toString();
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, RECORDING_SERVICE);
};
var generateMediaChannelKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
channelName=channelName.toString();
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, MEDIA_CHANNEL_SERVICE);
};
var generateInChannelPermissionKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, permission) {
var extra = {};
extra[ALLOW_UPLOAD_IN_CHANNEL] = permission;
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, extra, IN_CHANNEL_PERMISSION);
};
var generateDynamicKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, extra, serviceType) {
var signature = generateSignature5(appCertificate, serviceType, appID, unixTs, randomInt, channelName, uid, expiredTs, extra);
var content = DynamicKey5Content({
serviceType: serviceType
, signature: signature
, appID: hexDecode(appID)
, unixTs: unixTs
, salt: randomInt
, expiredTs: expiredTs
, extra: extra}).pack();
return version + content.toString('base64');
};
module.exports.version = version;
module.exports.noUpload = noUpload;
module.exports.audioVideoUpload = audioVideoUpload;
module.exports.generatePublicSharingKey = generatePublicSharingKey;
module.exports.generateRecordingKey = generateRecordingKey;
module.exports.generateMediaChannelKey = generateMediaChannelKey;
module.exports.generateInChannelPermissionKey = generateInChannelPermissionKey;
module.exports.generateDynamicKey = generateDynamicKey;
var generateSignature5 = function(appCertificate, serviceType, appID, unixTs, randomInt, channelName, uid, expiredTs, extra) {
// decode hex to avoid case problem
var rawAppID = hexDecode(appID);
var rawAppCertificate = hexDecode(appCertificate);
var m = Message({
serviceType: serviceType
, appID: rawAppID
, unixTs: unixTs
, salt: randomInt
, channelName: channelName
, uid: uid
, expiredTs: expiredTs
, extra: extra
});
var toSign = m.pack();
return encodeHMac(rawAppCertificate, toSign);
};
var encodeHMac = function(key, message) {
return crypto.createHmac('sha1', key).update(message).digest('hex').toUpperCase();
};
var hexDecode = function(str) {
return Buffer.from(str, 'hex');
};
var ByteBuf = function() {
var that = {
buffer: Buffer.alloc(1024)
, position: 0
};
that.buffer.fill(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;
};
return that;
}
var DynamicKey5Content = function(options) {
options.pack = function() {
var out = ByteBuf();
return out.putUint16(options.serviceType)
.putString(options.signature)
.putBytes(options.appID)
.putUint32(options.unixTs)
.putUint32(options.salt)
.putUint32(options.expiredTs)
.putTreeMap(options.extra)
.pack();
}
return options;
}
var Message = function(options) {
options.pack = function() {
var out = ByteBuf();
return out.putUint16(options.serviceType)
.putBytes(options.appID)
.putUint32(options.unixTs)
.putUint32(options.salt)
.putString(options.channelName)
.putUint32(options.uid)
.putUint32(options.expiredTs)
.putTreeMap(options.extra)
.pack();
}
return options;
}
// InChannelPermissionKey
var ALLOW_UPLOAD_IN_CHANNEL = 1;
// Service Type
var MEDIA_CHANNEL_SERVICE = 1;
var RECORDING_SERVICE = 2;
var PUBLIC_SHARING_SERVICE = 3;
var IN_CHANNEL_PERMISSION = 4;
+75
View File
@@ -0,0 +1,75 @@
const AccessToken = require('../src/AccessToken').AccessToken
const Priviledges = require('../src/AccessToken').priviledges
const Role = {
// DEPRECATED. Role::ATTENDEE has the same privileges as Role.PUBLISHER.
ATTENDEE: 0,
// RECOMMENDED. Use this role for a voice/video call or a live broadcast, if your scenario does not require authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in).
PUBLISHER: 1,
/* Only use this role if your scenario require authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in).
* @note In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role.SUBSCRIBER still has the same privileges as Role.PUBLISHER.
*/
SUBSCRIBER: 2,
// DEPRECATED. Role.ADMIN has the same privileges as Role.PUBLISHER.
ADMIN: 101
}
class RtcTokenBuilder {
/**
* Builds an RTC token using an Integer uid.
* @param {*} appID The App ID issued to you by Agora.
* @param {*} appCertificate Certificate of the application that you registered in the Agora Dashboard.
* @param {*} channelName The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are:
* - The 26 lowercase English letters: a to z.
* - The 26 uppercase English letters: A to Z.
* - The 10 digits: 0 to 9.
* - The space.
* - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
* @param {*} uid User ID. A 32-bit unsigned integer with a value ranging from 1 to (2^32-1).
* @param {*} role See #userRole.
* - Role.PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
* - Role.SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in). In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
* @param {*} privilegeExpiredTs represented by the number of seconds elapsed since 1/1/1970. If, for example, you want to access the Agora Service within 10 minutes after the token is generated, set expireTimestamp as the current timestamp + 600 (seconds).
* @return The new Token.
*/
static buildTokenWithUid(appID, appCertificate, channelName, uid, role, privilegeExpiredTs) {
return this.buildTokenWithAccount(appID, appCertificate, channelName, uid, role, privilegeExpiredTs)
}
/**
* Builds an RTC token using an Integer uid.
* @param {*} appID The App ID issued to you by Agora.
* @param {*} appCertificate Certificate of the application that you registered in the Agora Dashboard.
* @param {*} channelName The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are:
* - The 26 lowercase English letters: a to z.
* - The 26 uppercase English letters: A to Z.
* - The 10 digits: 0 to 9.
* - The space.
* - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
* @param {*} account The user account.
* @param {*} role See #userRole.
* - Role.PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
* - Role.SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in). In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
* @param {*} privilegeExpiredTs represented by the number of seconds elapsed since 1/1/1970. If, for example, you want to access the Agora Service within 10 minutes after the token is generated, set expireTimestamp as the current timestamp + 600 (seconds).
* @return The new Token.
*/
static buildTokenWithAccount(appID, appCertificate, channelName, account, role, privilegeExpiredTs) {
this.key = new AccessToken(appID, appCertificate, channelName, account)
this.key.addPriviledge(Priviledges.kJoinChannel, privilegeExpiredTs)
if (role == Role.ATTENDEE ||
role == Role.PUBLISHER ||
role == Role.ADMIN) {
this.key.addPriviledge(Priviledges.kPublishAudioStream, privilegeExpiredTs)
this.key.addPriviledge(Priviledges.kPublishVideoStream, privilegeExpiredTs)
this.key.addPriviledge(Priviledges.kPublishDataStream, privilegeExpiredTs)
}
return this.key.build();
}
}
module.exports.RtcTokenBuilder = RtcTokenBuilder;
module.exports.Role = Role;
+31
View File
@@ -0,0 +1,31 @@
const AccessToken = require("../src/AccessToken").AccessToken
const Priviledges = require('../src/AccessToken').priviledges
const Role = {
Rtm_User: 1
}
class RtmTokenBuilder {
/**
* @param {*} appID: The App ID issued to you by Agora. Apply for a new App ID from
* Agora Dashboard if it is missing from your kit. See Get an App ID.
* @param {*} appCertificate: Certificate of the application that you registered in
* the Agora Dashboard. See Get an App Certificate.
* @param {*} account: The user account.
* @param {*} role : Role_Publisher = 1: A broadcaster (host) in a live-broadcast profile.
* Role_Subscriber = 2: (Default) A audience in a live-broadcast profile.
* @param {*} privilegeExpiredTs : represented by the number of seconds elapsed since
* 1/1/1970. If, for example, you want to access the
* Agora Service within 10 minutes after the token is
* generated, set expireTimestamp as the current
* @return token
*/
static buildToken (appID, appCertificate, account, role, privilegeExpiredTs) {
const key = new AccessToken(appID, appCertificate, account, "")
key.addPriviledge(Priviledges.kRtmLogin, privilegeExpiredTs)
return key.build()
}
}
module.exports.RtmTokenBuilder = RtmTokenBuilder
module.exports.Role = Role
+29
View File
@@ -0,0 +1,29 @@
const md5 = require("md5");
var SignalingToken = {}
SignalingToken.get = function(appid, appcertificate, account, validTimeInSeconds){
var expiredTime = parseInt(new Date().getTime() / 1000)+ validTimeInSeconds;
var token_items = [];
//append SDK VERSION
token_items.push("1");
//append appid
token_items.push(appid);
//expired time
token_items.push(expiredTime);
//md5 account + appid + appcertificate + expiredtime
token_items.push(md5(account + appid + appcertificate + expiredTime));
return token_items.join(":");
}
//convenience function to get token valid within 1 day
SignalingToken.get1DayToken = function(appid, appcertificate, account){
return SignalingToken.get(appid, appcertificate, account, 3600 * 24);
}
module.exports = SignalingToken;
+78
View File
@@ -0,0 +1,78 @@
/**
* run this test with command:
* nodeunit AccessTokenTest.js
* see https://github.com/caolan/nodeunit
*/
var AccessToken = require('../src/AccessToken').AccessToken;
var Priviledges = require('../src/AccessToken').priviledges;
var appID = "970CA35de60c44645bbae8a215061b33";
var appCertificate = "5CFd2fd1755d40ecb72977518be15d3b";
var channel = "7d72365eb983485397e3e3f9d460bdda";
var uid = 2882341273;
var salt = 1;
var ts = 1111111;
var expireTimestamp = 1446455471;
exports.AccessToken_Test = function (test) {
var expected = "006970CA35de60c44645bbae8a215061b33IACV0fZUBw+72cVoL9eyGGh3Q6Poi8bgjwVLnyKSJyOXR7dIfRBXoFHlEAABAAAAR/QQAAEAAQCvKDdW";
var key = new AccessToken.AccessToken(appID, appCertificate, channel, uid);
key.salt = salt;
key.ts = ts;
key.messages[Priviledges.kJoinChannel] = expireTimestamp;
var actual = key.build();
test.equal(expected, actual);
test.done();
};
// test uid = 0
exports.AccessToken_Test2 = function (test) {
var expected = "006970CA35de60c44645bbae8a215061b33IACw1o7htY6ISdNRtku3p9tjTPi0jCKf9t49UHJhzCmL6bdIfRAAAAAAEAABAAAAR/QQAAEAAQCvKDdW";
var uid_zero = 0;
var key = new AccessToken.AccessToken(appID, appCertificate, channel, uid_zero);
key.salt = salt;
key.ts = ts;
key.messages[Priviledges.kJoinChannel] = expireTimestamp;
var actual = key.build();
test.equal(expected, actual);
test.done();
};
const RtcRole = require("../src/RtcTokenBuilder").Role;
exports.RtcTokenBuilder_Test = function (test) {
const appID = '970CA35de60c44645bbae8a215061b33';
const certificate = '5CFd2fd1755d40ecb72977518be15d3b';
const expected = "006970CA35de60c44645bbae8a215061b33IACMv3I+fsRSejxy6luEwzA/1t/zbEHWfJCJ5m8ssFP/fLdIfRBXoFHlIgABAAAAR/QQAAQAAQCvKDdWAgCvKDdWAwCvKDdWBACvKDdW";
const channelName = "7d72365eb983485397e3e3f9d460bdda";
const uid = 2882341273;
const salt = 1;
const ts = 1111111;
const privilegeExpiredsTs = 1446455471;
const role = RtcRole.PUBLISHER;
const key = new AccessToken(appID, certificate, channelName, uid);
key.addPriviledge(Priviledges.kJoinChannel, privilegeExpiredsTs);
key.salt = salt;
key.ts = ts;
if (role == RtcRole.PUBLISHER ||
role == RtcRole.SUBSCRIBER ||
role == RtcRole.ADMIN) {
key.addPriviledge(Priviledges.kPublishAudioStream, privilegeExpiredsTs)
key.addPriviledge(Priviledges.kPublishVideoStream, privilegeExpiredsTs)
key.addPriviledge(Priviledges.kPublishDataStream, privilegeExpiredsTs)
}
const actual = key.build();
test.equal(expected, actual);
test.done();
}
+47
View File
@@ -0,0 +1,47 @@
/**
* run this test with command:
* nodeunit DynamicKeyTest.js
* see https://github.com/caolan/nodeunit
*/
var DynamicKey5 = require('../src/DynamicKey5');
var appID = "970ca35de60c44645bbae8a215061b33";
var appCertificate = "5cfd2fd1755d40ecb72977518be15d3b";
var channel = "7d72365eb983485397e3e3f9d460bdda";
var ts = 1446455472;
var r = 58964981;
//var uid=999;
var uid=2882341273;
var expiredTs=1446455471;
exports.PublicSharingKey5_Test = function(test) {
var expected = "005AwAoADc0QTk5RTVEQjI4MDk0NUI0NzUwNTk0MUFDMjM4MDU2NzIwREY3QjAQAJcMo13mDERkW7roohUGGzOwKDdW9buDA68oN1YAAA==";
var actual = DynamicKey5.generatePublicSharingKey(appID, appCertificate, channel, ts, r, uid, expiredTs);
test.equal(expected, actual);
test.done();
};
exports.RecordingKey5_Test = function(test) {
var expected = "005AgAoADkyOUM5RTQ2MTg3QTAyMkJBQUIyNkI3QkYwMTg0MzhDNjc1Q0ZFMUEQAJcMo13mDERkW7roohUGGzOwKDdW9buDA68oN1YAAA==";
var result = DynamicKey5.generateRecordingKey(appID, appCertificate, channel, ts, r, uid, expiredTs);
test.equal(expected, result);
test.done();
};
exports.MediaChannelKey5_Test = function(test) {
var expected = "005AQAoAEJERTJDRDdFNkZDNkU0ODYxNkYxQTYwOUVFNTM1M0U5ODNCQjFDNDQQAJcMo13mDERkW7roohUGGzOwKDdW9buDA68oN1YAAA==";
var result = DynamicKey5.generateMediaChannelKey(appID, appCertificate, channel, ts, r, uid, expiredTs);
test.equal(expected, result);
test.done();
};
exports.InChannelPermission5_Test = function(test) {
var noUpload = "005BAAoADgyNEQxNDE4M0FGRDkyOEQ4REFFMUU1OTg5NTg2MzA3MTEyNjRGNzQQAJcMo13mDERkW7roohUGGzOwKDdW9buDA68oN1YBAAEAAQAw";
var generatedNoUpload = DynamicKey5.generateInChannelPermissionKey(appID, appCertificate, channel, ts, r, uid, expiredTs, DynamicKey5.noUpload);
test.equal(noUpload, generatedNoUpload);
var audioVideoUpload = "005BAAoADJERDA3QThENTE2NzJGNjQwMzY5NTFBNzE0QkI5NTc0N0Q1QjZGQjMQAJcMo13mDERkW7roohUGGzOwKDdW9buDA68oN1YBAAEAAQAz";
var generatedAudioVideoUpload = DynamicKey5.generateInChannelPermissionKey(appID, appCertificate, channel, ts, r, uid, expiredTs, DynamicKey5.audioVideoUpload);
test.equal(audioVideoUpload, generatedAudioVideoUpload);
test.done();
};
+44
View File
@@ -0,0 +1,44 @@
/**
* run this test with command:
* nodeunit AccessTokenTest.js
* see https://github.com/caolan/nodeunit
*/
var RtmTokenBuilder = require('../src/RtmTokenBuilder').RtmTokenBuilder;
var Priviledges = require('../src/AccessToken').priviledges;
var appID = "970CA35de60c44645bbae8a215061b33";
var appCertificate = "5CFd2fd1755d40ecb72977518be15d3b";
var account = "test_user";
var salt = 1;
var ts = 1111111;
var expireTimestamp = 1446455471;
exports.RtmToken_Test = function (test) {
var expected = "006970CA35de60c44645bbae8a215061b33IAAsR0qgiCxv0vrpRcpkz5BrbfEWCBZ6kvR6t7qG/wJIQob86ogAAAAAEAABAAAAR/QQAAEA6AOvKDdW";
var builder = new RtmTokenBuilder(appID, appCertificate, account);
builder.key.salt = salt;
builder.key.ts = ts;
builder.setPrivilege(Priviledges.kRtmLogin, expireTimestamp)
var actual = builder.buildToken();
test.equal(expected, actual);
test.done();
};
// test uid = 0
exports.RtmToken_Test2 = function (test) {
var expected = "006970CA35de60c44645bbae8a215061b33IABR8ywaENKv6kia6iUU6P54g017Bi6Ym9sIGdt9f3sLLYb86ogAAAAAEAABAAAAR/QQAAEA6ANkAAAA";
var builder = new RtmTokenBuilder(appID, appCertificate, account);
builder.key.salt = salt;
builder.key.ts = ts;
builder.setPrivilege(Priviledges.kRtmLogin, 100)
var actual = builder.buildToken();
test.equal(expected, actual);
test.done();
};