Tokens & Authentication

Last Edit: Jun 06 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", time.Time{})
                    

// at the moment we don't have a Swift client for server side usage
// You can use our user token generator here during development: https://getstream.io/chat/docs/token_generator/?language=swift
                    

// 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 = Number(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
// You can use our user token generator here during development: https://getstream.io/chat/docs/token_generator/?language=swift
                    

// 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'),
);
                    

String userId = "user-id";
String token = ChatUtils.devToken(userId);
User user = new User(userId);

client.setUser(user, token, new InitConnectionListener() {
    @Override
    public void onSuccess(@NotNull ConnectionData data) {
        User user = data.getUser();
        String connectionId = data.getConnectionId();
    }

    @Override
    public void onError(@NotNull ChatError error) {
        error.printStackTrace();
    }
});// Create a user when they login
let userExtraData = UserExtraData(name: "Bender", avatarURL: URL(string: "https://bit.ly/321RmWb")!)
let user = User(id: "bender", extraData: userExtraData)
                    

// Create a user when they login
let userExtraData = UserExtraData(name: "Bender", avatarURL: URL(string: "https://bit.ly/321RmWb")!)
let user = User(id: "bender", extraData: userExtraData)
// 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 -> {
    String newToken = "fetch a new token from your backend";
    listener.onSuccess(newToken);
}, null);
                    

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

// Create a user when they login
let userExtraData = UserExtraData(name: "Bender", avatarURL: URL(string: "https://bit.ly/321RmWb")!)
let user = User(id: "bender", extraData: userExtraData)

let tokenProvider: TokenProvider = { supplyToken in
    // Make a request here to your backend to generate a valid token for the user.
    YourTokenService.shared.getToken(for: user) { token
        supplyToken(token)
    }
}

Client.shared.set(user: user, tokenProvider: tokenProvider) { result in 
  // handle result
}
                    

const client = new StreamChat('api_key');
client.setUser(
    { id: 'vishal' },
    async () => {
        const token = await fetchTokenFromSomeApi(); // you need to implement this api

        return token;
    }
);
                    

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' });
                    

client.getGuestToken(userId, userName).enqueue(
        new Function1<Result<GuestUser>, Unit>() {
            @Override
            public Unit invoke(Result<GuestUser> result) {
                GuestUser data = result.data();
                User user = data.component1();
                String token = data.component2();

                client.setUser(user, token, null);

                return Unit.INSTANCE;
            }
        }
);
                    

let user = User(id: "bender")
// Setup the current user with guest token.
Client.shared.setGuestUser(user: user)
                    

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();
                    

client.setAnonymousUser(null);
                    

Client.shared.setAnonymousUser()
                    

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();
client.setUser(user, token, null);
                    

Client.shared.disconnect()
// Then you can call set(user:token:) as usual
                    

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 }}"),
);