AccessToken upgrade guide

Updated

Upgrade to AccessToken2.

To secure user access, integrate token authentication into your Broadcast Streaming identity management system. This guide shows you how to use Agora token generation libraries to create access tokens.

Understand the tech

A token contains the following information:

  • The App ID for your project
  • The App certificate for your project
  • Channel name
  • User ID
  • User permissions, such as whether they can send or receive streams
  • Token expiration Unix timestamp

When a user attempts to connect to an Agora channel, your app requests a token from your authentication system. Your authentication system uses Agora libraries to generate a token specific to the user and the channel, then sends it to your app. The app then sends this token to Agora SDRTN® with the request to join a channel. Agora SDRTN® validates the token and adds the user to the channel. The following diagram shows the authentication call flow between your app, your authentication system and Agora SDRTN®:

Token authentication flow

Prerequisites

Before starting, ensure that you have:

  • Implemented the SDK quickstart in your project.

  • The following information from Agora Console:

    • App ID: A unique string generated by Agora that identifies your project.
    • App Certificate: A string generated by Agora Console to enable token authentication. To obtain the App Certificate for your project, enable primary certificate.

Deploy a token server

This section shows you how to quickly deploy a token server based on AccessToken2. If you already have a token server that uses AccessToken skip to Upgrade to AccessToken2..

The following example uses Golang. Before starting, ensure that you have Golang version 1.14 or above.

Follow these steps to build and run a token generator locally:

  1. Create a new token-server folder. Create a server.go file inside the folder and paste the following Golang sample code into the file. Replace the values for appID and appCertificate with your App ID and App certificate.

Sample code for a token server

  package main

    import (
      rtctokenbuilder "github.com/AgoraIO/Tools/DynamicKey/AgoraDynamicKey/go/src/rtctokenbuilder2"
      "fmt"
      "log"
      "net/http"
      "encoding/json"
      "errors"
      "strconv"
    )

    type rtc_int_token_struct struct{
      Uid_rtc_int uint32 `json:"uid"`
      Channel_name string `json:"ChannelName"`
      Role uint32 `json:"role"`
    }

    var rtc_token string
    var int_uid uint32
    var channel_name string

    var role_num uint32
    var role rtctokenbuilder.Role

    // Use RtcTokenBuilder to generate RTC Token
    func generateRtcToken(int_uid uint32, channelName string, role rtctokenbuilder.Role){
      appID := "<Your App ID>"
      appCertificate := "<Your App Certificate>"
      // Ensure that the expiration time of the token is later than the permission expiration time. Permission expiration time, unit is seconds
      tokenExpireTimeInSeconds := uint32(40)
      // The token-privilege-will-expire callback is triggered 30 seconds before the permission expires.
      // For demonstration purposes, set the expiration time to 40 seconds. You can see the process of the client automatically updating the Token
      privilegeExpireTimeInSeconds := uint32(40)

      result, err := rtctokenbuilder.BuildTokenWithUid(appID, appCertificate, channelName, int_uid, role, tokenExpireTimeInSeconds, privilegeExpireTimeInSeconds)
      if err != nil {
        fmt.Println(err)
      } else {
        fmt.Printf("Token with uid: %s
  ", result)
        fmt.Printf("uid is %d
  ", int_uid )
        fmt.Printf("ChannelName is %s
  ", channelName)
        fmt.Printf("Role is %d
  ", role)
      }
      rtc_token = result
    }

    func rtcTokenHandler(w http.ResponseWriter, r *http.Request){
      w.Header().Set("Content-Type", "application/json; charset=UTF-8")
      w.Header().Set("Access-Control-Allow-Origin", "*")
      w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS");
      w.Header().Set("Access-Control-Allow-Headers", "*");

      if r.Method == "OPTIONS" {
        w.WriteHeader(http.StatusOK)
        return
      }

      if r.Method != "POST" && r.Method != "OPTIONS" {
        http.Error(w, "Unsupported method. Please check.", http.StatusNotFound)
        return
      }

      var t_int rtc_int_token_struct
      var unmarshalErr *json.UnmarshalTypeError
      int_decoder := json.NewDecoder(r.Body)
      int_err := int_decoder.Decode(&t_int)
      if (int_err == nil) {

            int_uid = t_int.Uid_rtc_int
            channel_name = t_int.Channel_name
            role_num = t_int.Role
            switch role_num {
              case 1:
                role = rtctokenbuilder.RolePublisher
              case 2:
                role = rtctokenbuilder.RoleSubscriber
            }
      }
      if (int_err != nil) {

        if errors.As(int_err, &unmarshalErr){
            errorResponse(w, "Bad request. Wrong type provided for field " + unmarshalErr.Value + unmarshalErr.Field + unmarshalErr.Struct, http.StatusBadRequest)
            } else {
            errorResponse(w, "Bad request.", http.StatusBadRequest)
          }
        return
      }

      generateRtcToken(int_uid, channel_name, role)
      errorResponse(w, rtc_token, http.StatusOK)
      log.Println(w, r)
    }

    func errorResponse(w http.ResponseWriter, message string, httpStatusCode int){
      w.Header().Set("Content-Type", "application/json")
      w.Header().Set("Access-Control-Allow-Origin", "*")
      w.WriteHeader(httpStatusCode)
      resp := make(map[string]string)
      resp["token"] = message
      resp["code"] = strconv.Itoa(httpStatusCode)
      jsonResp, _ := json.Marshal(resp)
      w.Write(jsonResp)
    }

    func main(){
      // Use int type uid to generate RTC Token
      http.HandleFunc("/fetch_rtc_token", rtcTokenHandler)
      fmt.Printf("Starting server at port 8082
  ")

      if err := http.ListenAndServe(":8082", nil); err != nil {
        log.Fatal(err)
      }
    }
  1. Open the terminal, go to the token-server folder path, and run the following command line to create a go.mod file for your token generator. This file defines the import path and dependencies:

    go mod init sampleServer
  2. Run the following command to install dependencies.

    go get github.com/AgoraIO/Tools/DynamicKey/AgoraDynamicKey/go/src/rtctokenbuilder2
  3. Run the following command to start the token generator:

    go run server.go

After the token generator is deployed successfully, your terminal returns the token generated based on the App ID and App certificate you filled in.

Reference

This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.

Upgrade to AccessToken2

If your current token server implementation uses AccessToken, follow these steps to upgrade your server to AccessToken2.

  1. Replace the import rtctokenbuilder declaration with the following code and delete the declaration that imports time:

    import (
      // Replace
      // rtctokenbuilder "github.com/AgoraIO/Tools/DynamicKey/AgoraDynamicKey/go/src/RtcTokenBuilder"
      rtctokenbuilder "github.com/AgoraIO/Tools/DynamicKey/AgoraDynamicKey/go/src/rtctokenbuilder2"
      "fmt"
      "log"
      "net/http"
      // delete
      // "time"
      "encoding/json"
      "errors"
      "strconv"
    )
  2. Remove the statement that generates the timestamp and add tokenExpireTimeInSeconds and privilegeExpireTimeInSeconds related code:

    // expireTimeInSeconds := uint32(40)
    // Get the current timestamp
    // currentTimestamp := uint32(time.Now().UTC().Unix())
    // Timestamp when the token expires.
    // expireTimestamp := currentTimestamp + expireTimeInSeconds
    tokenExpireTimeInSeconds := uint32(40)
    privilegeExpireTimeInSeconds := uint32(40)
  3. Update tokenbuilder method code:

    // Code before updating
    // result, err := rtctokenbuilder.BuildTokenWithUID(appID, appCertificate, channelName, int_uid, role, expireTimestamp)
    // Updated code
    // Change BuildTokenWithUID to BuildTokenWithUid
    // Change expireTimestamp to tokenExpireTimeInSeconds and privilegeExpireTimeInSeconds
    result, err := rtctokenbuilder.BuildTokenWithUid(appID, appCertificate, channelName, int_uid, role, tokenExpireTimeInSeconds, privilegeExpireTimeInSeconds)
  4. Remove unsupported roles

    switch role_num {
    // delete
    // case 0:
      // Deprecated. RoleAttendee and RolePublisher have the same permissions
      // role = rtctokenbuilder.RoleAttendee
      case 1:
        role = rtctokenbuilder.RolePublisher
      case 2:
        role = rtctokenbuilder.RoleSubscriber
    // delete
    // case 101:
      // Deprecated. RoleAdmin and RolePublisher have the same permissions
      // role = rtctokenbuilder.RoleAdmin
    }

See also