AWS S3 and Rekognition Setup

This document describes the AWS integration setup for CAIRL's ID document upload functionality.

Overview

The application uses AWS S3 for secure document storage and AWS Rekognition for ID verification.

Configuration

Environment Variables

Add the following to your .env.local file (never commit this file):

AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=your-actual-access-key-id
AWS_SECRET_ACCESS_KEY=your-actual-secret-access-key
AWS_S3_BUCKET=cairl-id-documents-production
AWS_S3_BUCKET_REGION=us-east-1

IMPORTANT: The .env.example file contains placeholder values only. Always use your real credentials in .env.local.

File Structure

src/lib/aws/
├── index.ts           # Main exports
├── s3.ts             # S3 client configuration
├── rekognition.ts    # Rekognition client configuration
└── upload.ts         # File upload utilities

src/app/api/
├── upload/id/        # ID upload endpoint
│   └── route.ts
└── test-s3/          # S3 connection test endpoint
    └── route.ts

API Endpoints

POST /api/upload/id

Upload an ID document to S3.

Request:

  • Method: POST
  • Content-Type: multipart/form-data
  • Body:
    • file (required): The ID document file
    • userId (optional): User ID for metadata
    • documentType (optional): Type of document (e.g., "passport", "drivers_license")

Response:

{
  "success": true,
  "data": {
    "key": "id-documents/1234567890-abc123.jpg",
    "fileName": "1234567890-abc123.jpg",
    "url": "https://presigned-url...",
    "bucket": "cairl-id-documents-production"
  }
}

Validation:

  • Allowed file types: JPEG, PNG, WebP, PDF
  • Maximum file size: 10MB

GET /api/upload/id

Health check endpoint for the upload service.

Response:

{
  "message": "ID upload endpoint is ready",
  "allowedTypes": [
    "image/jpeg",
    "image/jpg",
    "image/png",
    "image/webp",
    "application/pdf"
  ],
  "maxSize": "10MB"
}

GET /api/test-s3

Test S3 connection and configuration.

Response:

{
  "success": true,
  "message": "S3 connection successful",
  "config": {
    "bucket": "cairl-id-documents-production",
    "region": "us-east-1"
  }
}

Usage Examples

Upload a File (cURL)

curl -X POST http://localhost:3000/api/upload/id \
  -F "file=@/path/to/id-document.jpg" \
  -F "userId=user123" \
  -F "documentType=drivers_license"

Upload a File (JavaScript)

const formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("userId", "user123");
formData.append("documentType", "drivers_license");

const response = await fetch("/api/upload/id", {
  method: "POST",
  body: formData,
});

const result = await response.json();
console.log(result);

Test S3 Connection

curl http://localhost:3000/api/test-s3

Utility Functions

uploadToS3

Upload a file buffer to S3.

import { uploadToS3 } from "@/lib/aws";

const result = await uploadToS3(buffer, "document.jpg", {
  folder: "id-documents",
  metadata: { userId: "123", documentType: "passport" },
  isPublic: false,
});

getSignedS3Url

Get a signed URL for accessing a private S3 object.

import { getSignedS3Url } from "@/lib/aws";

const url = await getSignedS3Url("id-documents/file.jpg", 3600);
// URL expires in 1 hour (3600 seconds)

validateFile

Validate a file before upload.

import { validateFile } from "@/lib/aws";

const validation = validateFile({
  size: file.size,
  type: file.type,
});

if (!validation.valid) {
  console.error(validation.error);
}

Security

  • All ID documents are stored as private objects in S3
  • Access is controlled via signed URLs with expiration times
  • Files are validated for type and size before upload
  • Environment variables are never exposed to the client
  • The .env.local file is gitignored to prevent credential leaks

Testing

  1. Start the development server:

    npm run dev
    
  2. Test S3 connection:

    curl http://localhost:3000/api/test-s3
    
  3. Test file upload:

    curl -X POST http://localhost:3000/api/upload/id \
      -F "file=@test-image.jpg"
    

Troubleshooting

"AWS_REGION is not defined"

Make sure your .env.local file exists and contains all required AWS environment variables.

"Failed to connect to S3"

  • Verify your AWS credentials are correct
  • Check that the S3 bucket exists and is accessible
  • Ensure your IAM user has the necessary S3 permissions

"Invalid file type"

Only JPEG, PNG, WebP, and PDF files are allowed. Check the file MIME type.

"File too large"

Maximum file size is 10MB. Compress or resize the file before uploading.

Required IAM Permissions

Your AWS IAM user needs the following permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:GetObject", "s3:HeadBucket"],
      "Resource": [
        "arn:aws:s3:::cairl-id-documents-production",
        "arn:aws:s3:::cairl-id-documents-production/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "rekognition:DetectText",
        "rekognition:DetectFaces",
        "rekognition:CompareFaces"
      ],
      "Resource": "*"
    }
  ]
}

Next Steps

  • Implement Rekognition integration for ID verification
  • Add image preprocessing (rotation, compression)
  • Implement virus scanning for uploaded files
  • Add upload progress tracking
  • Set up S3 lifecycle policies for automatic deletion of old documents
  • Implement server-side encryption for S3 objects