Skip to main content
Android
iOS
Web
Windows
Unity
Flutter
React Native

Update the token-based authentication mechanism

If you integrate the Chat SDK and Agora Video SDK at the same time, Agora recommends you update the token-based authentication mechanism from AccessToken to AccessToken2.

This document uses the JAVA server and the Web client as examples to guide you how to build and update the token-based authentication mechanism step-by-step.

Prerequisites

  • You have built a token server based on Spring Framework and a Web client using Chat according to Authenticate Your Users with Tokens.

  • You have added the Video SDK Token service based on AccessToken to the token server of Chat. To do this, in AgoraChatTokenController.java file, import the RtcTokenBuilder with import com.agora.chat.token.io.agora.media.RtcTokenBuilder; and add the following method:


    _24
    // Generate <Vg k="VSDK" /> AccessToken
    _24
    @GetMapping("/rtc/{rtcChannelName}/{rtcUserId}/{role}/token")
    _24
    public String getRtcToken(@PathVariable String rtcChannelName, @PathVariable int rtcUserId, @PathVariable int role) {
    _24
    _24
    if (!StringUtils.hasText(appid) || !StringUtils.hasText(appcert)) {
    _24
    return "appid or appcert is empty";
    _24
    }
    _24
    _24
    RtcTokenBuilder builder = new RtcTokenBuilder();
    _24
    _24
    RtcTokenBuilder.Role rtcRole;
    _24
    _24
    switch(role) {
    _24
    case 1:
    _24
    default:
    _24
    rtcRole = RtcTokenBuilder.Role.Role_Publisher;
    _24
    break;
    _24
    case 2:
    _24
    rtcRole = RtcTokenBuilder.Role.Role_Subscriber;
    _24
    break;
    _24
    }
    _24
    _24
    return builder.buildTokenWithUid(appid, appcert, rtcChannelName, rtcUserId, rtcRole, expire);
    _24
    }

  • You have added the authentication logic to the client using the using the Video SDK. To do this, create a agoraRtcTokenClient folder with the following two files:

    • index.html


      _12
      <html>
      _12
      _12
      <head>
      _12
      <title>Token demo</title>
      _12
      </head>
      _12
      _12
      <body>
      _12
      <h1>Token demo</h1>
      _12
      <script src="https://download.agora.io/sdk/release/AgoraRTC_N.js"></script>
      _12
      <script src="./client.js"></script>
      _12
      </body>
      _12
      </html>

    • client.js. Replace <Your app ID> with your App ID.


      _96
      var rtc = {
      _96
      // For the local audio and video tracks.
      _96
      localAudioTrack: null,
      _96
      localVideoTrack: null,
      _96
      };
      _96
      _96
      var options = {
      _96
      // Pass your App ID here.
      _96
      appId: "<Your app ID>",
      _96
      // Set the channel name.
      _96
      channel: "ChannelA",
      _96
      // Set the user role as host (who can both send and receive streams) or audience (who can only receive streams).
      _96
      role: "host",
      _96
      };
      _96
      _96
      // Fetch a token from the sever.
      _96
      function fetchToken(uid, channelName, tokenRole) {
      _96
      _96
      url = 'http://localhost:8090/rtc/' + channelName + '/' + uid + '/' + tokenRole + '/' + 'token'
      _96
      _96
      return new Promise(function (resolve) {
      _96
      _96
      fetch(url)
      _96
      .then(res => res.text())
      _96
      .then((token => { resolve(token); }))
      _96
      _96
      })
      _96
      .catch(function (error) {
      _96
      console.log(error);
      _96
      });
      _96
      }
      _96
      _96
      async function startBasicCall() {
      _96
      const client = AgoraRTC.createClient({ mode: "live", codec: "vp9" });
      _96
      client.setClientRole(options.role);
      _96
      const uid = 123456;
      _96
      _96
      // Fetch a token before calling join to join a channel.
      _96
      let token = await fetchToken(uid, options.channel, 1);
      _96
      _96
      await client.join(options.appId, options.channel, token, uid);
      _96
      rtc.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
      _96
      rtc.localVideoTrack = await AgoraRTC.createCameraVideoTrack();
      _96
      await client.publish([rtc.localAudioTrack, rtc.localVideoTrack]);
      _96
      const localPlayerContainer = document.createElement("div");
      _96
      localPlayerContainer.id = uid;
      _96
      localPlayerContainer.style.width = "640px";
      _96
      localPlayerContainer.style.height = "480px";
      _96
      document.body.append(localPlayerContainer);
      _96
      _96
      rtc.localVideoTrack.play(localPlayerContainer);
      _96
      _96
      console.log("publish success!");
      _96
      _96
      client.on("user-published", async (user, mediaType) => {
      _96
      await client.subscribe(user, mediaType);
      _96
      console.log("subscribe success");
      _96
      _96
      if (mediaType === "video") {
      _96
      const remoteVideoTrack = user.videoTrack;
      _96
      const remotePlayerContainer = document.createElement("div");
      _96
      remotePlayerContainer.textContent =
      _96
      "Remote user " + user.uid.toString();
      _96
      remotePlayerContainer.style.width = "640px";
      _96
      remotePlayerContainer.style.height = "480px";
      _96
      document.body.append(remotePlayerContainer);
      _96
      remoteVideoTrack.play(remotePlayerContainer);
      _96
      }
      _96
      _96
      if (mediaType === "audio") {
      _96
      const remoteAudioTrack = user.audioTrack;
      _96
      remoteAudioTrack.play();
      _96
      }
      _96
      _96
      client.on("user-unpublished", (user) => {
      _96
      const remotePlayerContainer = document.getElementById(user.uid);
      _96
      remotePlayerContainer.remove();
      _96
      });
      _96
      });
      _96
      _96
      // When token-privilege-will-expire occurs, fetch a new token from the server and call renewToken to renew the token.
      _96
      client.on("token-privilege-will-expire", async function () {
      _96
      let token = await fetchToken(uid, options.channel, 1);
      _96
      await client.renewToken(token);
      _96
      });
      _96
      _96
      // When token-privilege-did-expire occurs, fetch a new token from the server and call join to rejoin the channel.
      _96
      client.on("token-privilege-did-expire", async function () {
      _96
      console.log("Fetching the new Token");
      _96
      let token = await fetchToken(uid, options.channel, 1);
      _96
      console.log("Rejoining the channel with new Token");
      _96
      await rtc.client.join(options.appId, options.channel, token, uid);
      _96
      });
      _96
      }
      _96
      _96
      startBasicCall();

  • To test the AccessToken server, open index.html with a supported browser to perform the following actions:

    • Successfully joining a channel.
    • Renewing a token every 10 seconds.

Implementation

To upgrade your authentication mechanism to AccessToken 2, use the following procedure.

Upgrade the token server to AccessToken2

This section shows you how to upgrade the token server to AccessToken2.

  1. Import RtcTokenBuilder2 with the following code:


    _1
    import com.agora.chat.token.io.agora.media.RtcTokenBuilder2;

  2. Replace the code for getRtcToken method with the following logic:


    _23
    // Generate <Vg k="VSDK" /> AccessToken2
    _23
    public String getRtcToken(@PathVariable String rtcChannelName, @PathVariable int rtcUserId, @PathVariable int role) {
    _23
    _23
    if (!StringUtils.hasText(appid) || !StringUtils.hasText(appcert)) {
    _23
    return "appid or appcert is empty";
    _23
    }
    _23
    _23
    RtcTokenBuilder2 builder = new RtcTokenBuilder2();
    _23
    _23
    RtcTokenBuilder2.Role rtcRole;
    _23
    _23
    switch(role) {
    _23
    case 1:
    _23
    default:
    _23
    rtcRole = RtcTokenBuilder2.Role.ROLE_PUBLISHER;
    _23
    break;
    _23
    case 2:
    _23
    rtcRole = RtcTokenBuilder2.Role.ROLE_SUBSCRIBER;
    _23
    break;
    _23
    }
    _23
    _23
    return builder.buildTokenWithUid(appid, appcert, rtcChannelName, rtcUserId, rtcRole, expire);
    _23
    }

No extra action is required for the client to get compatible with AccessToken2.

Test the AccessToken2 server

Open index.html with a supported browser to perform the following actions:

  • Successfully joining a channel.
  • Renewing a token every 10 seconds.

Reference

This section introduces token generator libraries, version requirements, and related documents about AccessToken2.

SDK compatibility for AccessToken2

AccessToken2 supports the following versions of the Agora Video SDK

SDKFirst SDK version to support AccessToken2
Video SDK Native SDK3.5.2
Video SDK ELectron SDK3.5.2
Video SDK Unity SDK3.5.2
Video SDK React Native SDK3.5.2
Video SDK Flutter SDK4.2.0
Video SDK Web SDK4.8.0
Video SDK WeChat Mini Program SDKNot supported

Video SDK SDKs that use AccessToken2 can interoperate with Video SDK SDKs that use AccessToken. Also, the Video SDK that supports AccessToken2 also supports AccessToken.

If you use other Video SDK extentions, such as Agora Cloud Recording and Media Push, contact support@agora.io for technical support before upgrading to AccessToken2.

Token generator libraries

Agora provides an open-source AgoraDynamicKey repository on GitHub, which enables you to generate AccessToken2 on your server with programming languages such as C++, Java, and Go.

LanguageAlgorithmCore MethodSample Code
C++HMAC-SHA256buildTokenWithUidRtcTokenBuilder2Sample.cpp
GoHMAC-SHA256buildTokenWithUidsample.go
JavaHMAC-SHA256buildTokenWithUidRtcTokenBuilder2Sample.java
Node.jsHMAC-SHA256buildTokenWithUidRtcTokenBuilder2Sample.js
PHPHMAC-SHA256buildTokenWithUidRtcTokenBuilder2Sample.php
PythonHMAC-SHA256buildTokenWithUidRtcTokenBuilder2Sample.py
Python3HMAC-SHA256buildTokenWithUidRtcTokenBuilder2Sample.py

API reference

Taking Java as an example, this section introduces the parameters and descriptions for the method to generate an AccessToken2.


_1
public String buildTokenWithUid(String appId, String appCertificate, String channelName, int uid, Role role, int expire)

ParameterDescription
appIdThe App ID of your Agora project.
appCertificateThe App Certificate of your Agora project.
channelNameThe channel name. The string length must be less than 64 bytes. Supported character scopes are:
  • All lowercase English letters: a to z.
  • All upper English letters: A to Z.
  • All numeric characters: 0 to 9.
  • The space character.
  • Punctuation characters and other symbols, including: "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " , ", "|", "~", ",".
uidThe user ID of the user to be authenticated. A 32-bit unsigned integer with a value range from 1 to (2³² - 1). It must be unique. Set uid as 0, if you do not want to authenticate the user ID, that is, any uid from the app client can join the channel.
roleThe privilege of the user, either as a publisher or a subscriber. This parameter determines whether a user can publish streams in the channel.
  • ROLE_PUBLISHER(1): (default) The user has the privilege of a publisher, that is, the user can publish streams in the channel.
  • ROLE_SUBSCRIBER(2): The user has the privilege of a subscriber, that is, the user can only subscribe to streams, not publish them, in the channel. This value takes effect only if you have enabled co-host authentication. For details, see Enable co-host authentication.
expireThe Unix timestamp (in seconds) when an AccessToken expires. Set this parameter as the current timestamp plus the valid period of AccessToken2. For example, if you set expire as the current timestamp plus 600, the AccessToken2 expires in 10 minutes. An AccessToken2 is valid for 24 hours at most. If you set it to a period longer than 24 hours, the AccessToken2 is still valid for 24 hours.

API for privilege-level expiration configuration

To facilitate privilege-level configuration in a channel, Agora provides an overloaded method to support configuring the expiration of the AccessToken2 and related privileges:

  • Join a channel
  • Publish audio
  • Publish video
  • Publish data stream

Take Java as an example:


_1
public String buildTokenWithUid(String appId, String appCertificate, String channelName, int uid, int tokenExpire, int joinChannelPrivilegeExpire, int pubAudioPrivilegeExpire, int pubVideoPrivilegeExpire, int pubDataStreamPrivilegeExpire)

This method generates an Video SDK AccessToken2 and supports configuring the following privileges:

  • The expiration time of AccessToken2
  • Joining an Video SDK channel
  • Publishing audio in an Video SDK channel
  • Publishing video in an Video SDK channel
  • Publishing data stream in an Video SDK channel

The privileges of publishing audio in an Video SDK channel, publishing video in an Video SDK channel, and publishing data stream in an Video SDK channel only take effect after enabling co-host authentication.

You can assign multiple privileges to a user. The maximum valid period of each privilege is 24 hours. When a privilege is about to expire or has expired, the Video SDK triggers the onTokenPriviegeWillExpire callback or the onRequestToken callback. You need to take the following actions in your own app logic:

  1. Tag the type of privilege which is about to expire or has expired in your app logic.
  2. The app fetches a new AccessToken2 from the token server.
  3. The SDK calls renewToken to renew the AccessToken2, or joinChannelto rejoin the channel.

You need to set an appropriate expiration timestamp. For example, if the expiration time of joining a channel is earlier than that of publishing audio in the channel, when the privilege of joining a channel expires, the user is kicked out of the Video SDK channel. Even if the privilege of publishing audio is still valid, the privilege does not mean anything for the user.

ParameterDescription
tokenExpireNumber of seconds passed from the generation of AccessToken2 to the expiration of AccessToken2. Set this parameter as the current timestamp plus the valid period of AccessToken2. For example, if you set tokenExpire as the current timestamp plus 600, the AccessToken2 expires in 10 minutes. An AccessToken2 is valid for 24 hours at most. If you set it to 0 or a period longer than 24 hours, the AccessToken2 is still valid for 24 hours.
joinChannelPrivilegeExpireNumber of seconds passed from the generation of AccessToken2 to the expiration of the privilege of joining a channel. Set this parameter as the current timestamp plus the valid period of the privilege of joining a channel. For example, if you set joinChannelPrivilegeExpire as the current timestamp plus 600, the privilege expires 10 minutes after generation.
pubAudioPrivilegeExpireNumber of seconds passed from the generation of AccessToken2 to the expiration of the privilege of publishing audio in a channel. Set this parameter as the current timestamp plus the valid period of publishing audio in a channel. For example, if you set pubAudioPrivilegeExpire as the current timestamp plus 600, the privilege expires 10 minutes after generation. If you do not want to enable this privilege, set this parameter to the current timestamp.
pubVideoPrivilegeExpireNumber of seconds passed from the generation of AccessToken2 to the expiration of the privilege of publishing video in a channel. Set this parameter as the current timestamp plus the valid period of publishing video in a channel. For example, if you set pubVideoPrivilegeExpire as the current timestamp plus 600, the privilege expires 10 minutes after generation. If you do not want to enable this privilege, set this parameter to the current timestamp.
pubDataStreamPrivilegeExpireNumber of seconds passed from the generation of AccessToken2 to the expiration of the privilege of publishing data stream in a channel. Set this parameter as the current timestamp plus the valid period of publishing video in a channel. For example, if you set pubDataStreamPrivilegeExpire as the current timestamp plus 600, the privilege expires 10 minutes after generation. If you do not want to enable this privilege, set this parameter to the current timestamp.

Enable co-host authentication

Refer to the following steps to enable this function in Agora Console:

  1. Log on to Agora Console. Under Projects, choose a project for which you want to enable co-host authentication, click the Edit icon, and enter the Edit Project page.
  2. In the Features area, click Enable authentication.
  3. Follow the on-screen instructions to know more about this function, check the box, and click Enable.

Co-host authentication takes effect in 5 minutes.

Once you have enabled co-host authentication, a user using your app must meet both of the following requirements to publish streams in a channel:

  • The role in setClientRole is set as "BROADCASTER".
  • The role in the code for generating tokens is set as ROLE_PUBLISHER.
vundefined