Skip to main content
Quick Reference for AI Agents & Developers
// Configure secure media mode during SDK init
AppSettings appSettings = (AppSettingsBuilder()
  ..subscriptionType = CometChatSubscriptionType.allUsers
  ..region = "YOUR_REGION"
  ..secureMediaMode = SecureMediaMode.headerBased
  ..autoEstablishSocketConnection = true
).build();

await CometChat.init("YOUR_APP_ID", appSettings,
  onSuccess: (String successMessage) {
    debugPrint("Initialization completed successfully");
  },
  onError: (CometChatException e) {
    debugPrint("Initialization failed: ${e.message}");
  }
);

// Fetch a time-limited presigned URL for secure media (Header-Based or Presigned mode)
String presignedUrl = await CometChat.fetchPresignedUrl("https://files-<region>.cometchat.io/<app_id>/media/file.jpg");

// Check if header-based mode is active
bool isHeaderMode = CometChatHelper.isHeaderModeEnabled();

// Check if a URL requires secure access
bool needsSecure = CometChatHelper.requiresSecureAccess("https://files-<region>.cometchat.io/<app_id>/media/file.jpg");
Token Based File Access lets you control how media files (images, videos, audio, documents) are accessed on CometChat’s secure media servers. The SDK supports three modes — Embedded (FAT appended as a query parameter automatically), Header-Based (FAT added in request headers), and Presigned (clean URLs where you fetch presigned URLs explicitly). Once Token Based File Access is enabled in the CometChat Dashboard, it cannot be disabled.
Available via: SDK | REST API | CometChat Dashboard
Enabling Token Based File Access is irreversible. Once you enable this feature in the CometChat Dashboard, it cannot be disabled. All media URLs will require a valid File Access Token (FAT) for access. Make sure your application is ready to handle secure media URLs before enabling.

Prerequisites

Before using Token Based File Access in your application, ensure the following:
  1. Enable in Dashboard: Navigate to your CometChat Dashboard → ChatsSettings and enable the Token Based File Access configuration. This is a one-time setup step that activates token-based media access for your app.
  2. SDK Initialization: Your application must initialize the CometChat SDK with a valid App ID and region before configuring secure media modes. See Setup for details.
Once Token Based File Access is enabled, all media URLs served by CometChat’s secure media servers require a valid File Access Token (FAT) for access. Any request to a media URL without a valid FAT will receive a 401 Unauthorized response. Ensure your application handles secure media URLs before enabling this feature.

Secure Media Modes

CometChat supports three modes for accessing media files on its secure media servers. The mode is configured during SDK initialization using AppSettingsBuilder.secureMediaMode.

Embedded Mode (Default)

Embedded Mode (SecureMediaMode.embedded) is the default mode. In this mode, the SDK automatically appends the File Access Token (FAT) as a ?fat=<token> query parameter to all media URLs. No additional work is required from the developer — media URLs are ready to use as-is.
  • The SDK handles FAT injection transparently
  • Media URLs include the token directly: https://files-<region>.cometchat.com/<app_id>/media/file.jpg?fat=eyJhbGci...
  • Suitable for simple integrations where clean URLs are not a concern
  • Works out of the box with Image.network(), video players, and other media widgets

Header-Based Mode

Header-Based Mode (SecureMediaMode.headerBased) provides media access by adding the File Access Token (FAT) in the request headers. In this mode, the SDK adds the FAT to the Authorization header when making media requests.
  • Media URLs remain clean without query parameters
  • The FAT is sent in the request header instead of the URL
  • Requires custom HTTP client configuration to include the FAT header
  • Ideal for applications that need clean URLs but can handle custom headers

Presigned Mode

Presigned Mode (SecureMediaMode.presigned) provides clean media URLs without embedded tokens. In this mode, the developer is responsible for calling CometChat.fetchPresignedUrl() to resolve a time-limited presigned URL before rendering media.
  • Media URLs remain clean without query parameters or headers
  • Developer calls CometChat.fetchPresignedUrl(url) to get a presigned URL at render time
  • Presigned URLs are time-limited and grant temporary access to the media file
  • Ideal for applications that need more security, clean URLs, or custom media handling logic

SecureMediaMode Enum

The SecureMediaMode enum defines the available secure media access modes:
ParameterValueDescription
SecureMediaMode.embedded0Default mode. FAT is appended as a ?fat=<token> query parameter to media URLs automatically by the SDK.
SecureMediaMode.headerBased1Header mode. FAT is added to the Authorization header when making media requests.
SecureMediaMode.presigned2Presigned URL mode. Developer calls CometChat.fetchPresignedUrl() to resolve a time-limited presigned URL for media access.

Configuration

Configure the secure media mode during SDK initialization using AppSettingsBuilder.secureMediaMode. Pass a value from the SecureMediaMode enum to select your preferred mode.
String region = "YOUR_REGION";
String appId = "YOUR_APP_ID";

AppSettings appSettings = (AppSettingsBuilder()
  ..subscriptionType = CometChatSubscriptionType.allUsers
  ..region = region
  ..secureMediaMode = SecureMediaMode.embedded
  ..autoEstablishSocketConnection = true
).build();

CometChat.init(appId, appSettings,
  onSuccess: (String successMessage) {
    debugPrint("Initialization completed successfully: $successMessage");
    // SDK is now configured for Embedded secure media access
  },
  onError: (CometChatException e) {
    debugPrint("Initialization failed with exception: ${e.message}");
  }
);
If you omit secureMediaMode, the SDK defaults to Embedded Mode (SecureMediaMode.embedded). In Embedded Mode, the SDK automatically appends the FAT as a query parameter to media URLs — no additional configuration is needed.

Fetching Presigned URLs

When using Presigned Mode or Header-Based Mode, call CometChat.fetchPresignedUrl() to resolve a time-limited presigned URL for any secure media file. The presigned URL grants temporary access to the media file without requiring additional authentication headers.
// Fetch a presigned URL for a secure media file
String mediaUrl = "https://files-<region>.cometchat.com/<app_id>/media/file.jpg";

CometChat.fetchPresignedUrl(mediaUrl,
  onSuccess: (String presignedUrl) {
    debugPrint("Presigned URL: $presignedUrl");
    // Use the presigned URL to render the media (e.g., Image.network(presignedUrl))
  },
  onError: (CometChatException e) {
    debugPrint("Error fetching presigned URL: ${e.message}");
  }
);

Parameters

ParameterTypeDescription
urlStringThe secure media URL to resolve. Must point to a file hosted on CometChat’s secure media servers.

Return Value

TypeDescription
Future<String>Resolves with a time-limited presigned URL that grants temporary access to the media file.

How Attachment URLs Differ

When Token Based File Access is enabled, the format of media attachment URLs depends on the configured mode. Understanding this difference is important for rendering media correctly in your application.

Embedded Mode

In Embedded Mode, the SDK automatically appends the File Access Token (FAT) as a ?fat=<token> query parameter to every media URL. Attachment URLs returned by the SDK are ready to use directly — no additional processing is needed.
https://files-<region>.cometchat.com/<app_id>/media/file.jpg?fat=eyJhbGciOiJIUzI1NiIs...
  • URLs are self-contained and can be used directly with Image.network() or video players
  • The SDK handles token injection transparently when you access attachment URLs from message objects
  • No developer action is required at render time

Header-Based Mode

In Header-Based Mode, the FAT is sent in the request header instead of the URL. You need to configure your HTTP client to include the FAT in the Authorization header when making media requests.
https://files-<region>.cometchat.com/<app_id>/media/file.jpg
  • URLs remain clean without query parameters
  • Use CometChat.getFat() to get the current FAT and add it to your request headers
  • Requires custom HTTP client configuration for media loading
// Example: Loading image with header-based authentication
String? fat = CometChat.getFat();
String mediaUrl = "https://files-<region>.cometchat.com/<app_id>/media/file.jpg";

// Use with http package or dio
final response = await http.get(
  Uri.parse(mediaUrl),
  headers: {
    'Authorization': 'Bearer $fat',
  },
);

Presigned Mode

In Presigned Mode, attachment URLs remain clean without any token parameters. The developer must explicitly call CometChat.fetchPresignedUrl() at render time to resolve a time-limited presigned URL before displaying the media.
https://files-<region>.cometchat.com/<app_id>/media/file.jpg
  • URLs do not contain any token information
  • Before rendering, call CometChat.fetchPresignedUrl(url) to get a presigned URL
  • The presigned URL is time-limited — fetch a new one if it expires
  • Gives you full control over when and how media files are loaded
In Embedded Mode, you can use attachment URLs directly from message objects. In Header-Based Mode, add the FAT to request headers. In Presigned Mode, always resolve the URL with CometChat.fetchPresignedUrl() before passing it to an image or media widget.

API Reference

The following static members are available on the CometChat class for working with Token Based File Access:
MemberTypeDescription
SecureMediaModeenumEnum with three values: embedded (0), headerBased (1), and presigned (2). Used with AppSettingsBuilder.secureMediaMode to configure the secure media access mode.
CometChat.getFat()String?Returns the decoded File Access Token (FAT) for the current session, or null if no valid FAT is available.
CometChat.fetchPresignedUrl(url)Future<String>Resolves a time-limited presigned URL for the given secure media URL. Used in Presigned Mode to get a temporary URL that grants access to the media file.

Helper Methods

The CometChatHelper class provides utility methods to check the current secure media configuration at runtime. These are synchronous methods that return values directly.

isHeaderModeEnabled()

Returns true when all three conditions are met: the secure media mode is set to headerBased, a valid FAT exists for the current session, and the secure media host is configured.
// Check if Header-Based mode is fully active
bool isEnabled = CometChatHelper.isHeaderModeEnabled();
debugPrint("Header-Based mode enabled: $isEnabled");

if (isEnabled) {
  // Add FAT to request headers when loading media
  debugPrint("Add FAT to Authorization header when loading media");
} else {
  // Embedded mode or Presigned mode — handle accordingly
  debugPrint("Use appropriate method for current mode");
}
ParameterTypeDescription
This method takes no parameters.
Return TypeDescription
booltrue if the mode is headerBased, a valid FAT exists, and the secure media host is configured. false otherwise.

requiresSecureAccess(url)

Returns true if the given URL points to the configured secure media host. Use this to determine whether a URL needs special handling for secure access.
// Check if a URL requires secure access
String mediaUrl = "https://files-<region>.cometchat.com/<app_id>/media/file.jpg";
bool needsSecure = CometChatHelper.requiresSecureAccess(mediaUrl);
debugPrint("Requires secure access: $needsSecure");

if (needsSecure) {
  // Handle based on current mode
  if (CometChatHelper.isHeaderModeEnabled()) {
    // Add FAT to headers
    String? fat = CometChat.getFat();
    debugPrint("Use FAT in Authorization header: $fat");
  } else {
    // Fetch presigned URL
    CometChat.fetchPresignedUrl(mediaUrl,
      onSuccess: (String presignedUrl) {
        debugPrint("Use this URL to render media: $presignedUrl");
      },
      onError: (CometChatException e) {
        debugPrint("Error fetching presigned URL: ${e.message}");
      }
    );
  }
} else {
  // URL does not require secure access
  debugPrint("Use the URL directly: $mediaUrl");
}
ParameterTypeDescription
urlStringThe media URL to check. The method compares the URL’s host against the configured secure media host.
Return TypeDescription
booltrue if the URL points to the configured secure media host. false otherwise.

Error Handling

When working with Token Based File Access, handle these common error scenarios gracefully in your application.

Feature Not Enabled

If Token Based File Access is not enabled in the CometChat Dashboard, calling CometChat.fetchPresignedUrl() will not throw an error — it simply returns the same URL string that was passed in. Media URLs work normally without a File Access Token in this case.
// Calling fetchPresignedUrl when the feature is not enabled
String mediaUrl = "https://example.com/file.jpg";

CometChat.fetchPresignedUrl(mediaUrl,
  onSuccess: (String returnedUrl) {
    // returnedUrl == mediaUrl — the same URL is returned as-is
    debugPrint("Returned URL: $returnedUrl");
  },
  onError: (CometChatException e) {
    debugPrint("Error: ${e.message}");
  }
);

Invalid URL Provided

If an invalid or malformed URL is passed to CometChat.fetchPresignedUrl(), the method does not throw an error — it returns the same string that was passed in.
// Passing an invalid URL to fetchPresignedUrl
String invalidUrl = "not-a-valid-url";

CometChat.fetchPresignedUrl(invalidUrl,
  onSuccess: (String returnedUrl) {
    // returnedUrl == invalidUrl — the same string is returned as-is
    debugPrint("Returned URL: $returnedUrl");
  },
  onError: (CometChatException e) {
    debugPrint("Error: ${e.message}");
  }
);

Expired File Access Token (FAT)

When the File Access Token expires, media requests return a 401 Unauthorized response. The SDK automatically refreshes the FAT on re-login. In your application, handle 401 responses by re-fetching the presigned URL.
// Handle expired FAT by re-fetching the presigned URL
String mediaUrl = "https://files-<region>.cometchat.com/<app_id>/media/file.jpg";

void loadSecureMedia(String url) {
  CometChat.fetchPresignedUrl(url,
    onSuccess: (String presignedUrl) {
      debugPrint("Presigned URL: $presignedUrl");
      // Use the presigned URL to render media
    },
    onError: (CometChatException e) {
      debugPrint("Error fetching presigned URL: ${e.message}");
      // If FAT expired, the SDK refreshes it on next login
      // Retry after re-authentication if needed
    }
  );
}

loadSecureMedia(mediaUrl);

Best Practices

Presigned URLs are time-limited but valid for a reasonable duration. Cache them in memory to avoid redundant network calls when rendering the same media file multiple times (e.g., in a scrolling message list). Invalidate the cache when the URL expires or returns a 401 response.
// Simple in-memory cache for presigned URLs
final Map<String, String> _presignedUrlCache = {};

Future<String> getCachedPresignedUrl(String url) async {
  if (_presignedUrlCache.containsKey(url)) {
    return _presignedUrlCache[url]!;
  }
  String presignedUrl = await CometChat.fetchPresignedUrl(url);
  _presignedUrlCache[url] = presignedUrl;
  return presignedUrl;
}
Presigned URLs expire after a set duration. If a media request returns a 401 or 403 response, discard the cached URL and fetch a new presigned URL. Implement a retry mechanism that re-fetches the presigned URL once before showing an error to the user.
// Retry with a fresh presigned URL on 401/403
Future<String> loadMediaWithRetry(String url) async {
  String presignedUrl = await CometChat.fetchPresignedUrl(url);
  final response = await http.get(Uri.parse(presignedUrl));
  
  if (response.statusCode == 401 || response.statusCode == 403) {
    // Token expired — fetch a new presigned URL
    _presignedUrlCache.remove(url);
    return await CometChat.fetchPresignedUrl(url);
  }
  return presignedUrl;
}
A 401 Unauthorized response on a media URL means the File Access Token (FAT) is missing, expired, or invalid. In your application, catch 401 errors and attempt to re-fetch the presigned URL. If the error persists, prompt the user to re-authenticate — the SDK refreshes the FAT automatically on login.
Use Embedded Mode when you want zero-effort media rendering — the SDK appends the FAT to every media URL automatically. This is ideal for simple chat UIs where you display media directly with Image.network().Use Header-Based Mode when you need clean URLs but can configure custom HTTP headers. This mode is suitable for applications using custom HTTP clients or CDN proxies that can forward headers.Use Presigned Mode when you need clean URLs, custom caching strategies, or full control over how media files are fetched. This mode is better suited for applications with custom media players or advanced image loading pipelines.You can check the current mode at runtime using CometChatHelper.isHeaderModeEnabled().

Troubleshooting

Symptom: Media files fail to load and the server returns a 401 Unauthorized response.Possible causes:
  • Token Based File Access is enabled in the Dashboard but the SDK is not configured with a secure media mode.
  • The File Access Token (FAT) has expired or is missing.
  • In Header-Based Mode, you are not including the FAT in request headers.
  • In Presigned Mode, you are using the raw media URL instead of a presigned URL.
Solution:
  1. Verify that secureMediaMode is set during SDK initialization.
  2. In Header-Based Mode, always include the FAT in the Authorization header.
  3. In Presigned Mode, always call CometChat.fetchPresignedUrl(url) before rendering media.
  4. If the FAT has expired, re-authenticate the user — the SDK refreshes the FAT on login.
  5. Use CometChat.getFat() to check if a valid FAT exists for the current session.
Symptom: A presigned URL that previously worked now returns a 401 or 403 response.Cause: Presigned URLs are time-limited. Once the URL expires, it can no longer be used to access the media file.Solution:
  1. Discard the expired presigned URL from any local cache.
  2. Call CometChat.fetchPresignedUrl(url) again with the original media URL to get a fresh presigned URL.
  3. Implement a retry mechanism in your media loading logic to handle expired URLs automatically.
Symptom: Media URLs contain ?fat=<token> when you expect clean URLs, or vice versa.Cause: The SDK is configured in a different mode than expected. For example, the SDK is in Embedded Mode but your code assumes Presigned Mode.Solution:
  1. Check the configured mode using CometChatHelper.isHeaderModeEnabled().
  2. Verify the secureMediaMode value passed during SDK initialization.
  3. In Embedded Mode (SecureMediaMode.embedded), URLs automatically include ?fat=<token> — do not call fetchPresignedUrl().
  4. In Header-Based Mode (SecureMediaMode.headerBased), add the FAT to request headers.
  5. In Presigned Mode (SecureMediaMode.presigned), URLs are clean — always call fetchPresignedUrl() before rendering.

Next Steps