logo

Lack of data validation - Token - Dart


Need

Implementation of robust data validation for JWT access tokens


Context

  1. Usage of Dart for building cross-platform mobile, web, and desktop applications
  2. Usage of Shelf for managing and organizing data in a Node.js application
  3. Usage of jaguar_jwt for JSON Web Token (JWT) authentication and authorization

Description

Insecure Code Example

import 'package:shelf/shelf.dart' as shelf;
import 'package:jaguar_jwt/jaguar_jwt.dart';

shelf.Response handleRequest(shelf.Request request) {
  final String authHeader = request.headers['Authorization'];
  if (authHeader != null && authHeader.startsWith('Bearer ')) {
    final String token = authHeader.substring(7);
    final decClaimSet = verifyJwtHS256Signature(token, 'yourSecret');
    if (decClaimSet != null) {
      return shelf.Response.ok('Authorized');
    }
  }
  return shelf.Response.forbidden('Unauthorized');
}

This Dart code is a simple server-side implementation using the Shelf framework. The `handleRequest` function is a request handler that checks if the incoming request has an 'Authorization' header that contains a JWT token. The `verifyJwtHS256Signature` function from the `jaguar_jwt` package is used to decode the JWT token. The `verifyJwtHS256Signature` function decodes the token but does not validate the signature of the token. This is a security vulnerability because an attacker can modify the token or remove the signature, and the server will still accept the request as valid. The `handleRequest` function checks if the decoded token is not null and if it is not, the server responds with a 200 OK status, indicating that the request is authorized. If the token is null or does not exist, the server responds with a 403 Forbidden status, indicating that the request is unauthorized. However, because the `verifyJwtHS256Signature` function does not validate the signature of the token, an attacker can send a request with a modified or unsigned token, and the server will respond with a 200 OK status, indicating that the request is authorized. This is a security vulnerability because it allows an attacker to bypass authentication and authorization checks.

Steps

  1. First, ensure that the JWT token is not null or empty before proceeding with any operations.
  2. Next, validate the JWT token's signature. This can be done by using a secret key that only the server knows. The 'verifyJwtHS256Signature' function should throw an exception if the signature is invalid.
  3. Handle the exception thrown by 'verifyJwtHS256Signature' function. If an exception is thrown, it means that the token is invalid. In this case, return a 'Unauthorized' response.
  4. If no exception is thrown, it means that the token is valid. Proceed with the request processing.

Secure Code Example

import 'package:shelf/shelf.dart' as shelf;
import 'package:jaguar_jwt/jaguar_jwt.dart';

shelf.Response handleRequest(shelf.Request request) {
  final String authHeader = request.headers['Authorization'];
  if (authHeader != null && authHeader.startsWith('Bearer ')) {
    final String token = authHeader.substring(7);
    if (token != null && token.isNotEmpty) {
      try {
        final decClaimSet = verifyJwtHS256Signature(token, 'yourSecret');
        if (decClaimSet != null) {
          return shelf.Response.ok('Authorized');
        }
      } on JwtException catch (e) {
        return shelf.Response.forbidden('Unauthorized');
      }
    }
  }
  return shelf.Response.forbidden('Unauthorized');
}

The updated code now includes a check to ensure that the JWT token is not null or empty before proceeding with any operations. This is done by adding an if condition `if (token != null && token.isNotEmpty)`. Next, the code validates the JWT token's signature by using the `verifyJwtHS256Signature` function. This function uses a secret key that only the server knows to verify the signature of the token. If the signature is invalid, the function will throw a `JwtException`. The code now handles the `JwtException` thrown by the `verifyJwtHS256Signature` function. If an exception is thrown, it means that the token is invalid. In this case, the function returns a 'Unauthorized' response by using `return shelf.Response.forbidden('Unauthorized');`. If no exception is thrown, it means that the token is valid. The function then proceeds with the request processing and returns a 'Authorized' response.


References

  • 353 - Lack of data validation - Token

  • Last updated

    2023/09/18