# Tokens & Authentication Stream uses JWT (JSON Web Tokens) to **authenticate** feeds users, enabling them to login. Knowing whether a user is authorized to perform certain actions is managed separately via a role based permissions system. The exception is Anonymous and Guest users who require no authentication to login. ## Token Providers A concept we will refer to throughout the docs is a Token Provider. At a high level, the Token Provider is an endpoint on your server that can perform the following sequence of tasks: 1. Receive information about a user from the front end. 2. Validate that user information against your system. 3. Provide a User-ID corresponding to that user to the server client's token creation method. 4. Return that token to the front end. User Tokens can only be safely generated from a server. This means you will need to implement a Token Provider prior to deploying your application to production. To conduct development before implementing a Token Provider, you will need to disable token authentication. ## Generating Tokens You can generate tokens server-side. You need to pass the user id the token belongs to. Optionally you can specify when the token should expire, by default it's set to 1 hour. ```js const userId = "john"; // validity is optional, in this case we set it to 1 day const validity = 24 * 60 * 60; client.generateUserToken({ user_id: userId, validity_in_seconds: validity }); ``` ```java import io.getstream.services.framework.StreamSDKClient; import io.getstream.services.framework.TokenBuilder; // Initialize client StreamSDKClient client = new StreamSDKClient("api_key", "api_secret"); // Generate user token String userId = "john"; // validity is optional, in this case we set it to 1 day Integer validity = 24 * 60 * 60; TokenBuilder tokenBuilder = new TokenBuilder("api_secret"); String token = tokenBuilder.createToken(userId, validity); ``` ```csharp using GetStream; // Initialize client var builder = new ClientBuilder() .ApiKey("api_key") .ApiSecret("api_secret"); var client = builder.Build(); // Generate user token - C# SDK doesn't have a direct method // You need to implement JWT generation manually or use the server token // For now, refer to the Node.js example for the API structure ``` ```go import ( "log" "time" "github.com/GetStream/getstream-go/v3" ) // Initialize client client, err := getstream.NewClient("api_key", "api_secret") if err != nil { log.Fatal(err) } // Generate user token userId := "john" // validity is optional, in this case we set it to 1 day expiration := time.Hour * 24 token, err := client.CreateToken(userId, getstream.WithExpiration(expiration)) if err != nil { log.Fatal("Error creating token:", err) } log.Printf("Token: %+v\n", token) ``` ```php use GetStream\ClientBuilder; // Initialize client $client = (new ClientBuilder()) ->apiKey('api_key') ->apiSecret('api_secret') ->build(); // Generate user token $userId = 'john'; // validity is optional, in this case we set it to 1 day $validity = 24 * 60 * 60; $token = $client->createUserToken($userId, [], $validity); ``` ```python from getstream import Stream # Initialize client client = Stream('api_key', 'api_secret') # Generate user token user_id = 'john' # validity is optional, in this case we set it to 1 day validity = 24 * 60 * 60 token = client.create_token(user_id, expiration=validity) ``` ```ruby require 'getstream_ruby' require 'jwt' # Initialize client client = GetStreamRuby.manual( api_key: 'api_key', api_secret: 'api_secret' ) # Generate user token user_id = 'john' # validity is optional, in this case we set it to 1 day validity = 24 * 60 * 60 exp = Time.now.to_i + validity token = JWT.encode( { user_id: user_id, iat: Time.now.to_i, exp: exp }, 'api_secret', 'HS256' ) ``` ## Manual Token Expiration Token Revocation is a way to manually expire tokens for a single user or for many users by setting a `revoke_tokens_issued_before` time, and any tokens issued before this will be considered expired and will fail to authenticate.  This can be reversed by setting the field to null. ### Token Revocation by User You can revoke all tokens that belong to certain user or list of users ```js await client.updateUsersPartial({ users: [ { id: "user1", set: { revoke_tokens_issued_before: new Date(), }, }, { id: "user2", set: { revoke_tokens_issued_before: new Date(), }, }, ], }); ``` ```java import io.getstream.client.Client; import java.util.*; Client client = Client.builder("api_key", "api_secret").build(); Map user1Updates = new HashMap<>(); user1Updates.put("revoke_tokens_issued_before", new Date()); Map user2Updates = new HashMap<>(); user2Updates.put("revoke_tokens_issued_before", new Date()); List> users = Arrays.asList( Map.of("id", "user1", "set", user1Updates), Map.of("id", "user2", "set", user2Updates) ); client.updateUsersPartial(Map.of("users", users)); ``` ```csharp using GetStream; using GetStream.Models; var builder = new ClientBuilder() .ApiKey("api_key") .ApiSecret("api_secret"); var client = builder.Build(); await client.UpdateUsersPartialAsync(new UpdateUsersPartialRequest { Users = new[] { new UpdateUserPartialRequest { Id = "user1", Set = new Dictionary { ["revoke_tokens_issued_before"] = DateTime.UtcNow } }, new UpdateUserPartialRequest { Id = "user2", Set = new Dictionary { ["revoke_tokens_issued_before"] = DateTime.UtcNow } } } }); ``` ```go request := &getstream.UpdateUsersPartialRequest{ Users: []getstream.UpdateUserPartialRequest{ { ID: "user1", Set: map[string]any{ "revoke_tokens_issued_before": time.Now(), }, }, { ID: "user2", Set: map[string]any{ "revoke_tokens_issued_before": time.Now(), }, }, }, } _, err = client.UpdateUsersPartial(context.Background(), request) if err != nil { log.Fatal("Error updating users:", err) } log.Printf("Users updated successfully") ``` ```php use GetStream\ClientBuilder; use GetStream\GeneratedModels; $client = (new ClientBuilder()) ->apiKey('api_key') ->apiSecret('api_secret') ->build(); $request = new GeneratedModels\UpdateUsersPartialRequest( users: [ new GeneratedModels\UpdateUserPartialRequest( id: 'user1', set: (object)['revoke_tokens_issued_before' => (new DateTime())->format(DateTime::ATOM)] ), new GeneratedModels\UpdateUserPartialRequest( id: 'user2', set: (object)['revoke_tokens_issued_before' => (new DateTime())->format(DateTime::ATOM)] ) ] ); $client->updateUsersPartial($request); ``` ```python from getstream import Stream from getstream.models import UpdateUserPartialRequest from datetime import datetime client = Stream('api_key', 'api_secret') users = [ UpdateUserPartialRequest( id='user1', set={'revoke_tokens_issued_before': datetime.utcnow()} ), UpdateUserPartialRequest( id='user2', set={'revoke_tokens_issued_before': datetime.utcnow()} ) ] client.update_users_partial(users) ``` ```ruby require 'getstream_ruby' client = GetStreamRuby.manual( api_key: 'api_key', api_secret: 'api_secret' ) partial_request = GetStream::Generated::Models::UpdateUsersPartialRequest.new( users: [ GetStream::Generated::Models::UpdateUserPartialRequest.new( id: 'user1', set: { revoke_tokens_issued_before: Time.now.iso8601 } ), GetStream::Generated::Models::UpdateUserPartialRequest.new( id: 'user2', set: { revoke_tokens_issued_before: Time.now.iso8601 } ) ] ) client.common.update_users_partial(partial_request) ``` Note: Your tokens must include the `iat` (issued at time) claim, which will be compared to the time in the `revoke_tokens_issued_before` field to determine whether the token is valid or expired. If you use the Node SDK to generate tokens, `iat` will be set for you. Tokens which have no `iat` will be considered invalid. ### Undoing the revoke To undo user-level token revocation, you can simply set revocation date to `null`: ```js await client.updateUsersPartial({ users: [ { id: "user1", set: { revoke_tokens_issued_before: null, }, }, { id: "user2", set: { revoke_tokens_issued_before: null, }, }, ], }); ``` ```java import io.getstream.services.framework.StreamSDKClient; import io.getstream.services.CommonImpl; import io.getstream.models.UpdateAppRequest; import java.util.Date; StreamSDKClient client = new StreamSDKClient("api_key", "api_secret"); CommonImpl common = new CommonImpl(client.getHttpClient()); // Revoke tokens for all users UpdateAppRequest request = UpdateAppRequest.builder() .revokeTokensIssuedBefore(new Date()) .build(); common.updateApp(request).execute(); // Please refer to the Node.js examples above for the API structure ``` ```csharp using GetStream; var builder = new ClientBuilder() .ApiKey("api_key") .ApiSecret("api_secret"); var client = builder.Build(); // Revoke tokens for all users var request = new UpdateAppRequest { RevokeTokensIssuedBefore = DateTime.UtcNow }; await client.UpdateAppAsync(request); // Please refer to the Node.js examples above for the API structure ``` ```go request := &getstream.UpdateUsersPartialRequest{ Users: []getstream.UpdateUserPartialRequest{ { ID: "user1", Set: map[string]any{ "revoke_tokens_issued_before": nil, }, }, { ID: "user2", Set: map[string]any{ "revoke_tokens_issued_before": nil, }, }, }, } _, err = client.UpdateUsersPartial(context.Background(), request) if err != nil { log.Fatal("Error updating users:", err) } log.Printf("Users updated successfully") ``` ```php use GetStream\ClientBuilder; use GetStream\GeneratedModels; $client = (new ClientBuilder()) ->apiKey('api_key') ->apiSecret('api_secret') ->build(); $request = new GeneratedModels\UpdateUsersPartialRequest( users: [ new GeneratedModels\UpdateUserPartialRequest( id: 'user1', set: (object)['revoke_tokens_issued_before' => null] ), new GeneratedModels\UpdateUserPartialRequest( id: 'user2', set: (object)['revoke_tokens_issued_before' => null] ) ] ); $client->updateUsersPartial($request); ``` ```ruby require 'getstream_ruby' client = GetStreamRuby.manual( api_key: 'api_key', api_secret: 'api_secret' ) partial_request = GetStream::Generated::Models::UpdateUsersPartialRequest.new( users: [ GetStream::Generated::Models::UpdateUserPartialRequest.new( id: 'user1', set: { revoke_tokens_issued_before: nil } ), GetStream::Generated::Models::UpdateUserPartialRequest.new( id: 'user2', set: { revoke_tokens_issued_before: nil } ) ] ) client.common.update_users_partial(partial_request) ``` ### Token Revocation by Application It is possible to revoke tokens for all users of an application.  This should be used with caution as it will expire every user’s token, regardless of whether the token has an `iat`  claim ```js await client.updateApp({ revoke_tokens_issued_before: new Date() - 60 * 1000, }); ``` ```java import io.getstream.services.framework.StreamSDKClient; import io.getstream.services.CommonImpl; import io.getstream.models.UpdateAppRequest; import java.util.Date; StreamSDKClient client = new StreamSDKClient("api_key", "api_secret"); CommonImpl common = new CommonImpl(client.getHttpClient()); // Revoke tokens for all users UpdateAppRequest request = UpdateAppRequest.builder() .revokeTokensIssuedBefore(new Date()) .build(); common.updateApp(request).execute(); // Please refer to the Node.js examples above for the API structure ``` ```csharp using GetStream; var builder = new ClientBuilder() .ApiKey("api_key") .ApiSecret("api_secret"); var client = builder.Build(); // Revoke tokens for all users var request = new UpdateAppRequest { RevokeTokensIssuedBefore = DateTime.UtcNow }; await client.UpdateAppAsync(request); // Please refer to the Node.js examples above for the API structure ``` ```go sixtySecondsAgo := time.Now().Add(-60 * time.Second) updateRequest := &getstream.UpdateAppRequest{ RevokeTokensIssuedBefore: &getstream.Timestamp{Time: &sixtySecondsAgo}, } ctx := context.Background() response, err := client.UpdateApp(ctx, updateRequest) if err != nil { log.Fatal("Error updating app:", err) } log.Printf("App updated successfully. Response: %+v\n", response) ``` ```php use GetStream\ClientBuilder; use GetStream\GeneratedModels; $client = (new ClientBuilder()) ->apiKey('api_key') ->apiSecret('api_secret') ->build(); $sixtySecondsAgo = new DateTime(); $sixtySecondsAgo->modify('-60 seconds'); $request = new GeneratedModels\UpdateAppRequest( revokeTokensIssuedBefore: $sixtySecondsAgo->format(DateTime::ATOM) ); $client->updateApp($request); ``` ```ruby require 'getstream_ruby' client = GetStreamRuby.manual( api_key: 'api_key', api_secret: 'api_secret' ) sixty_seconds_ago = Time.now - 60 request = GetStream::Generated::Models::UpdateAppRequest.new( revoke_tokens_issued_before: sixty_seconds_ago.iso8601 ) client.common.update_app(request) ``` ### Undoing the revoke To undo app-level token revocation, you can simply set revocation date to `null`: ```js await client.updateApp({ revoke_tokens_issued_before: null, }); ``` ```java import io.getstream.services.framework.StreamSDKClient; import io.getstream.services.CommonImpl; import io.getstream.models.UpdateAppRequest; import java.util.Date; StreamSDKClient client = new StreamSDKClient("api_key", "api_secret"); CommonImpl common = new CommonImpl(client.getHttpClient()); // Revoke tokens for all users UpdateAppRequest request = UpdateAppRequest.builder() .revokeTokensIssuedBefore(new Date()) .build(); common.updateApp(request).execute(); // Please refer to the Node.js examples above for the API structure ``` ```csharp using GetStream; var builder = new ClientBuilder() .ApiKey("api_key") .ApiSecret("api_secret"); var client = builder.Build(); // Revoke tokens for all users var request = new UpdateAppRequest { RevokeTokensIssuedBefore = DateTime.UtcNow }; await client.UpdateAppAsync(request); // Please refer to the Node.js examples above for the API structure ``` ```go updateRequest := &getstream.UpdateAppRequest{ RevokeTokensIssuedBefore: nil, } ctx := context.Background() response, err := client.UpdateApp(ctx, updateRequest) if err != nil { log.Fatal("Error updating app:", err) } log.Printf("App updated successfully. Response: %+v\n", response) ``` ```php use GetStream\ClientBuilder; use GetStream\GeneratedModels; $client = (new ClientBuilder()) ->apiKey('api_key') ->apiSecret('api_secret') ->build(); $request = new GeneratedModels\UpdateAppRequest( revokeTokensIssuedBefore: null ); $client->updateApp($request); ``` ```ruby require 'getstream_ruby' client = GetStreamRuby.manual( api_key: 'api_key', api_secret: 'api_secret' ) request = GetStream::Generated::Models::UpdateAppRequest.new( revoke_tokens_issued_before: nil ) client.common.update_app(request) ``` ## Developer Tokens For development applications, it is possible to disable token authentication and use client-side generated tokens or a manually generated static token. 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. On the [Dashboard](https://getstream.io/dashboard/): 1. Select the App you want to enable developer tokens on 2. Click *App*name to enter the _Chat Overview_ 3. Scroll to the *Authentication*section 4. Toggle _Disable Auth Checks_ 5. Click Save This disables the authentication check, but does not remove the requirement to send a token. Send either a client generated development token, or manually create one and hard code it into your application. ## Manually Generating Tokens You can generate a token manually using the JWT generator. If you need to test your app before you have a Token Provider and you don't want to enable developer tokens, you can hardcode tokens from this generator into your app for testing. ## How to Refresh Expired Tokens 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. Here is the regular flow to handle tokens with expiration with a token provider: 1. Feeds is initialized using the API Key and the token provider 2. The Feeds client will use the token provider to fetch the token when `connectUser` is called 3. When the token expires, the API will return a specific Authentication error code 4. The client will pause API requests and use the token provider to obtain a fresh token 5. The token provider returns a new token (ie. from your backend) 6. Feeds client replaces the old token with the new one and use it for all waiting and future API calls A token provider is a function or class that you implement and that is responsible for requesting a new token from your own login infrastructure. The most common token provider implementation does an HTTP call to your backend with the ID of the user as well as a valid session id or secret needed to authenticate them. --- This page was last updated at 2026-04-14T15:35:09.937Z. For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/python/tokens-and-authentication/](https://getstream.io/activity-feeds/docs/python/tokens-and-authentication/).