Skip to content

abhimanyusinghtuta/nodejs-file-upload-ssojet-auth-s3-r2

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ File Uploader API with SSOJet Authentication

A config-based file uploader Node.js API that supports multiple cloud storage providers (AWS S3, Cloudflare R2) with SSOJet OpenID Connect authentication. This is a pure API project with no frontend dashboard - perfect for integration into existing applications.

πŸ“‹ Table of Contents

✨ Features

  • πŸ” SSOJet OpenID Connect Authentication - Secure SSO integration
  • πŸš€ Multi-Cloud Storage - AWS S3 and Cloudflare R2 support
  • βš™οΈ Configuration-Based - Environment variable driven
  • πŸ“€ File Upload with URLs - Get direct access URLs after upload
  • πŸ›‘οΈ Security - Helmet.js, CORS, input validation
  • πŸ§ͺ Testing Suite - Jest tests and cURL examples
  • πŸ“ Pure API - No frontend dependencies, JSON responses only

πŸ—οΈ Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 β”‚    β”‚                 β”‚    β”‚                 β”‚
β”‚   Client App    │────│  File Uploader  │────│   Cloud Storage β”‚
β”‚                 β”‚    β”‚      API        β”‚    β”‚   (S3/R2)       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                       β”‚                       β”‚
         β”‚                       β”‚                       β”‚
         β”‚               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”             β”‚
         └───────────────│   SSOJet Auth   β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚    Provider     β”‚
                         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”„ Authentication & Upload Flow

1. Client β†’ GET /auth/ssojet
   ↓
2. Redirect β†’ SSOJet OAuth Provider
   ↓
3. User Authentication β†’ SSOJet
   ↓
4. Callback β†’ POST /auth/callback
   ↓
5. Session Created β†’ Client receives JSON response
   ↓
6. File Upload β†’ POST /api/upload (with session cookie)
   ↓
7. Cloud Storage β†’ File uploaded to S3/R2
   ↓
8. Response β†’ JSON with file URL

πŸ“¦ Prerequisites

Required Software

  • Node.js (v16.0.0 or higher)
  • npm (comes with Node.js)
  • Git (for cloning repository)

Required Accounts & Credentials

  1. SSOJet Account - Sign up at SSOJet
  2. Cloud Storage Account (choose one or both):
    • AWS Account with S3 access
    • Cloudflare Account with R2 access

SSOJet Application Setup

  1. Log in to SSOJet Dashboard
  2. Navigate to Applications
  3. Create new application:
    • Name: File Uploader API
    • Type: Regular Web App
    • Callback URL: http://localhost:3000/auth/callback
  4. Copy credentials:
    • Client ID
    • Client Secret
    • Issuer URL (from Advanced > Endpoints)

πŸ“š Reference: SSOJet Integration Guide

πŸ› οΈ Installation & Setup

1. Clone Repository

git clone https://github.com/abhimanyusinghtuta/nodejs-file-upload-ssojet-auth-s3-r2.git
cd nodejs-file-upload-ssojet-auth-s3-r2

2. Install Dependencies

npm install

3. Environment Configuration

cp .env.example .env

4. Configure Environment Variables

Edit .env file with your credentials:

# Server Configuration
PORT=3000
NODE_ENV=development

# SSOJet Authentication
SSOJET_CLIENT_ID=your_ssojet_client_id
SSOJET_CLIENT_SECRET=your_ssojet_client_secret
SSOJET_AUTHORITY_URL=https://your-subdomain.auth.ssojet.com
SSOJET_REDIRECT_URI=http://localhost:3000/auth/callback

# Session Configuration
SESSION_SECRET=your_super_secret_session_key
AUTH_ENABLED=true

# Default Storage Provider
DEFAULT_STORAGE_PROVIDER=cloudflare-r2

# AWS S3 Configuration (if using S3)
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_key
AWS_REGION=us-east-1
AWS_S3_BUCKET=your-s3-bucket-name

# Cloudflare R2 Configuration (if using R2)
CLOUDFLARE_R2_ACCOUNT_ID=your_cloudflare_account_id
CLOUDFLARE_R2_ACCESS_KEY_ID=your_r2_access_key
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_r2_secret_key
CLOUDFLARE_R2_BUCKET=your-r2-bucket-name
CLOUDFLARE_R2_PUBLIC_URL=https://your-public-domain.com

5. Start the Server

# Development
npm run dev

# Production
npm start

The server will start on http://localhost:3000

πŸ” Authentication Flow

Step-by-Step Authentication Process

1. Check Authentication Status

curl -X GET "http://localhost:3000/api/auth/status" --cookie-jar cookies.txt

2. Get SSO Authentication URL

curl -X GET "http://localhost:3000/login" --cookie cookies.txt

3. Initiate SSO Authentication

⚠️ Important: This step requires browser interaction for OAuth flow

Open in browser: http://localhost:3000/auth/ssojet

  1. Browser redirects to SSOJet
  2. User completes authentication
  3. SSOJet redirects back with auth code
  4. Server exchanges code for tokens
  5. Session cookie is created
  6. JSON response returned with user info

Successful Response:

{
  "success": true,
  "message": "Authentication successful",
  "data": {
    "user": {
      "id": "user_id_from_ssojet",
      "email": "user@example.com",
      "name": "User Name",
      "loginTime": "2025-09-05T18:50:16.242Z"
    },
    "redirectTo": "/api/auth/user",
    "sessionId": "session_id_for_reference"
  },
  "timestamp": "2025-09-05T18:50:16.243Z"
}

4. Verify Authentication

curl -X GET "http://localhost:3000/api/auth/user" --cookie cookies.txt

πŸ“€ API Usage

Authentication Required Endpoints

All file upload endpoints require authentication. Include session cookie in requests.

Upload File

curl -X POST "http://localhost:3000/api/upload" \
  --form "file=@/path/to/your/file.jpg" \
  --form "provider=cloudflare-r2" \
  --cookie cookies.txt

Parameters:

  • file (required): File to upload
  • provider (optional): aws-s3 or cloudflare-r2 (defaults to env variable)

Success Response:

{
  "success": true,
  "message": "File uploaded successfully",
  "data": {
    "filename": "file.jpg",
    "originalName": "file.jpg",
    "size": 51234,
    "mimetype": "image/jpeg",
    "provider": "cloudflare-r2",
    "url": "https://devcdn.pseo.one/uploads/1693934567890-file.jpg",
    "key": "uploads/1693934567890-file.jpg"
  },
  "timestamp": "2025-09-05T18:50:16.243Z"
}

List Available Providers

curl -X GET "http://localhost:3000/api/providers" --cookie cookies.txt

Public Endpoints (No Authentication Required)

Health Check

curl -X GET "http://localhost:3000/api/health"

API Documentation

curl -X GET "http://localhost:3000/"

βš™οΈ Configuration

Supported Storage Providers

AWS S3

AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_REGION=us-east-1
AWS_S3_BUCKET=my-upload-bucket

Cloudflare R2

CLOUDFLARE_R2_ACCOUNT_ID=abc123def456
CLOUDFLARE_R2_ACCESS_KEY_ID=your_r2_access_key
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_r2_secret_key
CLOUDFLARE_R2_BUCKET=my-r2-bucket
CLOUDFLARE_R2_PUBLIC_URL=https://cdn.example.com

Authentication Configuration

# Enable/disable authentication
AUTH_ENABLED=true

# SSOJet configuration
SSOJET_CLIENT_ID=cli_xxxxx.xxxxx.xxxxx
SSOJET_CLIENT_SECRET=sk_xxxxx.xxxxx
SSOJET_AUTHORITY_URL=https://your-subdomain.auth.ssojet.com
SSOJET_REDIRECT_URI=http://localhost:3000/auth/callback

# Session security
SESSION_SECRET=your-super-secret-session-key-here

πŸ§ͺ Testing

Run Test Suite

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run API integration tests
npm run test:api

Manual API Testing

# Test health endpoint
npm run test:health

# Test upload functionality
npm run test:upload

# Test provider listing
npm run test:providers

cURL Examples

See comprehensive cURL examples in CURL_EXAMPLES.md

πŸ”§ Troubleshooting

Common Issues

Authentication Problems

Issue: "Failed to obtain access token"

Solution: Verify SSOJet endpoints in OIDC discovery:
https://your-subdomain.auth.ssojet.com/.well-known/openid-configuration

Issue: Upload API works without authentication

Solution: Check AUTH_ENABLED=true in .env file
Check server logs for requireAuth middleware debug output

File Upload Problems

Issue: "Provider not configured"

Solution: Verify cloud storage credentials in .env
Check DEFAULT_STORAGE_PROVIDER setting

Issue: File upload fails with 413 error

Solution: File too large. Current limit is 50MB
Adjust limit in server.js if needed

Debug Mode

Enable detailed logging:

NODE_ENV=development npm start

Check server console for detailed authentication and upload logs.

πŸ“š References

Official Documentation

Libraries Used

  • Express.js: Web framework
  • Passport.js: Authentication middleware
  • passport-openidconnect: OpenID Connect strategy
  • @aws-sdk/client-s3: AWS S3 SDK v3
  • Multer: File upload handling
  • Helmet.js: Security headers

Related Projects


🀝 Contributing

  1. Fork the repository
  2. Create feature branch (git checkout -b feature/amazing-feature)
  3. Commit changes (git commit -m 'Add amazing feature')
  4. Push to branch (git push origin feature/amazing-feature)
  5. Open Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


Built with ❀️ using Node.js, Express, and SSOJet Authentication


### Cloudflare R2 Configuration

```env
# Cloudflare R2 Configuration
CLOUDFLARE_R2_ACCOUNT_ID=your_account_id
CLOUDFLARE_R2_ACCESS_KEY_ID=your_r2_access_key
CLOUDFLARE_R2_SECRET_ACCESS_KEY=your_r2_secret_key
CLOUDFLARE_R2_BUCKET=your-r2-bucket-name
CLOUDFLARE_R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com

General Configuration

# Server Configuration
PORT=3000
NODE_ENV=development

# Default Storage Provider
DEFAULT_STORAGE_PROVIDER=aws-s3  # or 'cloudflare-r2'

# File Upload Configuration
MAX_FILE_SIZE=10485760  # 10MB in bytes
ALLOWED_FILE_TYPES=image/jpeg,image/png,image/gif,application/pdf,text/plain

API Endpoints

Upload File

POST /api/upload

Upload a file to the configured storage provider.

Request:

  • Method: POST
  • Content-Type: multipart/form-data
  • Body: FormData with file field
  • Optional Query Parameters:
    • provider: Override default storage provider (aws-s3 or cloudflare-r2)

Response:

{
  "success": true,
  "message": "File uploaded successfully",
  "data": {
    "filename": "unique-filename.jpg",
    "originalName": "original-filename.jpg",
    "size": 1024576,
    "mimeType": "image/jpeg",
    "url": "https://bucket-name.s3.amazonaws.com/unique-filename.jpg",
    "provider": "aws-s3",
    "uploadedAt": "2023-12-07T10:30:00.000Z"
  }
}

Health Check

GET /api/health

Check API health status.

Response:

{
  "status": "healthy",
  "timestamp": "2023-12-07T10:30:00.000Z",
  "version": "1.0.0"
}

Usage Examples

Using cURL

# Upload file using default provider
curl -X POST \
  -F "file=@/path/to/your/file.jpg" \
  http://localhost:3000/api/upload

# Upload file using specific provider
curl -X POST \
  -F "file=@/path/to/your/file.jpg" \
  "http://localhost:3000/api/upload?provider=cloudflare-r2"

Using JavaScript (Fetch API)

const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch('/api/upload', {
  method: 'POST',
  body: formData
})
.then(response => response.json())
.then(data => {
  console.log('Upload successful:', data.data.url);
})
.catch(error => {
  console.error('Upload failed:', error);
});

Development

Running the Server

# Development mode (with auto-reload)
npm run dev

# Production mode
npm start

Running Tests

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

Project Structure

fileuploader/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ database.js
β”‚   β”‚   β”œβ”€β”€ storage.js
β”‚   β”‚   └── validation.js
β”‚   β”œβ”€β”€ controllers/
β”‚   β”‚   └── uploadController.js
β”‚   β”œβ”€β”€ middleware/
β”‚   β”‚   β”œβ”€β”€ auth.js
β”‚   β”‚   β”œβ”€β”€ upload.js
β”‚   β”‚   └── validation.js
β”‚   β”œβ”€β”€ providers/
β”‚   β”‚   β”œβ”€β”€ awsS3Provider.js
β”‚   β”‚   β”œβ”€β”€ cloudflareR2Provider.js
β”‚   β”‚   └── storageProviderFactory.js
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   └── upload.js
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”œβ”€β”€ fileUtils.js
β”‚   β”‚   └── response.js
β”‚   └── server.js
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ integration/
β”‚   β”‚   └── upload.test.js
β”‚   └── unit/
β”‚       β”œβ”€β”€ providers.test.js
β”‚       └── utils.test.js
β”œβ”€β”€ .env.example
β”œβ”€β”€ .gitignore
β”œβ”€β”€ package.json
└── README.md

Error Handling

The API includes comprehensive error handling:

  • 400 Bad Request: Invalid file type, missing file, or validation errors
  • 413 Payload Too Large: File size exceeds the maximum allowed limit
  • 500 Internal Server Error: Storage provider errors or server issues

Security Features

  • File type validation
  • File size limits
  • Secure headers with Helmet.js
  • CORS configuration
  • Input sanitization

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

For support, please open an issue in the GitHub repository or contact the maintainers.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published