Networking & http in flutter

6 mins

6 mins

Ashutosh

Published on Oct 9, 2024

How to Handle Authentication and Secure HTTP Requests in Flutter: Make authenticated requests

Learn how to securely authenticate HTTP requests in Flutter by adding authorization headers.
Learn how to securely authenticate HTTP requests in Flutter by adding authorization headers.

Introduction: The Need for Secure Requests

In many apps, especially those dealing with sensitive user data, authentication is a critical component. Authenticating HTTP requests is essential for accessing private APIs, managing user sessions, and ensuring that only authorized users interact with your app's backend.

In this blog, we’ll cover how to add authorization headers to your HTTP requests in Flutter, how to handle secure requests using tokens, and provide a complete example of how to implement this process. By the end of this guide, you’ll understand how to protect your app's communication and keep data secure.

  • What is an authenticated request in Flutter?

  • Why is authorization important for secure requests?


Adding Authorization Headers to HTTP Requests

The most common way to authenticate requests is by adding an authorization token in the HTTP headers. The token, usually in the form of a JWT (JSON Web Token) or OAuth token, tells the server that the request is coming from a trusted source.

To make an authenticated HTTP request in Flutter, you can use the http package, which allows you to modify request headers easily.

Here’s how you can add an authorization header:

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

Future<void> makeAuthenticatedRequest() async {
  final response = await http.get(
    Uri.parse('https://api.example.com/protected'),
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer your_token_here',
    },
  );

  if (response.statusCode == 200) {
    print('Request successful: ${response.body}');
  } else {
    print('Failed to authenticate: ${response.statusCode}');
  }
}

In the above code, the Authorization header is used to send a Bearer token (your_token_here) to the server. The server will verify the token to determine if the request is authorized.

  • How do I add an authorization token to an HTTP request in Flutter?

  • What is a Bearer token in Flutter?

Handling Secure Requests in Flutter

Security is paramount when sending sensitive data over the network. Apart from adding authorization tokens, you should consider the following best practices for handling secure requests in Flutter:

1. Use HTTPS Instead of HTTP

Always use HTTPS to encrypt the data being sent and received. By using HTTPS, you protect user data from being intercepted by attackers. If your API doesn’t support HTTPS, it’s a significant security risk.

2. Token Storage and Expiration

Tokens are usually short-lived and may expire after a certain time. It’s essential to store tokens securely and refresh them when necessary. Flutter provides secure storage options such as the flutter_secure_storage package, which ensures that sensitive information like tokens is stored in a secure and encrypted manner.

Here’s how to store and retrieve tokens securely:

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

final storage = FlutterSecureStorage();

Future<void> storeToken(String token) async {
  await storage.write(key: 'auth_token', value: token);
}

Future<String?> retrieveToken() async {
  return await storage.read(key: 'auth_token');
}

3. Refreshing Tokens

When your token expires, you may need to request a new one using a refresh token. This ensures that users remain authenticated without having to re-login frequently.

To handle token expiration, you can check the response status and refresh the token if necessary:

if (response.statusCode == 401) {
  // Token expired, refresh the token
  await refreshAuthToken();
}

Complete Example: Making Authenticated Requests with Token Storage

Let’s put everything together with a complete example that demonstrates how to send an authenticated request, store tokens securely, and handle token expiration.

import 'package:http/http.dart' as http;
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

final storage = FlutterSecureStorage();

Future<void> authenticateAndFetchData() async {
  String? token = await storage.read(key: 'auth_token');
  
  // If token is not available, you can get a new one (e.g., by logging in)
  if (token == null) {
    token = await loginAndGetToken(); // Assume this function logs in and retrieves a new token
    await storage.write(key: 'auth_token', value: token);
  }

  final response = await http.get(
    Uri.parse('https://api.example.com/protected'),
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer $token',
    },
  );

  if (response.statusCode == 200) {
    print('Authenticated request successful: ${response.body}');
  } else if (response.statusCode == 401) {
    // Token expired, refresh the token and retry
    String newToken = await refreshAuthToken();
    await storage.write(key: 'auth_token', value: newToken);

    // Retry the request with the new token
    final retryResponse = await http.get(
      Uri.parse('https://api.example.com/protected'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
        'Authorization': 'Bearer $newToken',
      },
    );

    if (retryResponse.statusCode == 200) {
      print('Retry successful: ${retryResponse.body}');
    } else {
      print('Failed after retry: ${retryResponse.statusCode}');
    }
  } else {
    print('Request failed: ${response.statusCode}');
  }
}

Future<String> loginAndGetToken() async {
  // Simulating token retrieval after login
  return 'new_token_example';
}

Future<String> refreshAuthToken() async {
  // Simulating refreshing the token
  return 'refreshed_token_example';
}

In this example:

  • We first attempt to retrieve the token from secure storage.

  • If the token is available, we use it to make the authenticated request.

  • If the token is missing or expired, we retrieve or refresh the token and retry the request.

This complete example shows how to manage authenticated requests effectively and securely.

  • How can I make authenticated requests in Flutter?

  • How do I handle token expiration in Flutter?


Conclusion

Securing HTTP requests in Flutter is a key aspect of creating robust and trustworthy applications. By adding authorization headers, storing tokens securely, and handling token expiration, you ensure that your app communicates with the backend securely.

With the steps outlined in this blog, you now have a comprehensive understanding of how to implement authenticated requests in Flutter. By following the complete example, you’ll be able to safeguard your app’s user data and protect your API interactions from unauthorized access.

Follow us on

Follow us on