Skip to content

Instantly share code, notes, and snippets.

@srsajjad
Last active September 20, 2025 12:16
Show Gist options
  • Save srsajjad/e48b61d37655c6df4e345c49001bb8f8 to your computer and use it in GitHub Desktop.
Save srsajjad/e48b61d37655c6df4e345c49001bb8f8 to your computer and use it in GitHub Desktop.

Clerk Flutter: Force Session Token Refresh

Key point: Do not cache session tokens. Fetch a fresh token right before each API call, and when you update the user externally, reload the User and refresh the token.

References: Force a session token refresh · clerk_flutter repo


Option 1 — Get a fresh token per request (http)

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:clerk_flutter/clerk_flutter.dart';

class ApiClient {
  final String baseUrl;

  ApiClient(this.baseUrl);

  Future<http.Response> get(String path) async {
    final session = Clerk.instance.session;
    if (session == null) {
      throw StateError('No active Clerk session');
    }

    // Force a fresh JWT for every request to avoid expired tokens
    final token = await session.getToken(skipCache: true);

    final uri = Uri.parse('$baseUrl$path');
    return http.get(
      uri,
      headers: {
        'Authorization': 'Bearer $token',
        'Content-Type': 'application/json',
      },
    );
  }

  Future<http.Response> post(String path, Map<String, dynamic> body) async {
    final session = Clerk.instance.session;
    if (session == null) {
      throw StateError('No active Clerk session');
    }

    final token = await session.getToken(skipCache: true);

    final uri = Uri.parse('$baseUrl$path');
    return http.post(
      uri,
      headers: {
        'Authorization': 'Bearer $token',
        'Content-Type': 'application/json',
      },
      body: jsonEncode(body),
    );
  }
}

Option 2 — Force refresh after updating user externally

import 'package:clerk_flutter/clerk_flutter.dart';

/// Call this after you update the Clerk user via your backend/webhook
/// and need both a fresh User object and a new session token.
Future<void> refreshUserAndTokenAfterExternalUpdate() async {
  // Refresh the User object and the session token
  await Clerk.instance.user?.reload();

  // If you only need a new token for subsequent requests:
  final freshToken = await Clerk.instance.session?.getToken(skipCache: true);
  // Use freshToken in your Authorization header (e.g., with http or Dio)
}

Why this works

  • Clerk rotates short‑lived session JWTs roughly every 60 seconds. Reusing cached tokens leads to 401s.
  • getToken(skipCache: true) forces a new token to be minted; user.reload() refreshes both the User object and the token when you changed user data outside the app.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment