Skip to main content
Linux C++
Linux Java

Token generators

In order to build a seamless authentication process for your users, you integrate token generation into your identity management system. This guide helps you integrate Agora token generation libraries into your authentication system and shows you how to upgrade to AccessToken2.

Understand the tech

A token contains the following information:

  • The App ID generated when you create a project in the Agora Console
  • 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 SD-RTN™ with the request to join a channel. Agora SD-RTN™ 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 SD-RTN™:

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.

Implement the authentication process

Refer to the following section to quickly deploy a token server. If you already have a token server that uses AccessToken skip to the Upgrade to AccessToken2.

Deploy a token server

This guide uses the Golang language as an example. Before starting, ensure that you have Golang version 1.14 or above.

Note

The following code deploys a token server based on AccessToken. To deploy an AccessToken2 server, refer to Secure authentication with tokens.

Refer to the following steps to build and run a token generator locally to generate tokens:

  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/RtcTokenBuilder"     "fmt"     "log"     "net/http"     "time"     "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>"     // For demonstration purposes, set the expiration timestamp to 40 seconds. When the token is about to expire, you can see the process of the client automatically updating the Token.     expireTimeInSeconds := uint32(40) // Token expiration time in seconds     // Get the current timestamp     currentTimestamp := uint32(time.Now().UTC().Unix())     // Token expiration Unix timestamp     expireTimestamp := currentTimestamp + expireTimeInSeconds     result, err := rtctokenbuilder.BuildTokenWithUID(appID, appCertificate, channelName, int_uid, role, expireTimestamp)     if err != nil {         fmt.Println(err)     } else {         fmt.Printf("Token with uid: %s\n", result)         fmt.Printf("uid is %d\n", int_uid )         fmt.Printf("ChannelName is %s\n", channelName)         fmt.Printf("Role is %d\n", 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 0:                     // Deprecated. RoleAttendee and RolePublisher have the same permissions                     role = rtctokenbuilder.RoleAttendee                 case 1:                     role = rtctokenbuilder.RolePublisher                 case 2:                     role = rtctokenbuilder.RoleSubscriber                 case 101:                     // Deprecated. RoleAdmin and RolePublisher have the same permissions                     role = rtctokenbuilder.RoleAdmin                 }     }     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(){     // Handle routing     // 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)     } }
  2. 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:


    _1
    $ go mod init sampleServer

  3. Run the following command to install dependencies.


    _1
    $ go get

  4. Run the following command to start the token generator:


    _1
    $ 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. To retrieve and use a token from your app, refer to Secure authentication with tokens.

Upgrade to AccessToken2

Take the following steps to upgrade your token server to AccessToken2.

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


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

  2. Remove the statement that generates the timestamp and add tokenExpireTimeInSeconds and privilegeExpireTimeInSeconds related code:


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

  3. Update tokenbuilder method code:


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

  4. Remove unsupported roles


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

Reference

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

vundefined