Tokens & Authentication

Last Edit: Mar 03 2020

Tokens

Tokens are used to authenticate the user. Typically, you send this token from your backend to the client-side when a user registers or logs in.

You can generate tokens server side with the following syntax:


const client = new StreamChat('', '{{ chat_api_secret }}');
const token = client.createToken('john');
                    

# pip install stream-chat

import stream_chat

chat_client = stream_chat.StreamChat(api_key="STREAM_KEY", api_secret="STREAM_SECRET")
token = chat_client.create_token('john')
                    

# gem install stream-chat-ruby

require 'stream-chat'

client = StreamChat::Client.new(api_key='STREAM_KEY', api_secret='STREAM_SECRET')
client.create_token('john')
                    

// composer require get-stream/stream-chat

$client = new GetStream\StreamChat\Client("STREAM_API_KEY", "STREAM_API_SECRET");
$token = $client->createToken("john");
                    

// at the moment we don't have a Java client for server side usage
                    

// go get github.com/GetStream/stream-chat-go

client, _ := stream.NewClient(APIKey, []byte(APISecret))
token := client.CreateToken("john", null)
                    

// at the moment we don't have a Swift client for server side usage
                    

// nuget install stream-chat-net

using StreamChat;

var client = new Client("API KEY", "API SECRET");
var token = client.CreateUserToken("john");
                    

// user tokens must be generated server-side, check other languages for examples
                    

// user tokens must be generated server-side, check other languages for examples
                    

By default, user tokens are valid indefinitely. You can set an expiration to tokens by passing it as the second parameter. The expiration should contain the number of seconds since the epoch.


// creates a token that expires in 1 hour using moment.js
const timestamp = moment().add('1h').format('X');
const token1 = client.createToken('john', timestamp);

// the same can be done with plain javascript
const token2 = client.createToken('john', Math.floor(Date.now() / 1000) + (60 * 60));
                    

# creates a token valid for 1 hour
token = chat_client.create_token(
    'john',
    exp=datetime.datetime.utcnow() + datetime.timedelta(hours=1)
)
                    

# creates a token valid for 1 hour
client.create_token('john', exp=Time.now.to_i + 3600)
                    

// creates a token valid for 1 hour
$expiration = (new DateTime())->getTimestamp() + 3600;
$token = $client->createToken("john", $expiration);
                    

// at the moment we don't have a Java SDK for server side integrations
                    

// creates a token valid for 1 hour
token := client.CreateToken("john", time.Now().UTC().Add(time.Hour))
                    

// at the moment we don't have a Swift client for server side usage
                    

// creates a token valid for 1 hour
var token = client.CreateUserToken("john", DateTime.Now.AddHours(1));
                    

// user tokens must be generated server-side, check other languages for examples
                    

// user tokens must be generated server-side, check other languages for examples
                    

Development Tokens

For development applications, it is possible to disable token authentication and use client-side generated tokens. Disabling auth checks is not suitable for a production application and should only be done for proofs-of-concept and applications in the early development stage. To enable development tokens, you need to change your application configuration.


await client.setUser(
    {
        id: 'john',
        name: 'John Doe',
        image: 'https://getstream.io/random_svg/?name=John',
    },
   client.devToken('john'),
);
                    

User user = new User(USER_ID, extraData);
client.setUser(user, client.devToken(USER_ID), new ClientConnectionCallback() {
    @Override
    public void onSuccess(User user) {
        Log.i(TAG, String.format("Connection established for user %s", user.getName()));
    }

    @Override
    public void onError(String errMsg, int errCode) {
        Log.e(TAG, String.format("Failed to establish websocket connection: %s", errMsg));
    }
});
                    

// Create a user, when he/she was logged in.
let user = User(id: "bender", name: "Bender", avatarURL: URL(string: "https://bit.ly/321RmWb")!)

// Setup the current user with a development token.
Client.shared.set(user: user, token: .development)
                    

val userId = "user-id"
val user = User(userId)
val token = ChatUtils.devToken(userId)

client.setUser(user, token, object : InitConnectionListener() {
    override fun onSuccess(data: ConnectionData) {
        val user = data.user
        val connectionId = data.connectionId
    }

    override fun onError(error: ChatError) {
        error.printStackTrace()
    }
})
                    

final user = User(id: "john", extraData: {
  "name": "John Doe",
  "image": "<a href="https://getstream.io/random_svg/?name=John" target="_self">https://i.imgur.com/fR9Jz14.png</a>",
});

await client.setUser(
  user,
  client.devToken("john"),
);
                    
The above code used the setUser call. The setUser call is the most convenient option when your app has authenticated users. Alternatively, you can use setGuestUser if you want to allow users to chat with a guest account or the setAnonymousUser if you want to allow anonymous users to watch the chat.

Token Expiration

If you're using tokens with an expiration date you'll want to update tokens as soon as a token exception occurs. Our React, RN, iOS, Android and Flutter libraries have built-in support for this:


client.setUser(user, listener -> {
    // make an API call to your backend to fetch a new token for this user
    listener.onSuccess(myNewToken);
);
                    

client.setUser(user, object : TokenProvider {
    override fun getToken(listener: TokenProvider.TokenProviderListener) {
        val myNewToken = "fetch a new token from your backend"
        listener.onSuccess(myNewToken)
    }
})
                    

Guest Users

Guest sessions can be created client-side and do not require any server-side authentication.

Guest users have a limited set of permissions. You can read more about how to configure permissions here. You can create a guest user session by using setGuestUser instead of setUser.


await client.setGuestUser({ id: 'tommaso' });
                    

// Not supported yet
                    

// Create a user, when he/she was logged in.
let user = User(id: "bender", name: "Bender", avatarURL: URL(string: "https://bit.ly/321RmWb")!)

// Setup the current user and guest token.
Client.shared.set(user: user, token: .guest)
                    

val userId = "user-id"
val userName = "bender"
client.getGuestToken(userId, userName).enqueue {
    val token = it.data().token
    val user = it.data().user
        
    client.setUser(user, token)
}
                    

await client.setGuestUser(user);
                    
The user object schema is the same as the one described in the Setting the user portion of the docs.

Anonymous Users

If a user is not logged in, you can call the setAnonymousUser method. While you’re anonymous, you can’t do much, but for the livestream channel type, you’re still allowed to read the chat conversation.


await client.setAnonymousUser();
                    

// not supported yet
                    

// not supported yet
                    

client.setAnonymousUser()
                    

await client.setAnonymousUser();
                    

Logging Out & Switching Users

To disconnect a user (say that you’re for instance logging out and logging in as someone new) you can call the disconnect method and repeat the setUser call as someone else:


client.disconnect();
client.setUser(
    {
        id: 'jack',
        name: 'Jack Doe',
    },
    'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiamxhaGV5In0.OkDbpbujWJ-XIVHaf00Dnqt3v8Yp_nQ6CGzm-Z4QUVc',
);
                    

client.disconnect();
// set the new user
User user = new User(userId);
client.setUser(user, token);
// if you're using our viewmodels
viewModel.reload();
                    

Client.shared.disconnect()
                    

client.disconnect()
client.setUser(User("bender"), "{{ chat_user_token }}")
                    

await client.disconnect();

final otherUser = User(id: "jack", extraData: {
  "name": "Jack Doe",
});

await client.setUser(
  otherUser,
  client.devToken("{{ chat_user_token }}"),
);