Token generators
To secure user access, integrate token authentication into your 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 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.
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:
-
Create a new
token-server
folder. Create aserver.go
file inside the folder and paste the following Golang sample code into the file. Replace the values forappID
andappCertificate
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\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 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) } }
-
Open the terminal, go to the
token-server
folder path, and run the following command line to create ago.mod
file for your token generator. This file defines the import path and dependencies: -
Run the following command to install dependencies.
-
Run the following command to start the token generator:
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
.
-
Replace the import
rtctokenbuilder
declaration with the following code and delete the declaration that importstime
: -
Remove the statement that generates the timestamp and add
tokenExpireTimeInSeconds
andprivilegeExpireTimeInSeconds
related code: -
Update
tokenbuilder
method code: -
Remove unsupported roles