Skip to main content

You are viewing Agora Docs forBeta products and features. Switch to Docs

Secure authentication with tokens

Authentication is the act of validating the identity of each user before they access a system. Agora uses digital tokens to authenticate users and their privileges before they access Agora SD-RTN™ to join a channel. Each token is valid for a limited period and works for specific and wildcard channel names. For example, you use a Agora* token to join AgoraChannel or AgoraAwesome. However, you cannot use it to join the AppTest channel.

This page shows you how to quickly set up an authentication token server, retrieve a token from the server, and use it to connect securely to a channel. You use this server for development purposes. To see how to develop your own token generator and integrate it into your production IAM system, read Token generators.

Understand the tech

An authentication token is a dynamic key that is valid for a maximum of 24 hours. On request, a token server returns an authentication token that is valid to join a specific channel or wildcard channels.

When users attempt to connect to an Agora channel, your app retrieves a token from the token server in your security infrastructure. Your app then sends this token to Agora SD-RTN™ for authentication. Agora SD-RTN™ validates the token and reads the user and project information stored in the token. A token contains the following information:

  • The App ID of your Agora project

  • The App certificate of your Agora project

  • The name of an individual channel, or a wildcard string for multiple channels

  • The user ID of the user to be authenticated (optional)

  • The privilege of the user, either as a publisher or a subscriber

  • The Unix timestamp showing when the token will expire

The following figure shows the call flow you need to implement to create step-up-authentication with Agora :

token authentication flow

Prerequisites

To follow this procedure, you must have:

  • Implemented the SDK quickstart

  • Created a cloud platform account that is verified through your GitHub account. The following platforms are currently supported:

    To integrate a token generator directly into your security infrastructure, see Token generators.

  • Android Studio 4.1 or higher.
  • Android SDK API Level 24 or higher.
  • A mobile device that runs Android 4.1 or higher.
  • An Agora account and project.

  • A computer with Internet access.

    Ensure that no firewall is blocking your network communication.

Implement the authentication workflow

In the SDK quickstart sample project, the app uses an authentication token obtained manually from Agora Console to join a channel. In a production environment, your app retrieves this token from a token server. This section shows you how to:

  1. Create and run a token server
  1. Authenticate using the SDK

Create and run a token server

This section shows you how to deploy a token server on a cloud platform.

  1. Start deploying the token server to your cloud platform:

    Click your cloud platform below. The cloud platform retrieves the project code and necessary files from Github, then takes you to the Deployment page.

  2. Fill in the information needed by your cloud platform:

    1. Blueprint name: A unique name for your deployment.

    2. Branch name: The branch of the repo or fork you want to deploy, default is main.

    3. APP_CERTIFICATE: The App Certificate obtained from Agora Console.

    4. APP_ID: The App ID obtained from Agora Console.

    5. Github account: The GitHub account where the cloud platform should clone the token server repository.

    6. Repository name: The name of the cloned repository, the default is agora-token-service.

    7. Private repository: Select this option to hide this repository.

  3. Create your token server:

    Click Deploy. The platform configures and builds the token server.

  4. Test your server

    1. Click the URL.

      You are notified of a URL where your server is deployed. Click the link and open the token server in your browser. Don’t worry if you see 404 page not found in your browser. Follow the next steps and test your server.

    2. Send a request to the token server using a URL based on the Token server GET request structure:


      _1
      /rtc/:channelName/:role/:tokentype/:uid/?expiry=expireTime

      For example: https://agora-token-server-<your id>.onrender.com/rtc/MyChannel/1/uid/1/?expiry=300

      Your token server returns a JSON object containing an encrypted token:


      _1
      {"rtcToken":"ThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleTokenThisIsAnExampleToken"}

Authentication using UI Kit

  1. Specify the token server URL

    In the MainActivity class, declare the following variable to hold the token server URL.


    _3
    // The base URL to your token server.
    _3
    // For example, "https://agora-token-service-production-92ff.up.railway.app"
    _3
    private String serverUrl = "<Token Server URL>";

    Make sure you specify the token-server URL in exactly the same format as shown in the example.

  2. Set the token URL for AgoraVideoViewer

    To set the token URL, you create an AgoraSettings object, set its TokenURL property and pass this object to the constructor when initializing AgoraVideoViewer. To do this, replace the code in the try {…​} block of the initializeAndJoinChannel() method with the following:


    _4
    AgoraSettings settings = new AgoraSettings();
    _4
    settings.setTokenURL(serverUrl);
    _4
    agView = new AgoraVideoViewer(this, new AgoraConnectionData(appId, null),
    _4
    AgoraVideoViewer.Style.FLOATING, settings, null);

  3. Fetch a token from the server when you join a channel

    In the joinChannel() method, replace the agView.join call with the following:


    _1
    agView.join(channelName, true, Constants.CLIENT_ROLE_BROADCASTER, 0);

Authenticate using the SDK

To retrieve tokens from the token server and use them to authenticate your app with Agora SD-RTN™ using :

  1. Import classes and interfaces:


    _1
    import io.agora.rtc2.*

  2. Declare variables for your request to the token server:


    _2
    var serverUrl : String // The base URL to your token server
    _2
    private val tokenExpiryTime : Int // Time in seconds after which the token will expire.

  3. Retrieve a token from the server:

    Use a GET request to retrieve an authentication token for a specific channel from the token server.


    _42
    fun fetchToken(channelName: String, uid: Int, callback: TokenCallback) {
    _42
    val tokenRole = if (isBroadcaster) 1 else 2
    _42
    // Prepare the Url
    _42
    val urlLString = "$serverUrl/rtc/$channelName/$tokenRole/uid/$uid/?expiry=$tokenExpiryTime"
    _42
    _42
    val client = OkHttpClient()
    _42
    _42
    // Create a request
    _42
    val request: Request = Builder()
    _42
    .url(urlLString)
    _42
    .header("Content-Type", "application/json; charset=UTF-8")
    _42
    .get()
    _42
    .build()
    _42
    _42
    // Send the async http request
    _42
    val call = client.newCall(request)
    _42
    call.enqueue(object : Callback {
    _42
    // Receive the response in a callback
    _42
    @Throws(IOException::class)
    _42
    override fun onResponse(call: Call, response: Response) {
    _42
    if (response.isSuccessful) {
    _42
    try {
    _42
    // Extract rtcToken from the response
    _42
    val responseBody = response.body!!.string()
    _42
    val jsonObject = JSONObject(responseBody)
    _42
    val rtcToken = jsonObject.getString("rtcToken")
    _42
    // Return the token
    _42
    callback.onTokenReceived(rtcToken)
    _42
    } catch (e: JSONException) {
    _42
    e.printStackTrace()
    _42
    callback.onError("Invalid token response")
    _42
    }
    _42
    } else {
    _42
    callback.onError("Token request failed")
    _42
    }
    _42
    }
    _42
    _42
    override fun onFailure(call: Call, e: IOException) {
    _42
    callback.onError("IOException: $e")
    _42
    }
    _42
    })
    _42
    }

  4. Join a channel using a token from the token server:

    Use fetchToken to retrieve a token before joining a channel.


    _21
    fun joinChannelWithToken(channelName: String): Int {
    _21
    if (agoraEngine == null) setupAgoraEngine()
    _21
    return if (isValidURL(serverUrl)) { // A valid server url is available
    _21
    // Fetch a token from the server for channelName
    _21
    fetchToken(channelName, object : TokenCallback {
    _21
    override fun onTokenReceived(rtcToken: String?) {
    _21
    // Handle the received rtcToken
    _21
    joinChannel(channelName, rtcToken)
    _21
    }
    _21
    _21
    override fun onError(errorMessage: String) {
    _21
    // Handle the error
    _21
    sendMessage("Error: $errorMessage")
    _21
    }
    _21
    })
    _21
    0
    _21
    } else { // use the token from the config.json file
    _21
    val token = config!!.optString("rtcToken")
    _21
    joinChannel(channelName, token)
    _21
    }
    _21
    }

  5. Renew an expiring token:

    A token expires either after the tokenExpiryTime specified in the call to the token server or, if the time is not specified, after 24 hours. When the onTokenPrivilegeWillExpire event in the IRtcEngineEventHandler receives a callback, you retrieve a fresh token and call renewToken.


    _18
    // Listen for the event that the token is about to expire
    _18
    override fun onTokenPrivilegeWillExpire(token: String) {
    _18
    sendMessage("Token is about to expire")
    _18
    // Get a new token
    _18
    fetchToken(channelName, object : TokenCallback {
    _18
    override fun onTokenReceived(rtcToken: String?) {
    _18
    // Use the token to renew
    _18
    agoraEngine!!.renewToken(rtcToken)
    _18
    sendMessage("Token renewed")
    _18
    }
    _18
    _18
    override fun onError(errorMessage: String) {
    _18
    // Handle the error
    _18
    sendMessage("Error: $errorMessage")
    _18
    }
    _18
    })
    _18
    super.onTokenPrivilegeWillExpire(token)
    _18
    }

Test the implementation

To test the Secure authentication with tokens example:

  1. Generate a temporary token in Agora Console.

  2. Configure the web demo you use to connect to your app:

    In your browser, navigate to the Agora web demo and update App ID, Channel, and Token with the values for your temporary token, then click Join.

  1. Configure your project:

    In agora-manager/res/raw/config.json, update the following:

    • appId - with your app ID from Agora Console.
    • rtcToken - an empty string.
    • serverUrl - with the base URL for your token server. For example: https://agora-token-service-production-yay.up.railway.app.
    • tokenExpiryTime - with an integer denoting the number of seconds after which a token expires.
  2. Run the Android reference app:

    1. In Android Studio, connect a physical Android device to your development machine.

    2. Click Run to start the app.

      A moment later you see the project installed on your device. If this is the first time you run the project, you need to grant microphone and camera access to your app.

    3. From the main screen of the app, choose from the dropdown and then select Secure authentication with tokens.

  3. Join a Channel:

Your app magically connects to the same channel you used in web demo. You don’t need to hardcode a token in your app; each channel is secured with a specific token, and each token is refreshed automatically. That’s pretty cool!

Reference

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

Source code for a token server

The token server RESTful web service used in this page is written in Golang using the Gin framework. Want to use the code in your authentication service? Download the token server source code and binaries for various platforms from Github.

To see how to create a token generator inside your IAM system, see Integrate a token generator.

Token server GET request structure

A token server GET request has the following structure:


_1
/rtc/:channelName/:role/:tokentype/:uid/?expiry=expireTime

  • :channelName is the name of the Agora Channel you wish to join

    A channel name may contain numbers with both upper and lower case letters. The name length must be less than 64 characters.

  • :role is the user role

    Use publisher for publisher, subscriber for subscriber.

  • :tokentype is the type of token

    Agora SD-RTN™ supports both integer user IDs and string user accounts for token generation. To ensure smooth communication, all the users in a channel must use the same type of ID, that is, either the integer uid, or a string userAccount. Best practice is to use the uid.

  • :uid is the user ID

    User Id can be any 32-bit unsigned integer. It can be set to 0, if you do not need to authenticate the user based on the user ID.

  • expireTime (optional) is the number of seconds after which the token will expire

    By default, a token expires after 24 hours unless a shorter life span is explicitly specified in the token request.

Wildcard tokens

When a user joins an audio or video call, or a live broadcast, Agora SD-RTN™ uses a token to authenticate the user. If users need to join multiple channels, or frequently switch between channels, they need to acquire a token from the authentication server each time they join a new channel. In order to avoid frequent retrieval of tokens when switching channels, Agora SD-RTN™ enables use of tokens based on channel wildcards. By using wildcard tokens, users can reuse the same token to join different channels. This approach not only speeds up the process of authentication, but also reduces the workload on your token server.

Prerequisites

Before generating wildcard tokens, make sure you have deployed the AccessToken2 server.

Generate wildcard token

The generation code of AccessToken2 provides two BuildTokenWithUid methods. You can use BuildTokenWithUid[1/2] or BuildTokenWithUid[2/2] according to the BuildTokenWithUid API reference, and fill in the corresponding parameter information.

When generating a wildcard token, you need to note that the following parameters are different compared to those used to generate a general token:

ParameterGeneral TokenWildcard Token
uidUser ID of the user to be authenticated. If there is no need to authenticate the user ID, that is, if clients can join the channel with any uid, set uid to 0.The user ID of the user to be authenticated. Supports int and string types for the user ID, but it must not be set to 0.
channelNameChannel name, the length should be less than 64 bytes.Channel name is set as wildcard * indicating any channel name.

After acquiring a wildcard token, users can join any channel with the same user ID and token.

Precautions

  1. Currently, Agora SD-RTN™ supports only the following combinations of channel name and user ID when joining a channel:

    • uid set to 0, channelName is specified
    • uid is specified, channelName set to *

    Agora SD-RTN™ does not support setting the uid to 0 and channelName to * at the same time.

  2. To prevent unauthorized users from disrupting the order of a channel using leaked wildcard tokens, Agora recommends that users who use wildcard tokens set their permissions as a viewer and the role as kRoleSubscriber.

    If a user using a wildcard token needs to connect to the microphone, best practice is to take the following steps to update the token:

    1. Call setClientRole to set the user's role as a host or broadcaster.

    2. When generating a fresh token, specify the channel name and user ID in the BuildTokenWithUid method. Set the user permission role to kRolePublisher, thereby generating a token with the permission to send streams.

    3. Call renewToken to update the token.

  3. If the wildcard token expires, you regenerate a new wildcard token on the server and then call renewToken to pass in the new token.

vundefined