agora-ruby 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.txt +21 -0
- data/README.md +187 -0
- data/Rakefile +6 -0
- data/agora-ruby.gemspec +29 -0
- data/bin/console +13 -0
- data/bin/setup +8 -0
- data/lib/agora/cloud_recording/client.rb +139 -0
- data/lib/agora/config.rb +12 -0
- data/lib/agora/dynamic_key/access_token.rb +55 -0
- data/lib/agora/dynamic_key/rtc_token_builder.rb +112 -0
- data/lib/agora/dynamic_key/rtm_token_builder.rb +46 -0
- data/lib/agora/dynamic_key/sign.rb +73 -0
- data/lib/agora/dynamic_key.rb +13 -0
- data/lib/agora/dynamic_key2/access_token.rb +220 -0
- data/lib/agora/dynamic_key2/apaas_token_builder.rb +73 -0
- data/lib/agora/dynamic_key2/chat_token_builder.rb +42 -0
- data/lib/agora/dynamic_key2/education_token_builder.rb +73 -0
- data/lib/agora/dynamic_key2/fpa_token_builder.rb +21 -0
- data/lib/agora/dynamic_key2/rtc_token_builder.rb +215 -0
- data/lib/agora/dynamic_key2/rtm_token_builder.rb +22 -0
- data/lib/agora/dynamic_key2/util.rb +60 -0
- data/lib/agora/dynamic_key2.rb +12 -0
- data/lib/agora/errors.rb +14 -0
- data/lib/agora/version.rb +3 -0
- data/lib/agora-ruby.rb +18 -0
- data/sample/README.md +12 -0
- data/sample/apaas_token_builder_sample.rb +29 -0
- data/sample/chat_token_builder_sample.rb +23 -0
- data/sample/education_token_builder_sample.rb +29 -0
- data/sample/fpa_token_builder_sample.rb +16 -0
- data/sample/rtc_token_builder2_sample.rb +55 -0
- data/sample/rtc_token_builder_sample.rb +40 -0
- data/sample/rtm_token_builder_sample.rb +27 -0
- data/token_compare.md +143 -0
- metadata +101 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
module Agora::AgoraDynamicKey
|
2
|
+
|
3
|
+
class RTCTokenBuilder
|
4
|
+
class InvalidParamsError < StandardError
|
5
|
+
attr_reader :params, :missing_keys
|
6
|
+
def initialize args={}
|
7
|
+
super
|
8
|
+
@params = args[:params]
|
9
|
+
@missing_keys = args[:missing_keys]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Role
|
14
|
+
# DEPRECATED. Role::ATTENDEE has the same privileges as Role::PUBLISHER.
|
15
|
+
ATTENDEE = 0
|
16
|
+
|
17
|
+
# RECOMMENDED. Use this role for a voice/video call or a live broadcast, if your scenario does not require authentication for [Co-host](https://docs.agora.io/en/video-calling/get-started/authentication-workflow?#co-host-token-authentication).
|
18
|
+
PUBLISHER = 1
|
19
|
+
|
20
|
+
# Only use this role if your scenario require authentication for [Co-host](https://docs.agora.io/en/video-calling/get-started/authentication-workflow?#co-host-token-authentication).
|
21
|
+
# @note In order for this role to take effect, please contact our support team to enable authentication for Co-host for you. Otherwise, Role::SUBSCRIBER still has the same privileges as Role::PUBLISHER.
|
22
|
+
SUBSCRIBER = 2
|
23
|
+
|
24
|
+
# DEPRECATED. Role::ADMIN has the same privileges as Role::PUBLISHER.
|
25
|
+
ADMIN = 101
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
|
30
|
+
#
|
31
|
+
# Builds an RTC token using an Integer uid.
|
32
|
+
# @param payload
|
33
|
+
# :app_id The App ID issued to you by Agora.
|
34
|
+
# :app_certificate Certificate of the application that you registered in the Agora Dashboard.
|
35
|
+
# :channel_name 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:
|
36
|
+
# - The 26 lowercase English letters: a to z.
|
37
|
+
# - The 26 uppercase English letters: A to Z.
|
38
|
+
# - The 10 digits: 0 to 9.
|
39
|
+
# - The space.
|
40
|
+
# - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
|
41
|
+
# :uid User ID. A 32-bit unsigned integer with a value ranging from 1 to (2^32-1).
|
42
|
+
# :role See #userRole.
|
43
|
+
# - Role::PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
|
44
|
+
# - Role::SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Co-host](https://docs.agora.io/en/video-calling/get-started/authentication-workflow?#co-host-token-authentication). In order for this role to take effect, please contact our support team to enable authentication for Co-host for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
|
45
|
+
# :privilege_expired_ts 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).
|
46
|
+
#
|
47
|
+
# @return The new Token.
|
48
|
+
#
|
49
|
+
def build_token_with_uid payload
|
50
|
+
check! payload, %i[app_id app_certificate channel_name role uid privilege_expired_ts]
|
51
|
+
build_token_with_account @params.merge(:account => @params[:uid])
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Builds an RTC token using a string user_account.
|
56
|
+
# @param payload
|
57
|
+
# :app_id The App ID issued to you by Agora.
|
58
|
+
# :app_certificate Certificate of the application that you registered in the Agora Dashboard.
|
59
|
+
# :channel_name 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:
|
60
|
+
# - The 26 lowercase English letters: a to z.
|
61
|
+
# - The 26 uppercase English letters: A to Z.
|
62
|
+
# - The 10 digits: 0 to 9.
|
63
|
+
# - The space.
|
64
|
+
# - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
|
65
|
+
# :account The user account.
|
66
|
+
# :role See #userRole.
|
67
|
+
# - Role::PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
|
68
|
+
# - Role::SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Co-host](https://docs.agora.io/en/video-calling/get-started/authentication-workflow?#co-host-token-authentication). In order for this role to take effect, please contact our support team to enable authentication for Co-host for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
|
69
|
+
# :privilege_expired_ts 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).
|
70
|
+
#
|
71
|
+
# @return The new Token.
|
72
|
+
#
|
73
|
+
def build_token_with_account payload
|
74
|
+
check! payload, %i[app_id app_certificate channel_name role account privilege_expired_ts]
|
75
|
+
@params.merge!(:uid => @params[:account])
|
76
|
+
generate_access_token!
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# generate access token
|
82
|
+
def generate_access_token!
|
83
|
+
# Assign appropriate access privileges to each role.
|
84
|
+
Agora::AgoraDynamicKey::AccessToken.generate!(@params) do |t|
|
85
|
+
t.grant Agora::AgoraDynamicKey::Privilege::JOIN_CHANNEL, t.privilege_expired_ts
|
86
|
+
if @params[:role] == Role::PUBLISHER ||
|
87
|
+
@params[:role] == Role::SUBSCRIBER ||
|
88
|
+
@params[:role] == Role::ADMIN
|
89
|
+
t.grant Agora::AgoraDynamicKey::Privilege::PUBLISH_AUDIO_STREAM, t.privilege_expired_ts
|
90
|
+
t.grant Agora::AgoraDynamicKey::Privilege::PUBLISH_VIDEO_STREAM, t.privilege_expired_ts
|
91
|
+
t.grant Agora::AgoraDynamicKey::Privilege::PUBLISH_DATA_STREAM, t.privilege_expired_ts
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# params check
|
97
|
+
def check!(payload, args)
|
98
|
+
raise InvalidParamsError.new(params: payload), "invalid params" if payload.nil? or payload.empty?
|
99
|
+
symbolize_keys payload.select { |key| args.include? key }
|
100
|
+
missing_keys = args - @params.keys
|
101
|
+
raise InvalidParamsError.new(params: payload, missing_keys: missing_keys), "missing params" if missing_keys.size != 0
|
102
|
+
_invalid_params = @params.select { |hash, (k, v)| v.nil? or v.empty?}
|
103
|
+
raise InvalidParamsError.new(params: payload), "invalid params" if _invalid_params.empty?
|
104
|
+
end
|
105
|
+
|
106
|
+
# symbolize keys
|
107
|
+
def symbolize_keys payload
|
108
|
+
@params = payload.inject({}) { |hash, (k, v)| hash[k.to_sym] = v; hash }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Agora::AgoraDynamicKey
|
2
|
+
class RTMTokenBuilder
|
3
|
+
module Role
|
4
|
+
RTM_USER = 1
|
5
|
+
end
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_accessor :token
|
9
|
+
|
10
|
+
#
|
11
|
+
# @param payload
|
12
|
+
# :app_id app_id The App ID issued to you by Agora. Apply for a new App ID from
|
13
|
+
# Agora Dashboard if it is missing from your kit. See Get an App ID.
|
14
|
+
# :app_certificate app_certificate Certificate of the application that you registered in
|
15
|
+
# the Agora Dashboard. See Get an App Certificate.
|
16
|
+
# :role role Agora::AgoraDynamicKey::RTCTokenBuilder::Role::RTM_USER = 1: RTM USER
|
17
|
+
# :account User Account.
|
18
|
+
# :privilege_expired_ts represented by the number of seconds elapsed since 1/1/1970.
|
19
|
+
# If, for example, you want to access the Agora Service within 10 minutes
|
20
|
+
# after the token is generated, set expireTimestamp as the current time stamp
|
21
|
+
# + 600 (seconds).
|
22
|
+
def build_token payload
|
23
|
+
check! payload, %i[app_id app_certificate role account privilege_expired_ts]
|
24
|
+
token = AccessToken.new @params.merge(:channel_name => @params[:account])
|
25
|
+
token.grant Privilege::RTM_LOGIN, @params[:privilege_expired_ts]
|
26
|
+
token.build!
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
# params check
|
31
|
+
def check!(payload, args)
|
32
|
+
raise InvalidParamsError.new(params: payload), "invalid params" if payload.nil? or payload.empty?
|
33
|
+
symbolize_keys payload.select { |key| args.include? key }
|
34
|
+
missing_keys = args - @params.keys
|
35
|
+
raise InvalidParamsError.new(params: payload, missing_keys: missing_keys), "missing params" if missing_keys.size != 0
|
36
|
+
_invalid_params = @params.select { |hash, (k, v)| v.nil? or v.empty?}
|
37
|
+
raise InvalidParamsError.new(params: payload), "invalid params" if _invalid_params.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
# symbolize keys
|
41
|
+
def symbolize_keys payload
|
42
|
+
@params = payload.inject({}) { |hash, (k, v)| hash[k.to_sym] = v; hash }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Agora::AgoraDynamicKey
|
4
|
+
class Sign
|
5
|
+
MAX_SIZE = 1024
|
6
|
+
SHA256 = OpenSSL::Digest.new("sha256")
|
7
|
+
class InvalidToken < StandardError; end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
private def parse_map_uint32 map
|
11
|
+
binary = [map.size].pack "v"
|
12
|
+
binary << map.flatten.pack("vV"*map.size)
|
13
|
+
end
|
14
|
+
|
15
|
+
def encode option
|
16
|
+
encode! option
|
17
|
+
rescue
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def encode! option
|
22
|
+
# pack message
|
23
|
+
message = [option.salt, option.expired_ts].pack "VV" # pack into uint16 with little endian
|
24
|
+
message << parse_map_uint32(option.privileges)
|
25
|
+
|
26
|
+
# generate signature
|
27
|
+
to_sign = "#{option.app_id}#{option.channel_name}#{option.uid}#{message}"
|
28
|
+
|
29
|
+
sign = OpenSSL::HMAC.new(option.app_certificate, SHA256).update(to_sign).digest
|
30
|
+
|
31
|
+
crc32_channel_name = Zlib::crc32(option.channel_name) & 0xffffffff
|
32
|
+
crc32_uid = Zlib::crc32("#{option.uid}") & 0xffffffff
|
33
|
+
|
34
|
+
uint32_channel_name = [crc32_channel_name].pack "V"
|
35
|
+
uint32_uid = [crc32_uid].pack "V"
|
36
|
+
|
37
|
+
uint16_sign_size = [sign.size].pack "v"
|
38
|
+
|
39
|
+
uint16_message_size = [message.size].pack "v"
|
40
|
+
# generate content
|
41
|
+
content = "#{uint16_sign_size}#{sign}#{uint32_channel_name}#{uint32_uid}#{uint16_message_size}#{message}"
|
42
|
+
# final content
|
43
|
+
"#{AccessToken::VERSION}#{option.app_id}#{Base64.strict_encode64(content)}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def decode string
|
47
|
+
docode!
|
48
|
+
rescue
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def decode! string
|
53
|
+
version = string[0..2]
|
54
|
+
raise InvalidToken, "can't match version" unless version == Agora::AgoraDynamicKey::AccessToken::VERSION
|
55
|
+
appId = string[3..3+31]
|
56
|
+
content = string[3+32..-1]
|
57
|
+
content_binary = Base64.strict_decode64(content)
|
58
|
+
uint16_sign_size = content_binary.unpack("v")[0]
|
59
|
+
sign = content_binary[2, uint16_sign_size].unpack "H*"
|
60
|
+
offset = uint16_sign_size + 2
|
61
|
+
uint32_channel_name, uint32_uid = content_binary[offset..offset+1].unpack("VV")
|
62
|
+
offset = offset + 8
|
63
|
+
uint16_message_size = content_binary[offset..offset+1].unpack("v")[0]
|
64
|
+
offset = offset + 2
|
65
|
+
message = content_binary[offset..offset+uint16_message_size]
|
66
|
+
salt, expired_ts = message[0..7].unpack("V*")
|
67
|
+
privileges_size = message[8..9].unpack("v")[0]
|
68
|
+
message[10..-1].unpack("vV"*privileges_size)
|
69
|
+
true
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'securerandom'
|
3
|
+
require 'zlib'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
module Agora
|
7
|
+
module DynamicKey
|
8
|
+
require_relative 'dynamic_key/sign'
|
9
|
+
require_relative 'dynamic_key/access_token'
|
10
|
+
require_relative 'dynamic_key/rtc_token_builder'
|
11
|
+
require_relative 'dynamic_key/rtm_token_builder'
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'zlib'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Agora::AgoraDynamicKey2
|
6
|
+
class Service
|
7
|
+
attr_accessor :type, :privileges
|
8
|
+
|
9
|
+
def initialize(type)
|
10
|
+
@type = type
|
11
|
+
@privileges = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_privilege(privilege, expire)
|
15
|
+
@privileges[privilege] = expire
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch_uid(uid)
|
19
|
+
return '' if uid.eql?(0)
|
20
|
+
|
21
|
+
uid.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def pack
|
25
|
+
Util.pack_uint16(@type) + Util.pack_map_uint32(@privileges)
|
26
|
+
end
|
27
|
+
|
28
|
+
def unpack(data)
|
29
|
+
@privileges, data = Util.unpack_map_uint32(data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ServiceRtc < Service
|
34
|
+
attr_accessor :channel_name, :uid
|
35
|
+
|
36
|
+
SERVICE_TYPE = 1
|
37
|
+
PRIVILEGE_JOIN_CHANNEL = 1
|
38
|
+
PRIVILEGE_PUBLISH_AUDIO_STREAM = 2
|
39
|
+
PRIVILEGE_PUBLISH_VIDEO_STREAM = 3
|
40
|
+
PRIVILEGE_PUBLISH_DATA_STREAM = 4
|
41
|
+
|
42
|
+
def initialize(channel_name = '', uid = '')
|
43
|
+
super(SERVICE_TYPE)
|
44
|
+
@channel_name = channel_name
|
45
|
+
@uid = fetch_uid(uid)
|
46
|
+
end
|
47
|
+
|
48
|
+
def pack
|
49
|
+
super() + Util.pack_string(@channel_name) + Util.pack_string(@uid)
|
50
|
+
end
|
51
|
+
|
52
|
+
def unpack(data)
|
53
|
+
_, data = super(data)
|
54
|
+
@channel_name, data = Util.unpack_string(data)
|
55
|
+
@uid, data = Util.unpack_string(data)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class ServiceRtm < Service
|
60
|
+
attr_accessor :user_id
|
61
|
+
|
62
|
+
SERVICE_TYPE = 2
|
63
|
+
PRIVILEGE_JOIN_LOGIN = 1
|
64
|
+
|
65
|
+
def initialize(user_id = '')
|
66
|
+
super(SERVICE_TYPE)
|
67
|
+
@user_id = user_id
|
68
|
+
end
|
69
|
+
|
70
|
+
def pack
|
71
|
+
super() + Util.pack_string(@user_id)
|
72
|
+
end
|
73
|
+
|
74
|
+
def unpack(data)
|
75
|
+
_, data = super(data)
|
76
|
+
@user_id, data = Util.unpack_string(data)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class ServiceFpa < Service
|
81
|
+
SERVICE_TYPE = 4
|
82
|
+
PRIVILEGE_LOGIN = 1
|
83
|
+
|
84
|
+
def initialize
|
85
|
+
super(SERVICE_TYPE)
|
86
|
+
end
|
87
|
+
|
88
|
+
def pack
|
89
|
+
super()
|
90
|
+
end
|
91
|
+
|
92
|
+
def unpack(data)
|
93
|
+
_, data = super(data)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class ServiceChat < Service
|
98
|
+
attr_accessor :uid
|
99
|
+
|
100
|
+
SERVICE_TYPE = 5
|
101
|
+
PRIVILEGE_USER = 1
|
102
|
+
PRIVILEGE_APP = 2
|
103
|
+
|
104
|
+
def initialize(uid = '')
|
105
|
+
super(SERVICE_TYPE)
|
106
|
+
@uid = fetch_uid(uid)
|
107
|
+
end
|
108
|
+
|
109
|
+
def pack
|
110
|
+
super() + Util.pack_string(@uid)
|
111
|
+
end
|
112
|
+
|
113
|
+
def unpack(data)
|
114
|
+
_, data = super(data)
|
115
|
+
@uid, data = Util.unpack_string(data)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class ServiceApaas < Service
|
120
|
+
attr_accessor :room_uuid, :user_uuid, :role
|
121
|
+
|
122
|
+
SERVICE_TYPE = 7
|
123
|
+
PRIVILEGE_ROOM_USER = 1
|
124
|
+
PRIVILEGE_USER = 2
|
125
|
+
PRIVILEGE_APP = 3
|
126
|
+
|
127
|
+
def initialize(room_uuid = '', user_uuid = '', role = -1)
|
128
|
+
super(SERVICE_TYPE)
|
129
|
+
@room_uuid = room_uuid
|
130
|
+
@user_uuid = user_uuid
|
131
|
+
@role = role
|
132
|
+
end
|
133
|
+
|
134
|
+
def pack
|
135
|
+
super() + Util.pack_string(@room_uuid) + Util.pack_string(@user_uuid) + Util.pack_int16(@role)
|
136
|
+
end
|
137
|
+
|
138
|
+
def unpack(data)
|
139
|
+
_, data = super(data)
|
140
|
+
@room_uuid, data = Util.unpack_string(data)
|
141
|
+
@user_uuid, data = Util.unpack_string(data)
|
142
|
+
@role, data = Util.unpack_int16(data)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class AccessToken
|
147
|
+
attr_accessor :app_cert, :app_id, :expire, :issue_ts, :salt, :services
|
148
|
+
|
149
|
+
VERSION = '007'.freeze
|
150
|
+
VERSION_LENGTH = 3
|
151
|
+
SERVICES = { ServiceRtc::SERVICE_TYPE => ServiceRtc,
|
152
|
+
ServiceRtm::SERVICE_TYPE => ServiceRtm,
|
153
|
+
ServiceFpa::SERVICE_TYPE => ServiceFpa,
|
154
|
+
ServiceChat::SERVICE_TYPE => ServiceChat,
|
155
|
+
ServiceApaas::SERVICE_TYPE => ServiceApaas }.freeze
|
156
|
+
|
157
|
+
def initialize(app_id = '', app_cert = '', expire = 900)
|
158
|
+
@app_id = app_id
|
159
|
+
@app_cert = app_cert
|
160
|
+
@expire = expire
|
161
|
+
@issue_ts = Time.now.to_i
|
162
|
+
@salt = rand(1...99_999_999)
|
163
|
+
@services = {}
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_service(service)
|
167
|
+
@services[service.type] = service
|
168
|
+
end
|
169
|
+
|
170
|
+
def build
|
171
|
+
return '' if !uuid?(@app_id) || !uuid?(@app_cert)
|
172
|
+
|
173
|
+
signing = fetch_sign
|
174
|
+
data = Util.pack_string(@app_id) + Util.pack_uint32(@issue_ts) + Util.pack_uint32(@expire) \
|
175
|
+
+ Util.pack_uint32(@salt) + Util.pack_uint16(@services.size)
|
176
|
+
|
177
|
+
@services.each do |_, service|
|
178
|
+
data += service.pack
|
179
|
+
end
|
180
|
+
|
181
|
+
signature = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), signing, data)
|
182
|
+
fetch_version + Base64.strict_encode64(Zlib::Deflate.deflate(Util.pack_string(signature) + data))
|
183
|
+
end
|
184
|
+
|
185
|
+
def fetch_sign
|
186
|
+
sign = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), Util.pack_uint32(@issue_ts), @app_cert)
|
187
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), Util.pack_uint32(@salt), sign)
|
188
|
+
end
|
189
|
+
|
190
|
+
def fetch_version
|
191
|
+
VERSION
|
192
|
+
end
|
193
|
+
|
194
|
+
def uuid?(str)
|
195
|
+
return false if str.length != 32
|
196
|
+
|
197
|
+
true
|
198
|
+
end
|
199
|
+
|
200
|
+
def parse(token)
|
201
|
+
return false if token[0..VERSION_LENGTH - 1] != fetch_version
|
202
|
+
|
203
|
+
data = Zlib::Inflate.inflate(Base64.strict_decode64(token[VERSION_LENGTH..-1]))
|
204
|
+
signature, data = Util.unpack_string(data)
|
205
|
+
@app_id, data = Util.unpack_string(data)
|
206
|
+
@issue_ts, data = Util.unpack_uint32(data)
|
207
|
+
@expire, data = Util.unpack_uint32(data)
|
208
|
+
@salt, data = Util.unpack_uint32(data)
|
209
|
+
service_num, data = Util.unpack_uint16(data)
|
210
|
+
|
211
|
+
(1..service_num).each do
|
212
|
+
service_type, data = Util.unpack_uint16(data)
|
213
|
+
service = SERVICES[service_type].new
|
214
|
+
_, data = service.unpack(data)
|
215
|
+
@services[service_type] = service
|
216
|
+
end
|
217
|
+
true
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Agora::AgoraDynamicKey2
|
2
|
+
class ApaasTokenBuilder
|
3
|
+
# Build room user token.
|
4
|
+
#
|
5
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
6
|
+
# from your kit. See Get an App ID.
|
7
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
8
|
+
# See Get an App Certificate.
|
9
|
+
# room_uuid: The room's id, must be unique.
|
10
|
+
# user_uuid: The user's id, must be unique.
|
11
|
+
# role: The user's role.
|
12
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
13
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
14
|
+
# return: The room user token.
|
15
|
+
def self.build_room_user_token(app_id, app_certificate, room_uuid, user_uuid, role, expire)
|
16
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
17
|
+
|
18
|
+
chat_user_id = Digest::MD5.hexdigest user_uuid
|
19
|
+
service_apaas = Agora::AgoraDynamicKey2::ServiceApaas.new(room_uuid, user_uuid, role)
|
20
|
+
service_apaas.add_privilege(Agora::AgoraDynamicKey2::ServiceApaas::PRIVILEGE_ROOM_USER, expire)
|
21
|
+
access_token.add_service(service_apaas)
|
22
|
+
|
23
|
+
service_rtm = Agora::AgoraDynamicKey2::ServiceRtm.new(user_uuid)
|
24
|
+
service_rtm.add_privilege(Agora::AgoraDynamicKey2::ServiceRtm::PRIVILEGE_JOIN_LOGIN, expire)
|
25
|
+
access_token.add_service(service_rtm)
|
26
|
+
|
27
|
+
service_chat = Agora::AgoraDynamicKey2::ServiceChat.new(chat_user_id)
|
28
|
+
service_chat.add_privilege(Agora::AgoraDynamicKey2::ServiceChat::PRIVILEGE_USER, expire)
|
29
|
+
access_token.add_service(service_chat)
|
30
|
+
|
31
|
+
access_token.build
|
32
|
+
end
|
33
|
+
|
34
|
+
# Build user token.
|
35
|
+
#
|
36
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
37
|
+
# from your kit. See Get an App ID.
|
38
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
39
|
+
# See Get an App Certificate.
|
40
|
+
# user_uuid: The user's id, must be unique.
|
41
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
42
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
43
|
+
# return: The user token.
|
44
|
+
def self.build_user_token(app_id, app_certificate, user_uuid, expire)
|
45
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
46
|
+
|
47
|
+
service_apaas = Agora::AgoraDynamicKey2::ServiceApaas.new('', user_uuid)
|
48
|
+
service_apaas.add_privilege(Agora::AgoraDynamicKey2::ServiceApaas::PRIVILEGE_USER, expire)
|
49
|
+
access_token.add_service(service_apaas)
|
50
|
+
|
51
|
+
access_token.build
|
52
|
+
end
|
53
|
+
|
54
|
+
# Build app token.
|
55
|
+
#
|
56
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
57
|
+
# from your kit. See Get an App ID.
|
58
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
59
|
+
# See Get an App Certificate.
|
60
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
61
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
62
|
+
# return: The app token.
|
63
|
+
def self.build_app_token(app_id, app_certificate, expire)
|
64
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
65
|
+
|
66
|
+
service_apaas = Agora::AgoraDynamicKey2::ServiceApaas.new
|
67
|
+
service_apaas.add_privilege(Agora::AgoraDynamicKey2::ServiceApaas::PRIVILEGE_APP, expire)
|
68
|
+
access_token.add_service(service_apaas)
|
69
|
+
|
70
|
+
access_token.build
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Agora::AgoraDynamicKey2
|
2
|
+
class ChatTokenBuilder
|
3
|
+
# Build the Chat user token.
|
4
|
+
#
|
5
|
+
# @param app_id: The App ID issued to you by Agora. Apply for a new App ID from
|
6
|
+
# Agora Dashboard if it is missing from your kit. See Get an App ID.
|
7
|
+
# @param app_certificate: Certificate of the application that you registered in
|
8
|
+
# the Agora Dashboard. See Get an App Certificate.
|
9
|
+
# @param user_id: The user's account, max length is 64 Bytes.
|
10
|
+
# @param expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
11
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
12
|
+
# @return The Chat User token.
|
13
|
+
def self.build_user_token(app_id, app_certificate, user_id, expire)
|
14
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
15
|
+
|
16
|
+
service_chat = Agora::AgoraDynamicKey2::ServiceChat.new(user_id)
|
17
|
+
service_chat.add_privilege(Agora::AgoraDynamicKey2::ServiceChat::PRIVILEGE_USER, expire)
|
18
|
+
access_token.add_service(service_chat)
|
19
|
+
|
20
|
+
access_token.build
|
21
|
+
end
|
22
|
+
|
23
|
+
# Build the Chat App token.
|
24
|
+
#
|
25
|
+
# @param app_id: The App ID issued to you by Agora. Apply for a new App ID from
|
26
|
+
# Agora Dashboard if it is missing from your kit. See Get an App ID.
|
27
|
+
# @param app_certificate: Certificate of the application that you registered in
|
28
|
+
# the Agora Dashboard. See Get an App Certificate.
|
29
|
+
# @param expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
30
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
31
|
+
# @return The Chat App token.
|
32
|
+
def self.build_app_token(app_id, app_certificate, expire)
|
33
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
34
|
+
|
35
|
+
service_chat = Agora::AgoraDynamicKey2::ServiceChat.new
|
36
|
+
service_chat.add_privilege(Agora::AgoraDynamicKey2::ServiceChat::PRIVILEGE_APP, expire)
|
37
|
+
access_token.add_service(service_chat)
|
38
|
+
|
39
|
+
access_token.build
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Agora::AgoraDynamicKey2
|
2
|
+
class EducationTokenBuilder
|
3
|
+
# Build room user token.
|
4
|
+
#
|
5
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
6
|
+
# from your kit. See Get an App ID.
|
7
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
8
|
+
# See Get an App Certificate.
|
9
|
+
# room_uuid: The room's id, must be unique.
|
10
|
+
# user_uuid: The user's id, must be unique.
|
11
|
+
# role: The user's role.
|
12
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
13
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
14
|
+
# return: The room user token.
|
15
|
+
def self.build_room_user_token(app_id, app_certificate, room_uuid, user_uuid, role, expire)
|
16
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
17
|
+
|
18
|
+
chat_user_id = Digest::MD5.hexdigest user_uuid
|
19
|
+
service_apaas = Agora::AgoraDynamicKey2::ServiceApaas.new(room_uuid, user_uuid, role)
|
20
|
+
service_apaas.add_privilege(Agora::AgoraDynamicKey2::ServiceApaas::PRIVILEGE_ROOM_USER, expire)
|
21
|
+
access_token.add_service(service_apaas)
|
22
|
+
|
23
|
+
service_rtm = Agora::AgoraDynamicKey2::ServiceRtm.new(user_uuid)
|
24
|
+
service_rtm.add_privilege(Agora::AgoraDynamicKey2::ServiceRtm::PRIVILEGE_JOIN_LOGIN, expire)
|
25
|
+
access_token.add_service(service_rtm)
|
26
|
+
|
27
|
+
service_chat = Agora::AgoraDynamicKey2::ServiceChat.new(chat_user_id)
|
28
|
+
service_chat.add_privilege(Agora::AgoraDynamicKey2::ServiceChat::PRIVILEGE_USER, expire)
|
29
|
+
access_token.add_service(service_chat)
|
30
|
+
|
31
|
+
access_token.build
|
32
|
+
end
|
33
|
+
|
34
|
+
# Build user token.
|
35
|
+
#
|
36
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
37
|
+
# from your kit. See Get an App ID.
|
38
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
39
|
+
# See Get an App Certificate.
|
40
|
+
# user_uuid: The user's id, must be unique.
|
41
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
42
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
43
|
+
# return: The user token.
|
44
|
+
def self.build_user_token(app_id, app_certificate, user_uuid, expire)
|
45
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
46
|
+
|
47
|
+
service_apaas = Agora::AgoraDynamicKey2::ServiceApaas.new('', user_uuid)
|
48
|
+
service_apaas.add_privilege(Agora::AgoraDynamicKey2::ServiceApaas::PRIVILEGE_USER, expire)
|
49
|
+
access_token.add_service(service_apaas)
|
50
|
+
|
51
|
+
access_token.build
|
52
|
+
end
|
53
|
+
|
54
|
+
# Build app token.
|
55
|
+
#
|
56
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
57
|
+
# from your kit. See Get an App ID.
|
58
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
59
|
+
# See Get an App Certificate.
|
60
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
61
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
62
|
+
# return: The app token.
|
63
|
+
def self.build_app_token(app_id, app_certificate, expire)
|
64
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
65
|
+
|
66
|
+
service_apaas = Agora::AgoraDynamicKey2::ServiceApaas.new
|
67
|
+
service_apaas.add_privilege(Agora::AgoraDynamicKey2::ServiceApaas::PRIVILEGE_APP, expire)
|
68
|
+
access_token.add_service(service_apaas)
|
69
|
+
|
70
|
+
access_token.build
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
module Agora::AgoraDynamicKey2
|
3
|
+
class FpaTokenBuilder
|
4
|
+
# Build the FPA token.
|
5
|
+
#
|
6
|
+
# @param app_id The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
7
|
+
# from your kit. See Get an App ID.
|
8
|
+
# @param app_certificate Certificate of the application that you registered in the Agora Dashboard.
|
9
|
+
# See Get an App Certificate.
|
10
|
+
# @return The FPA token.
|
11
|
+
def self.build_token(app_id, app_certificate)
|
12
|
+
access_token = Agora::AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, 24 * 3600)
|
13
|
+
|
14
|
+
service_fpa = Agora::AgoraDynamicKey2::ServiceFpa.new
|
15
|
+
service_fpa.add_privilege(Agora::AgoraDynamicKey2::ServiceFpa::PRIVILEGE_LOGIN, 0)
|
16
|
+
access_token.add_service(service_fpa)
|
17
|
+
|
18
|
+
access_token.build
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|