# Box.com Storage Integration Complete guide for Box.com OAuth 2.0 cloud storage integration with automatic token management and file streaming. ## 📋 Table of Contents - [Features](#features) - [Setup Guide](#setup-guide) - [Configuration](#configuration) - [API Endpoints](#api-endpoints) - [Usage Examples](#usage-examples) - [File Type Support](#file-type-support) - [Troubleshooting](#troubleshooting) --- ## ✨ Features - ✅ OAuth 2.0 User Authentication - ✅ Automatic token refresh and persistence (box-tokens.json) - ✅ File upload with automatic folder routing (IMAGE/VIDEO/DOCUMENT) - ✅ File streaming through your server (supports images, videos, PDFs, audio, etc.) - ✅ File deletion by ID - ✅ No manual token management required --- ## 🚀 Setup Guide ### Step 1: Create a Box Custom App 1. Go to [Box Developer Console](https://app.box.com/developers/console) 2. Click **"Create New App"** 3. Select **"Custom App"** 4. Choose **"User Authentication (OAuth 2.0)"** ⚠️ (NOT JWT or Client Credentials) 5. Name your app (e.g., "Streamflix API") ### Step 2: Configure OAuth Settings 1. In your app's **Configuration** tab: - Copy **Client ID** and **Client Secret** - Add redirect URI: `http://localhost:5119/box/oauth/callback` - Enable scopes: - ✅ Read all files and folders - ✅ Write all files and folders - Save changes ### Step 3: Get Folder IDs 1. Log in to [Box.com](https://app.box.com) 2. Create your folder structure: ``` Streamflix/ ├── images/ ├── videos/ └── documents/ ``` 3. Open each folder and copy the ID from the URL: ``` https://app.box.com/folder/358198319436 ^^^^^^^^^^^^ This is the folder ID ``` ### Step 4: Configure Environment Variables Update your `.env` file: ```env # Box.com OAuth 2.0 Configuration BOX_CLIENT_ID="your_client_id_here" BOX_CLIENT_SECRET="your_client_secret_here" BOX_REDIRECT_URI="http://localhost:5119/box/oauth/callback" # Box Folder IDs (get from Box.com URLs) BOX_STREAMFLIX_FOLDER_ID="358198319436" # Main folder BOX_IMAGES_FOLDER_ID="358199056099" # For IMAGE type uploads BOX_VIDEOS_FOLDER_ID="358199692412" # For VIDEO type uploads BOX_DOCUMENTS_FOLDER_ID="358199056099" # For DOCUMENT type uploads # App URL (for generating content URLs) APP_URL="http://localhost:5119" ``` ### Step 5: Authorize Your Application (One-Time) 1. Start your application: ```bash npm run start:dev ``` 2. Visit the authorization URL in your browser: ``` http://localhost:5119/box/oauth/authorize ``` 3. Log in to Box.com and grant access 4. **Done!** Tokens are automatically saved to `box-tokens.json` --- ## ⚙️ Configuration ### Automatic Token Management - Tokens are stored in `box-tokens.json` (already in `.gitignore`) - Access tokens automatically refresh every ~1 hour - Refresh tokens are automatically updated when Box issues new ones - No manual intervention required after initial authorization ### Folder Routing When uploading files, specify the `fileType` parameter: - `fileType=IMAGE` → Uploads to `BOX_IMAGES_FOLDER_ID` - `fileType=VIDEO` → Uploads to `BOX_VIDEOS_FOLDER_ID` - `fileType=DOCUMENT` → Uploads to `BOX_DOCUMENTS_FOLDER_ID` - No parameter → Uploads to `BOX_STREAMFLIX_FOLDER_ID` (main folder) --- ## 📡 API Endpoints ### 1. OAuth Authorization **Start OAuth Flow** ``` GET /box/oauth/authorize ``` Redirects to Box.com for user authorization (one-time setup). **OAuth Callback** (Automatically called by Box) ``` GET /box/oauth/callback?code={code} ``` Exchanges authorization code for tokens and saves to `box-tokens.json`. --- ### 2. Upload File ``` POST /box/upload ``` **Query Parameters:** - `fileType` (optional): `IMAGE`, `VIDEO`, or `DOCUMENT` - `customFilename` (optional): Custom filename without extension **Form Data:** - `file`: Binary file data **Example Request:** ```bash curl -X POST "http://localhost:5119/box/upload?fileType=IMAGE" \ -F "file=@photo.jpg" ``` **Response:** ```json { "success": true, "name": "1766841360028-photo.jpg", "boxFileId": "2087753948639", "size": 357909, "folderId": "358199056099", "publicUrl": "https://app.box.com/s/xxxxx", "contentUrl": "http://localhost:5119/box/file/2087753948639", "extraData": { "sha1": "22a487ac758861029dfa5791d94c8d50c51b909e", "createdAt": "2025-12-27T05:16:01-08:00", "modifiedAt": "2025-12-27T05:16:01-08:00" } } ``` **Use `contentUrl` for direct file access!** --- ### 3. Stream File Content ``` GET /box/file/:fileId ``` Streams file content through your server. Works for images, videos, PDFs, audio, and more. **Example:** ```html ``` **Supported Features:** - ✅ Images display inline - ✅ Videos support seeking (Accept-Ranges header) - ✅ PDFs display in browser - ✅ Audio files play inline - ✅ Text files display inline - ✅ Cached for 1 year (optimal performance) --- ### 4. Delete File ``` DELETE /box/by-id?fileId={fileId} ``` **Query Parameters:** - `fileId` (required): Box file ID **Example:** ```bash curl -X DELETE "http://localhost:5119/box/by-id?fileId=2087753948639" ``` **Response:** ```json { "message": "File deleted successfully", "success": true, "deletedFileId": "2087753948639" } ``` --- ## 🎯 Usage Examples ### Upload and Display Image ```javascript // Upload const formData = new FormData(); formData.append('file', imageFile); const response = await fetch( 'http://localhost:5119/box/upload?fileType=IMAGE', { method: 'POST', body: formData, }, ); const data = await response.json(); // Display using contentUrl const img = document.createElement('img'); img.src = data.contentUrl; // http://localhost:5119/box/file/2087753948639 document.body.appendChild(img); ``` ### Upload and Play Video ```javascript // Upload const formData = new FormData(); formData.append('file', videoFile); const response = await fetch( 'http://localhost:5119/box/upload?fileType=VIDEO', { method: 'POST', body: formData, }, ); const data = await response.json(); // Play video const video = document.createElement('video'); video.src = data.contentUrl; video.controls = true; document.body.appendChild(video); ``` ### Delete File ```javascript const fileId = '2087753948639'; await fetch(`http://localhost:5119/box/by-id?fileId=${fileId}`, { method: 'DELETE', }); ``` --- ## 🎨 File Type Support ### Images (Display Inline) - JPG/JPEG, PNG, GIF, WebP, SVG, BMP, ICO, TIFF ### Videos (Play Inline with Seeking) - MP4, WebM, OGG, AVI, MOV, WMV, FLV, MKV, M4V, 3GP ### Audio (Play Inline) - MP3, WAV, OGG, M4A, AAC, FLAC ### Documents (Display Inline) - PDF (viewable in browser) - Word, Excel, PowerPoint (will download) ### Text (Display Inline) - TXT, HTML, CSS, JS, JSON, XML, CSV, Markdown ### Archives (Download) - ZIP, RAR, 7Z, TAR, GZ --- ## 🔧 Troubleshooting ### "No tokens found! Please authorize via OAuth" **Solution:** Run the OAuth flow once: ``` http://localhost:5119/box/oauth/authorize ``` --- ### "Refresh token expired!" **Solution:** The refresh token has expired. Re-authorize: ``` http://localhost:5119/box/oauth/authorize ``` --- ### "Box OAuth credentials not configured" **Solution:** Check your `.env` file: - `BOX_CLIENT_ID` must be set - `BOX_CLIENT_SECRET` must be set - Restart your application after updating `.env` --- ### File downloads instead of displaying inline **Cause:** Incorrect MIME type or Content-Disposition header **Solution:** Already fixed! The stream endpoint now: - Detects MIME types from file extensions - Sets `Content-Disposition: inline` - Supports 50+ file formats --- ### Video won't seek/skip **Cause:** Missing `Accept-Ranges` header **Solution:** Already fixed! The stream endpoint now includes: ``` Accept-Ranges: bytes ``` This enables video seeking in all browsers. --- ### Images are resized/compressed **Answer:** No! Files are streamed **byte-for-byte** from Box.com with no modifications. What you upload is exactly what gets delivered. --- ## 🔐 Security Notes 1. **Never commit `box-tokens.json`** - Already in `.gitignore` 2. **Keep `.env` secure** - Never commit to version control 3. **Use environment variables** in production 4. **Rotate tokens** if compromised (re-run OAuth flow) --- ## 📝 Technical Details ### Token Flow 1. **Initial Authorization** (one-time) - User visits `/box/oauth/authorize` - Redirected to Box.com - User grants access - Tokens saved to `box-tokens.json` 2. **Automatic Refresh** (background) - Access token expires after 60 minutes - Service automatically refreshes using refresh token - New tokens saved to `box-tokens.json` - If Box issues new refresh token, it's automatically updated 3. **Persistence** - Tokens survive application restarts - Loaded from `box-tokens.json` on startup - No manual intervention required ### File Streaming - Files are **streamed**, not downloaded to server - Zero server storage used - Supports large files (videos, archives) - Browser caching enabled for optimal performance - Range requests supported for video seeking --- ## 📚 Additional Resources - [Box API Documentation](https://developer.box.com/reference/) - [Box OAuth 2.0 Guide](https://developer.box.com/guides/authentication/oauth2/) - [Box Developer Console](https://app.box.com/developers/console) --- ## 🎉 Quick Start Checklist - [ ] Create Box Custom App with OAuth 2.0 - [ ] Get Client ID and Client Secret - [ ] Create folder structure in Box.com - [ ] Get folder IDs from URLs - [ ] Update `.env` file - [ ] Start application - [ ] Visit `/box/oauth/authorize` - [ ] Grant access to Box - [ ] Test upload: `POST /box/upload` - [ ] Test display: Use `contentUrl` in browser - [ ] Done! 🚀 --- **Need help?** Check the troubleshooting section or contact support.