Access Authentication
To ensure the communication security of SparkRTC, access authentication is required when a user joins a room. This chapter describes the implementation principles of SparkRTC access authentication and how to generate an authentication signature.
Authentication Principles
signature = hmacSha256(app_key,(app_id + room_id + user_id + ctime))
Parameter |
Description |
---|---|
app_key |
An authentication key is generated by SparkRTC for each app. The key must be securely stored. For details about how to obtain app_key, see How Do I Obtain a Key? |
app_id |
Application ID generated by SparkRTC. Obtain the value of app_id from Applications on the SparkRTC console. |
room_id |
ID of the room created by the tenant. |
user_id |
User ID used by the tenant to access SparkRTC. |
ctime |
Time when the signature authentication expires. The value is the current UTC time (UNIX timestamp) of the system plus the authentication expiration time (recommended: 2 hours; maximum: < 12 hours). The unit is second.
NOTE:
The value of ctime is the creation time plus the expiration time. For example, if the current time is 9:00 and the authentication expiration time is 30 minutes, the value of ctime is 9:30. That is, the signature becomes invalid after 9:30. |
Tenants are advised to build their own app signature distribution servers to prevent the app_key from being leaked to the app. Figure 1 shows the authentication principles.
Signature Generation Method
To generate a signature, perform the following steps:
- Combine app_id, room_id, user_id , and ctime into a string.
1 2
long ctime = System.currentTimeMillis() / 1000 + 60 * 60; // The validity period is 1 hour, in seconds. String content = app_id + "+" + room_id + "+" + user_id + "+" + ctime;
- Use app_key to encrypt the string content in HMAC-SHA256 mode to obtain the signature string.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
String signatureStr = hmacSha(appKey, content, "HmacSHA256"); static String hmacSha(String KEY, String VALUE, String SHA_TYPE) { try { SecretKeySpec signingKey = new SecretKeySpec(KEY.getBytes("UTF-8"), SHA_TYPE); Mac mac = Mac.getInstance(SHA_TYPE); mac.init(signingKey); byte[] rawHmac = mac.doFinal(VALUE.getBytes("UTF-8")); byte[] hexArray = { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' }; byte[] hexChars = new byte[rawHmac.length * 2]; for (int j = 0; j < rawHmac.length; j++) { int v = rawHmac[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } catch (Exception ex) { throw new RuntimeException(ex); } }
Signature Generation Example
To prevent the app_key from being leaked, you are advised to configure your own app signature distribution server. After app_id, room_id, user_id, and ctime are passed to the server, the server returns the signature. The following is sample code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
package com.xxx.xxx.utils;
import androidx.annotation.NonNull;
import com.alibaba.fastjson.JSON;
import com.huawei.rtcdemo.Constants;
import java.io.IOException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import okhttp3.Response;
public class SignatureUtil {
private static final String TAG = "SignatureUtil";
public interface onSignatureSuccess {
void onSuccess(String signature);
}
public static void getSignature(String appid, String roomid, String userid, long ctime, String signatureKey, onSignatureSuccess callback) {
if (Constants.RTC_SIGNATURE_USE_LOCAL) {
getSignatureLocal(appid, roomid, userid, ctime, signatureKey, callback);
} else {
getSignatureRemote(appid, roomid, userid, ctime, callback);
}
}
private static void getSignatureLocal(String appid, String roomid, String userid, long ctime, String signatureKey, @NonNull onSignatureSuccess callback) {
String content = appid + "+" + roomid + "+" + userid + "+" + ctime; // here "+" is real char in content.
String signature = SignatureUtil.hmacSha256(signatureKey, content);
callback.onSuccess(signature);
}
private static void getSignatureRemote(String appid, String roomid, String userid, long ctime, @NonNull onSignatureSuccess callback) {
new Thread(new Runnable() {
@Override
public void run() {
HttpUtil httpUtil = new HttpUtil();
// Constants.RTC_SIGNATURE_URL indicates the distribution server address with the user's application signature.
String url = Constants.RTC_SIGNATURE_URL + "?appid=" + appid + "&roomid=" + roomid + "&userid=" + userid + "&ctime=" + ctime;
Response response = httpUtil.sendGetMethodWithHead(url, "X-AUTH-TOKEN", Constants.RTC_AUTH_TOKEN);
if (response == null) {
return;
}
if (response.isSuccessful()) {
try {
String json = response.body().string();
String signature = JSON.parseObject(json).getString("signature");
callback.onSuccess(signature);
} catch (IOException e) {
LogUtil.e(TAG, "getSignature failed:" + e.getMessage());
}
} else {
LogUtil.e(TAG, "getSignature failed!");
}
}
}).start();
}
public static String hmacSha256(String KEY, String VALUE) {
return hmacSha(KEY, VALUE, "HmacSHA256");
}
private static String hmacSha(String KEY, String VALUE, String SHA_TYPE) {
try {
SecretKeySpec signingKey = new SecretKeySpec(KEY.getBytes("UTF-8"), SHA_TYPE);
Mac mac = Mac.getInstance(SHA_TYPE);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(VALUE.getBytes("UTF-8"));
byte[] hexArray = {
(byte) '0', (byte) '1', (byte) '2', (byte) '3',
(byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
(byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
};
byte[] hexChars = new byte[rawHmac.length * 2];
for (int j = 0; j < rawHmac.length; j++) {
int v = rawHmac[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
|
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot