AWS S3 SignatureDoesNotMatch Presigned Request

I am implementing image upload to AWS S3 storage, currently I can’t solve the “SingatureDoesNotMatch” error when uploading using the pre-signed URL.

My frontend call looks like this, I retrieve the pre-signed URL but when I try to use it for upload I get the 403 forbidden.

const uploadImageToS3 = async (file, leagueId) => {
  const backendUrl = process.env.REACT_APP_BACKEND_URL || 'http://localhost:8080';
  const jwtToken = Cookies.get('jwtToken');
  const objectKey = `-event-${file.name}`;
  const url = `${backendUrl}/aws/generate-presigned-url?fileName=${objectKey}&contentType=image/jpeg`;

  try {
    const authOptions = {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${jwtToken}`,
        'Content-Type': 'application/json'
      }
    };

    // Fetch the presigned URL from your backend
    const response = await fetchWithAuth(url, authOptions, () => console.log('Logout or handle auth failure'));

    if (!response.ok) {
      throw new Error('Failed to obtain presigned URL');
    }

    let presignedUrl = await response.text();

    // Use the presigned URL to upload the file to S3
    const result = await fetch(presignedUrl, {
      method: 'PUT',
      headers: {
        'Content-Type': "image/jpeg",
      },
      body: file
    });

    if (!result.ok) {
      throw new Error('Failed to upload image to S3');
    }

    console.log('Uploaded successfully!');
    return objectKey;
  } catch (error) {
    console.error('Error uploading image to S3:', error);
    throw error;
  }
};

Backend method (bucket name and credentials are correct):

@GetMapping("/generate-presigned-url")
    public ResponseEntity<?> generatePresignedUrl(@RequestParam String fileName, @RequestParam String contentType) {
        System.out.println(contentType + " filename: " + fileName);
        try {
            // Set the expiry time. Adjust based on your needs.
            Date expiration = new Date();
            long expTimeMillis = Instant.now().toEpochMilli();
            expTimeMillis += 1000 * 60 * 5;
            expiration.setTime(expTimeMillis);

            // Generate the pre-signed URL.
            GeneratePresignedUrlRequest generatePresignedUrlRequest =
                    new GeneratePresignedUrlRequest(bucketName, fileName)
                            .withMethod(HttpMethod.PUT)
                            .withExpiration(expiration)
                            .withContentType(contentType);

            URL url = amazonS3.generatePresignedUrl(generatePresignedUrlRequest);

            return ResponseEntity.ok(url.toString());
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body("Error generating URL: " + e.getMessage());
        }
    }