Building Authenticated GraphQL Subscriptions with Hasura and Flutter

Summary
Summary
Summary
Summary

This tutorial covers building authenticated GraphQL subscriptions with Hasura and Flutter. Learn to configure JWT in Hasura, integrate `graphql_flutter` with HTTP and WebSocket links, authenticate subscription connections, manage real-time event streams, handle errors, and clean up resources for secure, reactive mobile development.

This tutorial covers building authenticated GraphQL subscriptions with Hasura and Flutter. Learn to configure JWT in Hasura, integrate `graphql_flutter` with HTTP and WebSocket links, authenticate subscription connections, manage real-time event streams, handle errors, and clean up resources for secure, reactive mobile development.

This tutorial covers building authenticated GraphQL subscriptions with Hasura and Flutter. Learn to configure JWT in Hasura, integrate `graphql_flutter` with HTTP and WebSocket links, authenticate subscription connections, manage real-time event streams, handle errors, and clean up resources for secure, reactive mobile development.

This tutorial covers building authenticated GraphQL subscriptions with Hasura and Flutter. Learn to configure JWT in Hasura, integrate `graphql_flutter` with HTTP and WebSocket links, authenticate subscription connections, manage real-time event streams, handle errors, and clean up resources for secure, reactive mobile development.

Key insights:
Key insights:
Key insights:
Key insights:
  • Setting up Hasura with JWT Authentication: Configure Hasura's JWT secret and permissions to control subscription access.

  • Integrating GraphQL Client in Flutter: Use graphql_flutter with HttpLink and AuthLink to include JWT in requests.

  • Authenticating WebSocket Connections: Initialize WebSocketLink with the JWT in initialPayload to secure live data streams.

  • Managing Subscription Events: Employ client.subscribe and StreamBuilder to receive and render real-time updates.

  • Error Handling and Cleanup: Implement retry logic, token refresh, and cancel subscriptions to maintain a robust connection.

Introduction

Building real-time features in mobile apps often requires a robust subscription mechanism. With Hasura's GraphQL engine and Flutter's flexible ecosystem, you can stream live updates securely using authenticated GraphQL subscriptions. This tutorial walks through setting up JWT authentication in Hasura, configuring a Flutter GraphQL client, and managing secure WebSocket subscriptions to deliver real-time data in your mobile development projects.

Setting up Hasura with JWT Authentication

First, configure Hasura to accept JWT tokens for authorization. In your Hasura console under Settings → JWT, provide your JWT issuer and JWK URL or public key. For example, if using Auth0:

Set HASURA_GRAPHQL_JWT_SECRET to:

{ 
  "type": "RS256",
  "key_url": "https://your-domain/.well-known/jwks.json"
}

Next, define role-based permissions on tables. Under Data → your table → Permissions, grant select or insert permissions to the user role, leveraging X-Hasura-User-Id from the JWT payload. This ensures only authenticated users receive subscription updates.

Integrating GraphQL Client in Flutter

Add the graphql_flutter package to your pubspec.yaml:

dependencies: 
    flutter:
      sdk: flutter
     graphql_flutter

Initialize the client in your main app file. Use an HttpLink combined with an AuthLink to include the JWT on every request.

final authLink = AuthLink(
  getToken: () async => 'Bearer ${await secureStorage.read(key: 'jwt')}',
);
final httpLink = HttpLink('https://hasura.your-domain/v1/graphql');
final link = authLink.concat(httpLink);

final client = GraphQLClient(
  link: link,
  cache: GraphQLCache(store: InMemoryStore()),
);

Wrap your app with GraphQLProvider and pass this client to enable queries, mutations, and subscriptions throughout your widget tree.

Authenticating WebSocket Connections

Subscriptions in GraphQL require a WebSocket link. You must forward the same JWT during the WebSocket handshake. Configure WebSocketLink accordingly:

final wsLink = WebSocketLink(
  'wss://hasura.your-domain/v1/graphql',
  config: SocketClientConfig(
    initialPayload: () async => {
      'headers': {'Authorization': 'Bearer ${await secureStorage.read(key: 'jwt')}'},
    },
  ),
);
final combinedLink = Link.split(
  (request) => request.isSubscription,
  wsLink,
  link, // from HttpLink + AuthLink
);

This setup ensures that each subscription connection is authenticated using the same JWT as HTTP operations.

Managing Subscription Events

With the client and link configured, you can listen to live updates. Use client.subscribe to start streaming:

const chatSubscription = gql(r'''
  subscription OnNewMessage($roomId: Int!) {
    messages(where: {room_id: {_eq: $roomId}}) {
      id
      content
      created_at
    }
  }
''');

final stream = client.subscribe(
  SubscriptionOptions(document: chatSubscription, variables: {'roomId': 42}),
);

stream.listen((result) {
  if (result.hasException) {
    // Handle errors
    return;
  }
  final messages = result.data?['messages'] as List;
  // Update UI with new messages
});

Inside your Flutter widgets, you can use StreamBuilder to rebuild UI as new data arrives. Ensure you dispose of subscriptions when the widget unmounts to avoid memory leaks.

Error Handling and Cleanup

Network interruptions or authorization failures can occur. Listen for errors on the WebSocket client and implement retry logic. For instance, wrap your stream listener in a try-catch and show a loading or reconnect indicator:

  • On AuthError (e.g., token expired), trigger a token refresh and restart the subscription.

  • On NetworkError, implement an exponential backoff reconnection strategy.

Always call stream.drain() or cancel the subscription in your State.dispose() method to clean up resources.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Secure, real-time data in Flutter is achievable by combining Hasura's GraphQL subscriptions with JWT authentication and Flutter's graphql_flutter package. By configuring JWT-based permissions, setting up authenticated WebSocket links, and handling subscription streams responsibly, you can build responsive, secure mobile applications that react instantly to server-side events.

Introduction

Building real-time features in mobile apps often requires a robust subscription mechanism. With Hasura's GraphQL engine and Flutter's flexible ecosystem, you can stream live updates securely using authenticated GraphQL subscriptions. This tutorial walks through setting up JWT authentication in Hasura, configuring a Flutter GraphQL client, and managing secure WebSocket subscriptions to deliver real-time data in your mobile development projects.

Setting up Hasura with JWT Authentication

First, configure Hasura to accept JWT tokens for authorization. In your Hasura console under Settings → JWT, provide your JWT issuer and JWK URL or public key. For example, if using Auth0:

Set HASURA_GRAPHQL_JWT_SECRET to:

{ 
  "type": "RS256",
  "key_url": "https://your-domain/.well-known/jwks.json"
}

Next, define role-based permissions on tables. Under Data → your table → Permissions, grant select or insert permissions to the user role, leveraging X-Hasura-User-Id from the JWT payload. This ensures only authenticated users receive subscription updates.

Integrating GraphQL Client in Flutter

Add the graphql_flutter package to your pubspec.yaml:

dependencies: 
    flutter:
      sdk: flutter
     graphql_flutter

Initialize the client in your main app file. Use an HttpLink combined with an AuthLink to include the JWT on every request.

final authLink = AuthLink(
  getToken: () async => 'Bearer ${await secureStorage.read(key: 'jwt')}',
);
final httpLink = HttpLink('https://hasura.your-domain/v1/graphql');
final link = authLink.concat(httpLink);

final client = GraphQLClient(
  link: link,
  cache: GraphQLCache(store: InMemoryStore()),
);

Wrap your app with GraphQLProvider and pass this client to enable queries, mutations, and subscriptions throughout your widget tree.

Authenticating WebSocket Connections

Subscriptions in GraphQL require a WebSocket link. You must forward the same JWT during the WebSocket handshake. Configure WebSocketLink accordingly:

final wsLink = WebSocketLink(
  'wss://hasura.your-domain/v1/graphql',
  config: SocketClientConfig(
    initialPayload: () async => {
      'headers': {'Authorization': 'Bearer ${await secureStorage.read(key: 'jwt')}'},
    },
  ),
);
final combinedLink = Link.split(
  (request) => request.isSubscription,
  wsLink,
  link, // from HttpLink + AuthLink
);

This setup ensures that each subscription connection is authenticated using the same JWT as HTTP operations.

Managing Subscription Events

With the client and link configured, you can listen to live updates. Use client.subscribe to start streaming:

const chatSubscription = gql(r'''
  subscription OnNewMessage($roomId: Int!) {
    messages(where: {room_id: {_eq: $roomId}}) {
      id
      content
      created_at
    }
  }
''');

final stream = client.subscribe(
  SubscriptionOptions(document: chatSubscription, variables: {'roomId': 42}),
);

stream.listen((result) {
  if (result.hasException) {
    // Handle errors
    return;
  }
  final messages = result.data?['messages'] as List;
  // Update UI with new messages
});

Inside your Flutter widgets, you can use StreamBuilder to rebuild UI as new data arrives. Ensure you dispose of subscriptions when the widget unmounts to avoid memory leaks.

Error Handling and Cleanup

Network interruptions or authorization failures can occur. Listen for errors on the WebSocket client and implement retry logic. For instance, wrap your stream listener in a try-catch and show a loading or reconnect indicator:

  • On AuthError (e.g., token expired), trigger a token refresh and restart the subscription.

  • On NetworkError, implement an exponential backoff reconnection strategy.

Always call stream.drain() or cancel the subscription in your State.dispose() method to clean up resources.

Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.

Conclusion

Secure, real-time data in Flutter is achievable by combining Hasura's GraphQL subscriptions with JWT authentication and Flutter's graphql_flutter package. By configuring JWT-based permissions, setting up authenticated WebSocket links, and handling subscription streams responsibly, you can build responsive, secure mobile applications that react instantly to server-side events.

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Build Flutter Apps Faster with Vibe Studio

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.

Other Insights

Other Insights

Other Insights

Other Insights

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

Join a growing community of builders today

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025

28-07 Jackson Ave

Walturn

New York NY 11101 United States

© Steve • All Rights Reserved 2025