sahablibya / laravel-sharepoint-filesystem
SharePoint/OneDrive filesystem driver for Laravel using Microsoft Graph API with client credentials authentication
Installs: 37
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/sahablibya/laravel-sharepoint-filesystem
Requires
- php: ^8.1|^8.2|^8.3|^8.4
- guzzlehttp/psr7: ^2.0
- illuminate/filesystem: ^10.0|^11.0|^12.0
- illuminate/http: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- league/flysystem: ^3.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- pestphp/pest: ^2.0|^3.0
- phpunit/phpunit: ^10.0|^11.0
This package is auto-updated.
Last update: 2025-10-11 12:37:48 UTC
README
A Laravel filesystem driver for SharePoint and OneDrive using Microsoft Graph API with client credentials authentication. No manual OAuth flows required - perfect for server-side applications and automated backups.
✨ Features
- ✅ Zero-configuration OAuth - Automatic token management with client credentials flow
- ✅ SharePoint Document Libraries - Direct access to your SharePoint sites
- ✅ OneDrive for Business - Full OneDrive integration
- ✅ Automatic Token Refresh - Handles token expiry seamlessly with smart caching
- ✅ Laravel 10, 11, 12 - Compatible with modern Laravel versions
- ✅ Flysystem v3 - Built on the latest Flysystem architecture
- ✅ Large File Support - Optimized for files up to 250MB
- ✅ Production Ready - Battle-tested in real-world applications
- ✅ Spatie Backup Compatible - Perfect for automated backups to SharePoint
📋 Requirements
- PHP 8.1 or higher
- Laravel 10.x, 11.x, or 12.x
- Microsoft Azure app registration with appropriate permissions
📦 Installation
Install via Composer:
composer require sahablibya/laravel-sharepoint-filesystem
The service provider will be automatically registered via Laravel's package discovery.
⚙️ Configuration
Step 1: Azure App Registration
- Go to Azure Portal
- Navigate to Azure Active Directory → App registrations
- Click New registration
- Enter a name (e.g., "Laravel SharePoint Integration")
- Click Register
- Note your Application (client) ID and Directory (tenant) ID
Step 2: Create Client Secret
- In your app registration, go to Certificates & secrets
- Click New client secret
- Add a description and set expiration
- Click Add
- ⚠️ Copy the secret value immediately (you won't see it again!)
Step 3: Grant API Permissions
- Go to API permissions
- Click Add a permission → Microsoft Graph → Application permissions
- Add these permissions:
Files.ReadWrite.All- Read and write files in all site collectionsSites.ReadWrite.All- Read and write items in all site collections
- Click Grant admin consent (requires admin privileges)
- Wait 2-5 minutes for permissions to propagate
Step 4: Get SharePoint Drive ID (Optional)
To use a specific SharePoint document library, you need the drive ID:
Option A: Using Microsoft Graph Explorer
- Go to Graph Explorer
- Sign in with your account
- Find your site:
GET https://graph.microsoft.com/v1.0/sites?search=YourSiteName - Get drives for that site:
GET https://graph.microsoft.com/v1.0/sites/{site-id}/drives - Copy the
idof your desired document library
Option B: Using PowerShell
Connect-PnPOnline -Url "https://yourtenant.sharepoint.com/sites/yoursite" Get-PnPList | Where-Object {$_.BaseTemplate -eq 101}
Step 5: Environment Configuration
Add these variables to your .env file:
GRAPH_CLIENT_ID=your-application-client-id GRAPH_CLIENT_SECRET=your-client-secret-value GRAPH_TENANT_ID=your-tenant-id # Optional: Specify a SharePoint document library SHAREPOINT_DRIVE_ID=your-drive-id # Optional: Prefix path within the drive SHAREPOINT_PREFIX=backups
Step 6: Register Filesystem Disk
Add the SharePoint disk to your config/filesystems.php:
'disks' => [ // ... other disks 'sharepoint' => [ 'driver' => 'sharepoint', 'client_id' => env('GRAPH_CLIENT_ID'), 'client_secret' => env('GRAPH_CLIENT_SECRET'), 'tenant_id' => env('GRAPH_TENANT_ID', 'common'), 'drive_id' => env('SHAREPOINT_DRIVE_ID'), // Optional 'prefix' => env('SHAREPOINT_PREFIX', ''), // Optional 'throw' => false, ], ],
🚀 Usage
Basic Operations
use Illuminate\Support\Facades\Storage; // Write a file Storage::disk('sharepoint')->put('documents/report.pdf', $contents); // Write from a stream (memory efficient for large files) $stream = fopen('/path/to/large-file.zip', 'r'); Storage::disk('sharepoint')->writeStream('backups/large-file.zip', $stream); // Read a file $contents = Storage::disk('sharepoint')->get('documents/report.pdf'); // Read as stream $stream = Storage::disk('sharepoint')->readStream('documents/report.pdf'); // Check if file exists if (Storage::disk('sharepoint')->exists('documents/report.pdf')) { // File exists } // Delete a file Storage::disk('sharepoint')->delete('documents/report.pdf'); // Delete multiple files Storage::disk('sharepoint')->delete(['file1.pdf', 'file2.pdf']); // Copy a file Storage::disk('sharepoint')->copy('old.pdf', 'new.pdf'); // Move a file Storage::disk('sharepoint')->move('old-location.pdf', 'new-location.pdf');
Directory Operations
// Create a directory Storage::disk('sharepoint')->makeDirectory('documents/2024'); // List files in a directory $files = Storage::disk('sharepoint')->files('documents'); // List all files recursively $files = Storage::disk('sharepoint')->allFiles('documents'); // List directories $directories = Storage::disk('sharepoint')->directories('documents'); // List all directories recursively $directories = Storage::disk('sharepoint')->allDirectories('documents'); // Delete a directory Storage::disk('sharepoint')->deleteDirectory('old-documents');
File Metadata
// Get file size $size = Storage::disk('sharepoint')->size('documents/report.pdf'); // Get last modified time $timestamp = Storage::disk('sharepoint')->lastModified('documents/report.pdf'); // Get MIME type $mimeType = Storage::disk('sharepoint')->mimeType('documents/report.pdf');
URLs & Downloads
// Store an uploaded file $path = $request->file('document')->store('uploads', 'sharepoint'); // Download a file return Storage::disk('sharepoint')->download('documents/report.pdf'); // Download with custom name return Storage::disk('sharepoint')->download('documents/report.pdf', 'custom-name.pdf');
🔄 Using with Spatie Laravel Backup
Perfect integration with Spatie Laravel Backup:
// config/backup.php 'destination' => [ 'disks' => [ 'local', 'sharepoint', // Add SharePoint as backup destination ], ],
Run backups:
# Full backup (database + files) php artisan backup:run # Database only php artisan backup:run --only-db # List backups php artisan backup:list # Clean old backups php artisan backup:clean
🔧 Advanced Configuration
Multiple SharePoint Sites
'disks' => [ 'sharepoint-hr' => [ 'driver' => 'sharepoint', 'client_id' => env('GRAPH_CLIENT_ID'), 'client_secret' => env('GRAPH_CLIENT_SECRET'), 'tenant_id' => env('GRAPH_TENANT_ID'), 'drive_id' => 'hr-drive-id', 'prefix' => 'employee-files', ], 'sharepoint-finance' => [ 'driver' => 'sharepoint', 'client_id' => env('GRAPH_CLIENT_ID'), 'client_secret' => env('GRAPH_CLIENT_SECRET'), 'tenant_id' => env('GRAPH_TENANT_ID'), 'drive_id' => 'finance-drive-id', 'prefix' => 'reports', ], ],
Using OneDrive
The package also supports OneDrive for Business. Use the onedrive driver:
'onedrive' => [ 'driver' => 'onedrive', 'client_id' => env('GRAPH_CLIENT_ID'), 'client_secret' => env('GRAPH_CLIENT_SECRET'), 'tenant_id' => env('GRAPH_TENANT_ID'), 'prefix' => env('ONEDRIVE_PREFIX', ''), ],
Token Caching
Access tokens are automatically cached for 58 minutes (tokens typically expire in 60 minutes). The cache key is unique per disk configuration, allowing multiple SharePoint/OneDrive connections with independent token management.
🐛 Troubleshooting
Permission Errors
Error: "Access denied" or "403 Forbidden"
Solutions:
- Verify
Files.ReadWrite.AllandSites.ReadWrite.Allpermissions are added - Ensure admin consent is granted (look for green checkmarks in Azure Portal)
- Wait 2-5 minutes after granting consent for changes to propagate
- Clear Laravel cache:
php artisan cache:clear
Authentication Errors
Error: "Failed to obtain access token" or "invalid_client"
Solutions:
- Verify
GRAPH_CLIENT_IDmatches your app registration's Application ID - Verify
GRAPH_CLIENT_SECRETis correct (they expire!) - Check
GRAPH_TENANT_IDmatches your Directory (tenant) ID - Ensure no extra spaces in your
.envfile
Drive Not Found
Error: "itemNotFound" or "Resource not found"
Solutions:
- Verify
SHAREPOINT_DRIVE_IDis correct - Try removing
drive_idto use the default OneDrive - Ensure the app has access to the specified drive
- Check the drive exists and hasn't been deleted
Timeout Issues
Error: Timeouts when uploading large files
Solutions:
- The package automatically sets a 5-minute timeout for file operations
- For files > 250MB, consider using Microsoft's resumable upload API
- Check your PHP
max_execution_timeandmemory_limitsettings
Clear Token Cache
If you're experiencing authentication issues:
php artisan cache:clear
Or clear specific SharePoint tokens:
php artisan cache:forget sharepoint_access_token_*
🧪 Testing Connection
Test your SharePoint connection:
use Illuminate\Support\Facades\Storage; Route::get('/test-sharepoint', function () { try { // Create a test file $testContent = 'Test file created at ' . now(); Storage::disk('sharepoint')->put('test.txt', $testContent); // Verify it exists if (!Storage::disk('sharepoint')->exists('test.txt')) { return 'File creation failed!'; } // Read it back $content = Storage::disk('sharepoint')->get('test.txt'); // Clean up Storage::disk('sharepoint')->delete('test.txt'); return 'SharePoint connection successful! Content: ' . $content; } catch (\Exception $e) { return 'Connection failed: ' . $e->getMessage(); } });
🔐 Security Best Practices
- Never commit credentials - Keep
.envin.gitignore - Use environment-specific apps - Separate Azure apps for dev/staging/production
- Rotate secrets regularly - Set expiration dates on client secrets in Azure
- Monitor access logs - Review app activity in Azure Portal regularly
- Principle of least privilege - Only grant necessary permissions
- Secure your
.env- Restrict file permissions:chmod 600 .env
📚 API Reference
Supported Flysystem Operations
| Method | Supported | Notes |
|---|---|---|
write() |
✅ | Write file contents |
writeStream() |
✅ | Write from stream (memory efficient) |
read() |
✅ | Read file contents |
readStream() |
✅ | Read as stream |
delete() |
✅ | Delete file |
deleteDirectory() |
✅ | Delete directory and contents |
createDirectory() |
✅ | Create directory |
fileExists() |
✅ | Check if file exists |
directoryExists() |
✅ | Check if directory exists |
listContents() |
✅ | List directory contents |
move() |
✅ | Move/rename file |
copy() |
✅ | Copy file |
lastModified() |
✅ | Get last modified timestamp |
fileSize() |
✅ | Get file size |
mimeType() |
✅ | Get MIME type |
visibility() |
❌ | Not supported by SharePoint/OneDrive |
setVisibility() |
❌ | Not supported by SharePoint/OneDrive |
🤝 Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Development Setup
# Clone the repository git clone https://github.com/sahablibya/laravel-sharepoint-filesystem.git cd laravel-sharepoint-filesystem # Install dependencies composer install # Run tests composer test
📝 Changelog
Please see CHANGELOG.md for recent changes.
📄 License
This package is open-sourced software licensed under the MIT license.
💡 Credits
- Developed by SahabLibya Development Team
- Built on Flysystem by Frank de Jonge
- Powered by Microsoft Graph API
🙏 Acknowledgments
Special thanks to:
- The Laravel community for inspiration and best practices
- Microsoft for the comprehensive Graph API
- All contributors who help improve this package
📞 Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: dev@sahablibya.ly
Made with ❤️ by SahabLibya Development Team