Token authentication

更新时间:
复制 MD 格式

Tokens are security signatures that prevent unauthorized access to your cloud services. You generate a token on your server and distribute it to the client SDK, which uses the token to join a channel.

Prerequisites

  • You have an Alibaba Cloud account and the ApsaraVideo Live service is activated.

  • You have created an ARTC application and obtained its AppID and AppKey. For more information, see Create an ARTC application.

Sample code

Server-side generation (recommended)

Alibaba Cloud provides code examples for Go, Java, Python, and other languages. See Token generation code examples.

Client-side generation (for development and debugging only)

Important

Because generating a token requires your AppKey, embedding it in your client-side code poses a serious security risk. For production applications, generate tokens on your app server and then distribute them to the client.

During development and debugging, if your app server does not yet generate tokens, you can temporarily generate one on the client by referencing the APIExample logic. Sample code:

Generate a token on an Android client: Android/ARTCExample/KeyCenter/src/main/java/com/aliyun/artc/api/keycenter/ARTCTokenHelper.java

Generate a token on an iOS client: iOS/ARTCExample/Common/ARTCTokenHelper.swift

Generate a token on a HarmonyOS client: Harmony/ARTCExample/entry/src/main/ets/common/keycenter/ARTCTokenHelper.ets

Join a channel with a token

Note

For production applications, we strongly recommend generating tokens on your app server and distributing them to the client to ensure security.

Use a token to join a channel on an Android client: Android/ARTCExample/QuickStart/src/main/java/com/aliyun/artc/api/quickstart/TokenGenerate/TokenGenerateActivity.java
Use a token to join a channel on an iOS client: iOS/ARTCExample/QuickStart/TokenGenerate/TokenGenerateVC.swift

Use a token to join a channel on a HarmonyOS client: Harmony/ARTCExample/entry/src/main/ets/pages/quickstart/TokenGenerate.ets

How it works

Token workflow

image
  1. The client requests a token from the app server. The app server generates a token based on the required rules and returns it.

  2. The client uses the token, AppID, channel ID, user ID, and other information to join the specified channel.

  3. The Alibaba Cloud ARTC service validates the token, allowing the client to join the channel.

Token generation

The following table describes the parameters used to generate a token.

Parameter

Description

AppID

The ID and key of your ARTC application, generated when you create an ARTC application in the ApsaraVideo Live console. See Get application development parameters.

AppKey

ChannelId

A user-defined channel ID. The value must be a string and cannot be a Long. It can contain digits, uppercase letters, lowercase letters, hyphens (-), and underscores (_), and cannot exceed 64 characters in length. The host and co-streaming guests must use the same channel ID.

UserID

A user-defined user ID. The value must be a string and cannot be a Long. It can contain digits, uppercase letters, lowercase letters, hyphens (-), and underscores (_), and cannot exceed 64 characters in length.

nonce

The nonce can be an empty string. We recommend leaving it empty.

timestamp

The expiration timestamp in seconds. We recommend setting the expiration to 24 hours. To set a 24-hour expiration, add 86,400 (24 * 60 * 60) to the current timestamp in seconds.

Token generation process example:

yuque_diagram (1)

Token generation code example:

// 1. Concatenate the fields: AppID+AppKey+ChannelID+UserID+Nonce+Timestamp
// 2. Use the SHA-256 algorithm to hash the concatenated string and generate the token.
token = sha256(AppID+AppKey+ChannelId+UserID+Nonce+timestamp)
// Example:
AppID = "abc",AppKey="abckey",ChannelID="abcChannel",UserID="abcUser",Nonce="",Timestamp=1699423634
token = sha256("abcabckeyabcChannelabcUser1699423634") = "3c9ee8d9f8734f0b7560ed8022a0590659113955819724fc9345ab8eedf84f31"

ARTC scenarios

The following examples show how to use a token to authenticate users joining a channel in an ARTC scenario on Android and iOS.

Single-parameter method (recommended)

The ARTC SDK provides a single-parameter API for joining a channel. This approach prevents channel joining failures caused by parameter inconsistencies between your app server and the client. Package the authentication token, appid, channelid, nonce, userid, and timestamp into a JSON object, and then Base64-encode the JSON string to create a new authentication string (Base64 token).

Note

When contacting Alibaba Cloud for technical support, you must provide the Base64 token or the username you passed.

yuque_diagram (3)

Base64 token generation example

Java

package com.example;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Calendar;
import org.json.JSONObject;

public class App {

    public static String createBase64Token(String appid, String appkey, String channelid, String userid) {
        // Calculate the expiration timestamp (24 hours from now)
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR_OF_DAY, 24);
        long timestamp = calendar.getTimeInMillis() / 1000;

        // Concatenate the strings
        String stringBuilder = appid + appkey + channelid + userid + timestamp;

        // Calculate the SHA-256 hash
        String token = sha256(stringBuilder);

        // Create the JSON object
        JSONObject base64tokenJson = new JSONObject();
        base64tokenJson.put("appid", appid);
        base64tokenJson.put("channelid", channelid);
        base64tokenJson.put("userid", userid);
        base64tokenJson.put("nonce", "");
        base64tokenJson.put("timestamp", timestamp);
        base64tokenJson.put("token", token);

        // Convert the JSON object to a string and encode it in Base64
        String jsonStr = base64tokenJson.toString();
        String base64token = Base64.getEncoder().encodeToString(jsonStr.getBytes(StandardCharsets.UTF_8));
        return base64token;
    }

    private static String sha256(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1)
                    hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String appid = "your_appid";
        String appkey = "your_appkey";
        String channel_id = "your_channel_id";
        String user_id = "your_user_id";

        String base64token = createBase64Token(appid, appkey, channel_id, user_id);
        System.out.println("Base64 Token: " + base64token);
    }
}

Go

package main

import (
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"time"
)

func createBase64Token(appid, appkey, channelID, userID string) (string, error) {
	// Calculate the expiration timestamp (24 hours from now)
	timestamp := time.Now().Add(24 * time.Hour).Unix()

	// Concatenate the strings
	stringBuilder := appid + appkey + channelID + userID + fmt.Sprintf("%d", timestamp)

	// Calculate the SHA-256 hash
	hasher := sha256.New()
	hasher.Write([]byte(stringBuilder))
	token := hasher.Sum(nil)

	// Convert the hash to a hexadecimal string using encoding/hex
	tokenHex := hex.EncodeToString(token)

	// Create the JSON object
	tokenJSON := map[string]interface{}{
		"appid":     appid,
		"channelid": channelID,
		"userid":    userID,
		"nonce":     "",
		"timestamp": timestamp,
		"token":     tokenHex,
	}

	// Convert the JSON object to a string and encode it in Base64
	jsonBytes, err := json.Marshal(tokenJSON)
	if err != nil {
		return "", err
	}
	base64Token := base64.StdEncoding.EncodeToString(jsonBytes)

	return base64Token, nil
}

func main() {
	appid := "your_appid"
	appkey := "your_appkey"
	channelID := "your_channel_id"
	userID := "your_user_id"

	token, err := createBase64Token(appid, appkey, channelID, userID)
	if err != nil {
		fmt.Println("Error creating token:", err)
		return
	}
	fmt.Println("Base64 Token:", token)
}

Python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import hashlib
import datetime
import time
import base64
import json

def create_base64_token(app_id, app_key, channel_id, user_id):
    expire = datetime.datetime.now() + datetime.timedelta(days=1)
    timestamp = int(time.mktime(expire.timetuple()))
    h = hashlib.sha256()
    h.update(str(app_id).encode('utf-8'))
    h.update(str(app_key).encode('utf-8'))
    h.update(str(channel_id).encode('utf-8'))
    h.update(str(user_id).encode('utf-8'))
    h.update(str(timestamp).encode('utf-8'))
    token = h.hexdigest()

    jsonToken = {'appid':app_id,
                 'channelid':channel_id,
                 'userid':user_id,
                 'nonce':'',
                 'timestamp':timestamp,
                 'token':token
                }
    base64Token = base64.b64encode(json.dumps(jsonToken).encode())

    return base64Token

def main():
    app_id = 'your_appid'
    app_key = 'your_appkey'
    channel_id = 'your_channel_id'
    user_id = 'your_user_id'

    base64Token = create_base64_token(app_id, app_key, channel_id, user_id)
    
    print(base64Token)

if __name__ == '__main__':
    main()

Node.js

'use strict'
const crypto = require('crypto')
function create_base64_token(appid, appkey, channelid, userid) {
    let timestamp = Math.floor(Date.now() / 1000 + 24 * 60 * 60)

    let string_builder = appid + appkey + channelid + userid + timestamp.toString()
    let token = crypto.createHash('sha256').update(string_builder).digest('hex')
    let base64tokenJson = {
        appid:appid,
        channelid:channelid,
        userid:userid,
        nonce:'',
        timestamp:timestamp,
        token:token
    }
    let base64token = Buffer.from(JSON.stringify(base64tokenJson), 'utf-8').toString('base64')
    return base64token
}

let appid = "your_appid";
let appkey = "your_appkey";
let channel_id = "your_channel_id";
let user_id = "your_user_id";

let base64token = create_base64_token(appid, appkey, channel_id, user_id)
console.log(base64token)

Rust

use chrono::{Duration, Utc};
use sha2::{Sha256, Digest};
use serde_json::json;
use base64::encode;

fn create_base64_token(appid: &str, appkey: &str, channel_id: &str, user_id: &str) -> String {
    // Calculate the expiration timestamp (24 hours from now)
    let timestamp = (Utc::now() + Duration::hours(24)).timestamp();

    // Concatenate the strings
    let string_builder = format!("{}{}{}{}{}", appid, appkey, channel_id, user_id, timestamp);

    // Calculate the SHA-256 hash
    let mut hasher = Sha256::new();
    hasher.update(string_builder);
    let token = hasher.finalize();
    let token_hex = format!("{:x}", token);

    // Create the JSON object
    let token_json = json!({
        "appid": appid,
        "channelid": channel_id,
        "userid": user_id,
        "nonce": "",
        "timestamp": timestamp,
        "token": token_hex
    });

    // Convert the JSON object to a string and encode it in Base64
    let base64_token = encode(token_json.to_string());

    base64_token
}

fn main() {
    let appid = "your_appid";
    let appkey = "your_appkey";
    let channel_id = "your_channel_id";
    let user_id = "your_user_id";

    let token = create_base64_token(appid, appkey, channel_id, user_id);
    println!("Base64 Token: {}", token);
}

Client API call examples

After the client obtains the Base64 token from your app server, it uses the token to join the channel.

  • Android:

    // You can set channelId and userId to null. If you pass values for channelId and userId, they must match those used to generate the token. You can use this feature to verify parameter consistency between the server and the client.
    // base64Token is the Base64-encoded token.
    // username is an identifier passed for troubleshooting purposes.
    mAliRtcEngine.joinChannel(base64Token, null, null, "username");
  • iOS:

    // You can set channelId and userId to null. If you pass values for channelId and userId, they must match those used to generate the token. You can use this feature to verify parameter consistency between the server and the client.
    // base64Token is the Base64-encoded token.
    // username is an identifier passed for troubleshooting purposes.
    [self.engine joinChannel:base64Token channelId:nil userId:nil name:@"username" onResultWithUserId:nil];

Multi-parameter method

The ARTC SDK also provides a multi-parameter API for joining a channel. This method uses the AliRtcAuthInfo data structure to store the token and user information for authentication.

Important

The channel ID and user ID used to join the channel must match those used to generate the token.

  • Android:

    // Pass the token and user information for the multi-parameter method.
    AliRtcAuthInfo authInfo = new AliRtcAuthInfo();
    authInfo.appId = appId;
    authInfo.channelId = channelId;
    authInfo.userId = userId;
    authInfo.timestamp = timestamp;
    authInfo.nonce = nonce;
    authInfo.token = token;
    // Join the channel.
    mAliRtcEngine.joinChannel(authInfo, "");
  • iOS:

    // Pass the token and user information for the multi-parameter method.
    let authInfo = AliRtcAuthInfo()
    authInfo.appId = appId
    authInfo.channelId = channelId
    authInfo.nonce = nonce
    authInfo.userId = userId
    authInfo.timestamp = timestamp
    authInfo.token = authToken
    // Join the channel.
    self.rtcEngine?.joinChannel(authInfo, name: nil)

Co-streaming scenarios

Add the token, AppID, ChannelID, nonce, userId, and timestamp parameters to the query string of the co-streaming URL, and then pass the URL to the SDK. For details about the URL fields, see Co-streaming URL rules.

image

Example URLs

Ingest URL for co-streaming or battle scenarios:

artc://live.aliyun.com/push/633?timestamp=1685094092&token=fe4e674ade****6686&userId=718&sdkAppId=xxx

Streaming URL for co-streaming or battle scenarios:

artc://live.aliyun.com/play/633?timestamp=1685094092&token=fe4e674ade****6686&userId=718&sdkAppId=xxx
Note

live.aliyun.com is a fixed prefix for co-streaming URLs and is not a real domain name. Do not perform domain-related operations, such as ping, traceroute, or telnet, on it.

Handling token expiration

When you create a token, the timestamp field defines its expiration time.

After a user joins a channel using a token:

  • The SDK triggers the onAuthInfoWillExpire callback 30 seconds before the token expires. You can call the refreshAuthInfo method to update the authentication information.

  • When the token expires, the SDK triggers the onAuthInfoExpired callback. To remain in the channel, the user must rejoin the channel.