agora-token 2.0.0
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/README.md +36 -0
- package/index.d.ts +232 -0
- package/index.js +7 -0
- package/package.json +19 -0
- package/sample/AccessToken2Sample.js +18 -0
- package/sample/EducationTokenSample.js +21 -0
- package/sample/FpaTokenBuilderSample.js +7 -0
- package/sample/README.md +12 -0
- package/sample/RtcTokenBuilder2Sample.js +28 -0
- package/sample/RtcTokenBuilderSample.js +25 -0
- package/sample/RtmTokenBuilder2Sample.js +8 -0
- package/sample/RtmTokenBuilderSample.js +14 -0
- package/sample.js +46 -0
- package/server/DemoServer.js +66 -0
- package/server/README.md +26 -0
- package/server/package-lock.json +242 -0
- package/server/package.json +14 -0
- package/src/AccessToken.js +237 -0
- package/src/AccessToken2.js +414 -0
- package/src/DynamicKey5.js +173 -0
- package/src/EducationTokenBuilder.js +80 -0
- package/src/FpaTokenBuilder.js +24 -0
- package/src/RtcTokenBuilder.js +75 -0
- package/src/RtcTokenBuilder2.js +197 -0
- package/src/RtmTokenBuilder.js +31 -0
- package/src/RtmTokenBuilder2.js +28 -0
- package/src/SignalingToken.js +29 -0
- package/test/AccessToken2Test.js +110 -0
- package/test/AccessTokenTest.js +77 -0
- package/test/DynamicKeyTest.js +47 -0
- package/test/EducationTokenBuilderTest.js +45 -0
- package/test/FpaTokenBuilderTest.js +22 -0
- package/test/RtcTokenBuilder2Test.js +140 -0
- package/test/RtmTokenBuilder2Test.js +24 -0
- package/test/RtmTokenBuilderTest.js +24 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
var crypto = require('crypto')
|
|
2
|
+
const zlib = require('zlib')
|
|
3
|
+
const VERSION_LENGTH = 3
|
|
4
|
+
const APP_ID_LENGTH = 32
|
|
5
|
+
|
|
6
|
+
const getVersion = () => {
|
|
7
|
+
return "007"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class Service {
|
|
11
|
+
constructor(service_type) {
|
|
12
|
+
this.__type = service_type
|
|
13
|
+
this.__privileges = {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
__pack_type() {
|
|
17
|
+
let buf = new ByteBuf()
|
|
18
|
+
buf.putUint16(this.__type)
|
|
19
|
+
return buf.pack()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
__pack_privileges() {
|
|
23
|
+
let buf = new ByteBuf()
|
|
24
|
+
buf.putTreeMapUInt32(this.__privileges)
|
|
25
|
+
return buf.pack()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
service_type() {
|
|
29
|
+
return this.__type
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
add_privilege(privilege, expire) {
|
|
33
|
+
this.__privileges[privilege] = expire
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pack() {
|
|
37
|
+
return Buffer.concat([this.__pack_type(), this.__pack_privileges()])
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
unpack(buffer) {
|
|
41
|
+
let bufReader = new ReadByteBuf(buffer)
|
|
42
|
+
this.__privileges = bufReader.getTreeMapUInt32()
|
|
43
|
+
return bufReader
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const kRtcServiceType = 1
|
|
48
|
+
|
|
49
|
+
class ServiceRtc extends Service {
|
|
50
|
+
constructor(channel_name, uid) {
|
|
51
|
+
super(kRtcServiceType)
|
|
52
|
+
this.__channel_name = channel_name
|
|
53
|
+
this.__uid = uid === 0 ? '' : `${uid}`
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
pack() {
|
|
57
|
+
let buffer = new ByteBuf()
|
|
58
|
+
buffer.putString(this.__channel_name).putString(this.__uid)
|
|
59
|
+
return Buffer.concat([super.pack(), buffer.pack()])
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
unpack(buffer) {
|
|
63
|
+
let bufReader = super.unpack(buffer)
|
|
64
|
+
this.__channel_name = bufReader.getString()
|
|
65
|
+
this.__uid = bufReader.getString()
|
|
66
|
+
return bufReader
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
ServiceRtc.kPrivilegeJoinChannel = 1
|
|
71
|
+
ServiceRtc.kPrivilegePublishAudioStream = 2
|
|
72
|
+
ServiceRtc.kPrivilegePublishVideoStream = 3
|
|
73
|
+
ServiceRtc.kPrivilegePublishDataStream = 4
|
|
74
|
+
|
|
75
|
+
const kRtmServiceType = 2
|
|
76
|
+
|
|
77
|
+
class ServiceRtm extends Service {
|
|
78
|
+
constructor(user_id) {
|
|
79
|
+
super(kRtmServiceType)
|
|
80
|
+
this.__user_id = user_id || ""
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
pack() {
|
|
84
|
+
let buffer = new ByteBuf()
|
|
85
|
+
buffer.putString(this.__user_id)
|
|
86
|
+
return Buffer.concat([super.pack(), buffer.pack()])
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
unpack(buffer) {
|
|
90
|
+
let bufReader = super.unpack(buffer)
|
|
91
|
+
this.__user_id = bufReader.getString()
|
|
92
|
+
return bufReader
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
ServiceRtm.kPrivilegeLogin = 1
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
const kFpaServiceType = 4
|
|
100
|
+
|
|
101
|
+
class ServiceFpa extends Service {
|
|
102
|
+
constructor() {
|
|
103
|
+
super(kFpaServiceType)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
pack() {
|
|
107
|
+
return super.pack()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
unpack(buffer) {
|
|
111
|
+
let bufReader = super.unpack(buffer)
|
|
112
|
+
return bufReader
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
ServiceFpa.kPrivilegeLogin = 1
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
const kChatServiceType = 5
|
|
120
|
+
|
|
121
|
+
class ServiceChat extends Service {
|
|
122
|
+
constructor(user_id) {
|
|
123
|
+
super(kChatServiceType)
|
|
124
|
+
this.__user_id = user_id || ""
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
pack() {
|
|
128
|
+
let buffer = new ByteBuf()
|
|
129
|
+
buffer.putString(this.__user_id)
|
|
130
|
+
return Buffer.concat([super.pack(), buffer.pack()])
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
unpack(buffer) {
|
|
134
|
+
let bufReader = super.unpack(buffer)
|
|
135
|
+
this.__user_id = bufReader.getString()
|
|
136
|
+
return bufReader
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
ServiceChat.kPrivilegeUser = 1
|
|
141
|
+
ServiceChat.kPrivilegeApp = 2
|
|
142
|
+
|
|
143
|
+
const kEducationServiceType = 7
|
|
144
|
+
|
|
145
|
+
class ServiceEducation extends Service {
|
|
146
|
+
constructor(roomUuid, userUuid, role) {
|
|
147
|
+
super(kEducationServiceType)
|
|
148
|
+
this.__room_uuid = roomUuid || ""
|
|
149
|
+
this.__user_uuid = userUuid || ""
|
|
150
|
+
this.__role = role || -1
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
pack() {
|
|
154
|
+
let buffer = new ByteBuf()
|
|
155
|
+
buffer.putString(this.__room_uuid)
|
|
156
|
+
buffer.putString(this.__user_uuid)
|
|
157
|
+
buffer.putInt16(this.__role)
|
|
158
|
+
return Buffer.concat([super.pack(), buffer.pack()])
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
unpack(buffer) {
|
|
162
|
+
let bufReader = super.unpack(buffer)
|
|
163
|
+
this.__room_uuid = bufReader.getString()
|
|
164
|
+
this.__user_uuid = bufReader.getString()
|
|
165
|
+
this.__role = bufReader.getInt16()
|
|
166
|
+
return bufReader
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
ServiceEducation.PRIVILEGE_ROOM_USER = 1
|
|
171
|
+
ServiceEducation.PRIVILEGE_USER = 2
|
|
172
|
+
ServiceEducation.PRIVILEGE_APP = 3
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class AccessToken2 {
|
|
176
|
+
constructor(appId, appCertificate, issueTs, expire) {
|
|
177
|
+
this.appId = appId
|
|
178
|
+
this.appCertificate = appCertificate
|
|
179
|
+
this.issueTs = issueTs || new Date().getTime() / 1000
|
|
180
|
+
this.expire = expire
|
|
181
|
+
// salt ranges in (1, 99999999)
|
|
182
|
+
this.salt = Math.floor(Math.random() * (99999999)) + 1
|
|
183
|
+
this.services = {}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
__signing() {
|
|
187
|
+
let signing = encodeHMac(new ByteBuf().putUint32(this.issueTs).pack(), this.appCertificate)
|
|
188
|
+
signing = encodeHMac(new ByteBuf().putUint32(this.salt).pack(), signing)
|
|
189
|
+
return signing
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
__build_check() {
|
|
193
|
+
let is_uuid = (data) => {
|
|
194
|
+
if (data.length !== APP_ID_LENGTH) {
|
|
195
|
+
return false
|
|
196
|
+
}
|
|
197
|
+
let buf = Buffer.from(data, 'hex')
|
|
198
|
+
return !!buf
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const {appId, appCertificate, services} = this
|
|
202
|
+
if (!is_uuid(appId) || !is_uuid(appCertificate)) {
|
|
203
|
+
return false
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (Object.keys(services).length === 0) {
|
|
207
|
+
return false
|
|
208
|
+
}
|
|
209
|
+
return true
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
add_service(service) {
|
|
213
|
+
this.services[service.service_type()] = service
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
build() {
|
|
217
|
+
if (!this.__build_check()) {
|
|
218
|
+
return ""
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let signing = this.__signing()
|
|
222
|
+
let signing_info = new ByteBuf().putString(this.appId)
|
|
223
|
+
.putUint32(this.issueTs)
|
|
224
|
+
.putUint32(this.expire)
|
|
225
|
+
.putUint32(this.salt)
|
|
226
|
+
.putUint16(Object.keys(this.services).length).pack()
|
|
227
|
+
Object.values(this.services).forEach(service => {
|
|
228
|
+
signing_info = Buffer.concat([signing_info, service.pack()])
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
let signature = encodeHMac(signing, signing_info)
|
|
232
|
+
let content = Buffer.concat([new ByteBuf().putString(signature).pack(), signing_info])
|
|
233
|
+
let compressed = zlib.deflateSync(content)
|
|
234
|
+
return `${getVersion()}${Buffer.from(compressed).toString('base64')}`
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
from_string(origin_token) {
|
|
238
|
+
let origin_version = origin_token.substring(0, VERSION_LENGTH)
|
|
239
|
+
if (origin_version !== getVersion()) {
|
|
240
|
+
return false
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let origin_content = origin_token.substring(VERSION_LENGTH, origin_token.length)
|
|
244
|
+
let buffer = zlib.inflateSync(new Buffer(origin_content, 'base64'))
|
|
245
|
+
let bufferReader = new ReadByteBuf(buffer)
|
|
246
|
+
|
|
247
|
+
let signature = bufferReader.getString()
|
|
248
|
+
this.appId = bufferReader.getString()
|
|
249
|
+
this.issueTs = bufferReader.getUint32()
|
|
250
|
+
this.expire = bufferReader.getUint32()
|
|
251
|
+
this.salt = bufferReader.getUint32()
|
|
252
|
+
let service_count = bufferReader.getUint16()
|
|
253
|
+
|
|
254
|
+
let remainBuf = bufferReader.pack()
|
|
255
|
+
for (let i = 0; i < service_count; i++) {
|
|
256
|
+
let bufferReaderService = new ReadByteBuf(remainBuf)
|
|
257
|
+
let service_type = bufferReaderService.getUint16()
|
|
258
|
+
let service = new AccessToken2.kServices[service_type]()
|
|
259
|
+
remainBuf = service.unpack(bufferReaderService.pack()).pack()
|
|
260
|
+
this.services[service_type] = service
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
var encodeHMac = function (key, message) {
|
|
266
|
+
return crypto.createHmac('sha256', key).update(message).digest()
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
var ByteBuf = function () {
|
|
270
|
+
var that = {
|
|
271
|
+
buffer: Buffer.alloc(1024)
|
|
272
|
+
, position: 0
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
that.buffer.fill(0)
|
|
276
|
+
|
|
277
|
+
that.pack = function () {
|
|
278
|
+
var out = Buffer.alloc(that.position)
|
|
279
|
+
that.buffer.copy(out, 0, 0, out.length)
|
|
280
|
+
return out
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
that.putUint16 = function (v) {
|
|
284
|
+
that.buffer.writeUInt16LE(v, that.position)
|
|
285
|
+
that.position += 2
|
|
286
|
+
return that
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
that.putUint32 = function (v) {
|
|
290
|
+
that.buffer.writeUInt32LE(v, that.position)
|
|
291
|
+
that.position += 4
|
|
292
|
+
return that
|
|
293
|
+
}
|
|
294
|
+
that.putInt32 = function (v) {
|
|
295
|
+
that.buffer.writeInt32LE(v, that.position)
|
|
296
|
+
that.position += 4
|
|
297
|
+
return that
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
that.putInt16 = function (v) {
|
|
301
|
+
that.buffer.writeInt16LE(v, that.position)
|
|
302
|
+
that.position += 2
|
|
303
|
+
return that
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
that.putBytes = function (bytes) {
|
|
307
|
+
that.putUint16(bytes.length)
|
|
308
|
+
bytes.copy(that.buffer, that.position)
|
|
309
|
+
that.position += bytes.length
|
|
310
|
+
return that
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
that.putString = function (str) {
|
|
314
|
+
return that.putBytes(Buffer.from(str))
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
that.putTreeMap = function (map) {
|
|
318
|
+
if (!map) {
|
|
319
|
+
that.putUint16(0)
|
|
320
|
+
return that
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
that.putUint16(Object.keys(map).length)
|
|
324
|
+
for (var key in map) {
|
|
325
|
+
that.putUint16(key)
|
|
326
|
+
that.putString(map[key])
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return that
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
that.putTreeMapUInt32 = function (map) {
|
|
333
|
+
if (!map) {
|
|
334
|
+
that.putUint16(0)
|
|
335
|
+
return that
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
that.putUint16(Object.keys(map).length)
|
|
339
|
+
for (var key in map) {
|
|
340
|
+
that.putUint16(key)
|
|
341
|
+
that.putUint32(map[key])
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return that
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return that
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
var ReadByteBuf = function (bytes) {
|
|
351
|
+
var that = {
|
|
352
|
+
buffer: bytes
|
|
353
|
+
, position: 0
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
that.getUint16 = function () {
|
|
357
|
+
var ret = that.buffer.readUInt16LE(that.position)
|
|
358
|
+
that.position += 2
|
|
359
|
+
return ret
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
that.getUint32 = function () {
|
|
363
|
+
var ret = that.buffer.readUInt32LE(that.position)
|
|
364
|
+
that.position += 4
|
|
365
|
+
return ret
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
that.getInt16 = function () {
|
|
369
|
+
var ret = that.buffer.readUInt16LE(that.position)
|
|
370
|
+
that.position += 2
|
|
371
|
+
return ret
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
that.getString = function () {
|
|
375
|
+
var len = that.getUint16()
|
|
376
|
+
|
|
377
|
+
var out = Buffer.alloc(len)
|
|
378
|
+
that.buffer.copy(out, 0, that.position, (that.position + len))
|
|
379
|
+
that.position += len
|
|
380
|
+
return out
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
that.getTreeMapUInt32 = function () {
|
|
384
|
+
var map = {}
|
|
385
|
+
var len = that.getUint16()
|
|
386
|
+
for (var i = 0; i < len; i++) {
|
|
387
|
+
var key = that.getUint16()
|
|
388
|
+
var value = that.getUint32()
|
|
389
|
+
map[key] = value
|
|
390
|
+
}
|
|
391
|
+
return map
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
that.pack = function () {
|
|
395
|
+
let length = that.buffer.length
|
|
396
|
+
var out = Buffer.alloc(length)
|
|
397
|
+
that.buffer.copy(out, 0, that.position, length)
|
|
398
|
+
return out
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return that
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
AccessToken2.kServices = {}
|
|
405
|
+
AccessToken2.kServices[kRtcServiceType] = ServiceRtc
|
|
406
|
+
AccessToken2.kServices[kRtmServiceType] = ServiceRtm
|
|
407
|
+
AccessToken2.kServices[kFpaServiceType] = ServiceFpa
|
|
408
|
+
AccessToken2.kServices[kChatServiceType] = ServiceChat
|
|
409
|
+
AccessToken2.kServices[kEducationServiceType] = ServiceEducation
|
|
410
|
+
|
|
411
|
+
module.exports = {
|
|
412
|
+
AccessToken2, ServiceRtc, ServiceRtm, ServiceFpa, ServiceChat, ServiceEducation,
|
|
413
|
+
kRtcServiceType, kRtmServiceType, kFpaServiceType, kChatServiceType, kEducationServiceType,
|
|
414
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
var crypto = require('crypto');
|
|
2
|
+
|
|
3
|
+
var version = "005";
|
|
4
|
+
var noUpload = "0";
|
|
5
|
+
var audioVideoUpload = "3";
|
|
6
|
+
|
|
7
|
+
var generatePublicSharingKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
|
|
8
|
+
channelName=channelName.toString();
|
|
9
|
+
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, PUBLIC_SHARING_SERVICE);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
var generateRecordingKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
|
|
13
|
+
channelName=channelName.toString();
|
|
14
|
+
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, RECORDING_SERVICE);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
var generateMediaChannelKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
|
|
18
|
+
channelName=channelName.toString();
|
|
19
|
+
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, MEDIA_CHANNEL_SERVICE);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
var generateInChannelPermissionKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, permission) {
|
|
23
|
+
var extra = {};
|
|
24
|
+
extra[ALLOW_UPLOAD_IN_CHANNEL] = permission;
|
|
25
|
+
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, extra, IN_CHANNEL_PERMISSION);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
var generateDynamicKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, extra, serviceType) {
|
|
29
|
+
var signature = generateSignature5(appCertificate, serviceType, appID, unixTs, randomInt, channelName, uid, expiredTs, extra);
|
|
30
|
+
var content = DynamicKey5Content({
|
|
31
|
+
serviceType: serviceType
|
|
32
|
+
, signature: signature
|
|
33
|
+
, appID: hexDecode(appID)
|
|
34
|
+
, unixTs: unixTs
|
|
35
|
+
, salt: randomInt
|
|
36
|
+
, expiredTs: expiredTs
|
|
37
|
+
, extra: extra}).pack();
|
|
38
|
+
return version + content.toString('base64');
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports.version = version;
|
|
42
|
+
module.exports.noUpload = noUpload;
|
|
43
|
+
module.exports.audioVideoUpload = audioVideoUpload;
|
|
44
|
+
module.exports.generatePublicSharingKey = generatePublicSharingKey;
|
|
45
|
+
module.exports.generateRecordingKey = generateRecordingKey;
|
|
46
|
+
module.exports.generateMediaChannelKey = generateMediaChannelKey;
|
|
47
|
+
module.exports.generateInChannelPermissionKey = generateInChannelPermissionKey;
|
|
48
|
+
module.exports.generateDynamicKey = generateDynamicKey;
|
|
49
|
+
|
|
50
|
+
var generateSignature5 = function(appCertificate, serviceType, appID, unixTs, randomInt, channelName, uid, expiredTs, extra) {
|
|
51
|
+
// decode hex to avoid case problem
|
|
52
|
+
var rawAppID = hexDecode(appID);
|
|
53
|
+
var rawAppCertificate = hexDecode(appCertificate);
|
|
54
|
+
|
|
55
|
+
var m = Message({
|
|
56
|
+
serviceType: serviceType
|
|
57
|
+
, appID: rawAppID
|
|
58
|
+
, unixTs: unixTs
|
|
59
|
+
, salt: randomInt
|
|
60
|
+
, channelName: channelName
|
|
61
|
+
, uid: uid
|
|
62
|
+
, expiredTs: expiredTs
|
|
63
|
+
, extra: extra
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
var toSign = m.pack();
|
|
67
|
+
return encodeHMac(rawAppCertificate, toSign);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
var encodeHMac = function(key, message) {
|
|
71
|
+
return crypto.createHmac('sha1', key).update(message).digest('hex').toUpperCase();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
var hexDecode = function(str) {
|
|
75
|
+
return Buffer.from(str, 'hex');
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
var ByteBuf = function() {
|
|
79
|
+
var that = {
|
|
80
|
+
buffer: Buffer.alloc(1024)
|
|
81
|
+
, position: 0
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
that.buffer.fill(0);
|
|
85
|
+
|
|
86
|
+
that.pack = function() {
|
|
87
|
+
var out = Buffer.alloc(that.position);
|
|
88
|
+
that.buffer.copy(out, 0, 0, out.length);
|
|
89
|
+
return out;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
that.putUint16 = function(v) {
|
|
93
|
+
that.buffer.writeUInt16LE(v, that.position);
|
|
94
|
+
that.position += 2;
|
|
95
|
+
return that;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
that.putUint32 = function(v) {
|
|
99
|
+
that.buffer.writeUInt32LE(v, that.position);
|
|
100
|
+
that.position += 4;
|
|
101
|
+
return that;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
that.putBytes = function(bytes) {
|
|
105
|
+
that.putUint16(bytes.length);
|
|
106
|
+
bytes.copy(that.buffer, that.position);
|
|
107
|
+
that.position += bytes.length;
|
|
108
|
+
return that;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
that.putString = function(str) {
|
|
112
|
+
return that.putBytes(Buffer.from(str));
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
that.putTreeMap = function(map) {
|
|
116
|
+
if (!map) {
|
|
117
|
+
that.putUint16(0);
|
|
118
|
+
return that;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
that.putUint16(Object.keys(map).length);
|
|
122
|
+
for (var key in map) {
|
|
123
|
+
that.putUint16(key);
|
|
124
|
+
that.putString(map[key]);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return that;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return that;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
var DynamicKey5Content = function(options) {
|
|
134
|
+
options.pack = function() {
|
|
135
|
+
var out = ByteBuf();
|
|
136
|
+
return out.putUint16(options.serviceType)
|
|
137
|
+
.putString(options.signature)
|
|
138
|
+
.putBytes(options.appID)
|
|
139
|
+
.putUint32(options.unixTs)
|
|
140
|
+
.putUint32(options.salt)
|
|
141
|
+
.putUint32(options.expiredTs)
|
|
142
|
+
.putTreeMap(options.extra)
|
|
143
|
+
.pack();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return options;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
var Message = function(options) {
|
|
150
|
+
options.pack = function() {
|
|
151
|
+
var out = ByteBuf();
|
|
152
|
+
return out.putUint16(options.serviceType)
|
|
153
|
+
.putBytes(options.appID)
|
|
154
|
+
.putUint32(options.unixTs)
|
|
155
|
+
.putUint32(options.salt)
|
|
156
|
+
.putString(options.channelName)
|
|
157
|
+
.putUint32(options.uid)
|
|
158
|
+
.putUint32(options.expiredTs)
|
|
159
|
+
.putTreeMap(options.extra)
|
|
160
|
+
.pack();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return options;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// InChannelPermissionKey
|
|
167
|
+
var ALLOW_UPLOAD_IN_CHANNEL = 1;
|
|
168
|
+
|
|
169
|
+
// Service Type
|
|
170
|
+
var MEDIA_CHANNEL_SERVICE = 1;
|
|
171
|
+
var RECORDING_SERVICE = 2;
|
|
172
|
+
var PUBLIC_SHARING_SERVICE = 3;
|
|
173
|
+
var IN_CHANNEL_PERMISSION = 4;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const AccessToken = require('../src/AccessToken2').AccessToken2
|
|
2
|
+
const ServiceEducation = require('../src/AccessToken2').ServiceEducation
|
|
3
|
+
const ServiceRtm = require('../src/AccessToken2').ServiceRtm
|
|
4
|
+
const ServiceChat = require('../src/AccessToken2').ServiceChat
|
|
5
|
+
const md5 = require("md5")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EducationTokenBuilder {
|
|
9
|
+
/**
|
|
10
|
+
* build user room token
|
|
11
|
+
* @param appId The App ID issued to you by Agora. Apply for a new App ID from
|
|
12
|
+
* Agora Dashboard if it is missing from your kit. See Get an App ID.
|
|
13
|
+
* @param appCertificate Certificate of the application that you registered in
|
|
14
|
+
* the Agora Dashboard. See Get an App Certificate.
|
|
15
|
+
* @param roomUuid The room's id, must be unique.
|
|
16
|
+
* @param userUuid The user's id, must be unique.
|
|
17
|
+
* @param role The user's role, such as 0(invisible), 1(teacher), 2(student), 3(assistant), 4(observer) etc.
|
|
18
|
+
* @param expire represented by the number of seconds elapsed since now. If, for example, you want to access the
|
|
19
|
+
* Agora Service within 10 minutes after the token is generated, set expireTimestamp as 600(seconds).
|
|
20
|
+
* @return The education user room token.
|
|
21
|
+
*/
|
|
22
|
+
static buildRoomUserToken(appId, appCertificate, roomUuid, userUuid, role, expire) {
|
|
23
|
+
let accessToken = new AccessToken(appId, appCertificate, 0, expire)
|
|
24
|
+
|
|
25
|
+
let chatUserId = md5(userUuid)
|
|
26
|
+
let eduService = new ServiceEducation(roomUuid, userUuid, role)
|
|
27
|
+
accessToken.add_service(eduService)
|
|
28
|
+
|
|
29
|
+
let rtmService = new ServiceRtm(userUuid)
|
|
30
|
+
rtmService.add_privilege(ServiceRtm.kPrivilegeLogin, expire)
|
|
31
|
+
accessToken.add_service(rtmService)
|
|
32
|
+
|
|
33
|
+
let chatService = new ServiceChat(chatUserId)
|
|
34
|
+
chatService.add_privilege(ServiceChat.kPrivilegeUser, expire)
|
|
35
|
+
accessToken.add_service(chatService)
|
|
36
|
+
|
|
37
|
+
return accessToken.build()
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* build user individual token
|
|
42
|
+
* @param appId The App ID issued to you by Agora. Apply for a new App ID from
|
|
43
|
+
* Agora Dashboard if it is missing from your kit. See Get an App ID.
|
|
44
|
+
* @param appCertificate Certificate of the application that you registered in
|
|
45
|
+
* the Agora Dashboard. See Get an App Certificate.
|
|
46
|
+
* @param userUuid The user's id, must be unique.
|
|
47
|
+
* @param expire represented by the number of seconds elapsed since now. If, for example, you want to access the
|
|
48
|
+
* Agora Service within 10 minutes after the token is generated, set expireTimestamp as 600(seconds).
|
|
49
|
+
* @return The education user token.
|
|
50
|
+
*/
|
|
51
|
+
static buildUserToken(appId, appCertificate, userUuid, expire) {
|
|
52
|
+
let accessToken = new AccessToken(appId, appCertificate, 0, expire)
|
|
53
|
+
let eduService = new ServiceEducation("", userUuid)
|
|
54
|
+
eduService.add_privilege(ServiceEducation.PRIVILEGE_USER, expire)
|
|
55
|
+
accessToken.add_service(eduService)
|
|
56
|
+
|
|
57
|
+
return accessToken.build()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* build app global token
|
|
62
|
+
* @param appId The App ID issued to you by Agora. Apply for a new App ID from
|
|
63
|
+
* Agora Dashboard if it is missing from your kit. See Get an App ID.
|
|
64
|
+
* @param appCertificate Certificate of the application that you registered in
|
|
65
|
+
* the Agora Dashboard. See Get an App Certificate.
|
|
66
|
+
* @param expire represented by the number of seconds elapsed since now. If, for example, you want to access the
|
|
67
|
+
* Agora Service within 10 minutes after the token is generated, set expireTimestamp as 600(seconds).
|
|
68
|
+
* @return The education global token.
|
|
69
|
+
*/
|
|
70
|
+
static buildAppToken(appId, appCertificate, expire) {
|
|
71
|
+
let accessToken = new AccessToken(appId, appCertificate, 0, expire)
|
|
72
|
+
let eduService = new ServiceEducation()
|
|
73
|
+
eduService.add_privilege(ServiceEducation.PRIVILEGE_APP, expire)
|
|
74
|
+
accessToken.add_service(eduService)
|
|
75
|
+
|
|
76
|
+
return accessToken.build()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports.EducationTokenBuilder = EducationTokenBuilder
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const AccessToken = require('../src/AccessToken2').AccessToken2
|
|
2
|
+
const ServiceFpa = require('../src/AccessToken2').ServiceFpa
|
|
3
|
+
|
|
4
|
+
class FpaTokenBuilder {
|
|
5
|
+
/**
|
|
6
|
+
* Build the FPA token.
|
|
7
|
+
* @param appId The App ID issued to you by Agora. Apply for a new App ID from
|
|
8
|
+
* Agora Dashboard if it is missing from your kit. See Get an App ID.
|
|
9
|
+
* @param appCertificate Certificate of the application that you registered in
|
|
10
|
+
* the Agora Dashboard. See Get an App Certificate.
|
|
11
|
+
* @return The FPA token.
|
|
12
|
+
*/
|
|
13
|
+
static buildToken(appId, appCertificate) {
|
|
14
|
+
let token = new AccessToken(appId, appCertificate, 0, 24 * 3600)
|
|
15
|
+
|
|
16
|
+
let serviceFpa = new ServiceFpa()
|
|
17
|
+
serviceFpa.add_privilege(ServiceFpa.kPrivilegeLogin, 0)
|
|
18
|
+
token.add_service(serviceFpa)
|
|
19
|
+
|
|
20
|
+
return token.build()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports.FpaTokenBuilder = FpaTokenBuilder
|