I am attempting to upload videos to YouTube using the YouTube Data API and a service account in my Node.js backend. However, I keep encountering an "Unauthorized" error. Here is a summary of what I have done so far:
Set Up Service Account:
Created a service account in the Google Cloud Console and downloaded the JSON key file.Enabled domain-wide delegation and provided the necessary permissions in the G Suite Admin console.Granted the following scopes: https://www.googleapis.com/auth/youtube.upload.Backend Code:
const multer = require('multer');const path = require('path');const fs = require('fs');const { google } = require('googleapis');const credentials = require('./path/to/your/service-account-file.json');const router = express.Router();const scopes = ['https://www.googleapis.com/auth/youtube.upload'];// Initialize the JWT clientconst auth = new google.auth.JWT( credentials.client_email, null, credentials.private_key, scopes,'user@example.com' // G Suite user email);// Function to upload a videoasync function uploadVideo(req, res) { const filePath = req.file.path; const { fileName } = req.body; try { const youtube = google.youtube({ version: 'v3', auth, }); if (!filePath) { return res.status(400).json({ error: 'File data not provided' }); } // Video resource const videoParams = { part: 'snippet,status', requestBody: { snippet: { title: req.body.title || 'Test', description: '', tags: [], }, status: { privacyStatus: 'public', }, }, media: { body: fs.createReadStream(filePath), }, }; // Execute the request to upload the video const response = await youtube.videos.insert(videoParams, { onUploadProgress: (evt) => { const progress = (evt.bytesRead / videoParams.media.body._readableState.length) * 100; console.log(`${Math.round(progress)}% uploaded`); }, }); console.log('Video uploaded:', response.data); const videoUrl = `https://www.youtube.com/watch?v=${response.data.id}`; // Send response with video URL res.status(200).json({ message: 'Video uploaded successfully', videoUrl }); } catch (error) { console.error('Error uploading video:', error); res.status(500).json({ error: 'Failed to upload video', message: error.message }); }}const storage = multer.diskStorage({ destination: 'uploads', filename: function (req, file, callback) { callback(null, `${Date.now()}.mp4`); },});const upload = multer({ storage, limits: { fileSize: 100 * 1024 * 1024 }, fileFilter: function (req, file, cb) { const { mimetype } = file; if (mimetype.startsWith('video/')) { cb(null, true); } else { cb(new Error('Invalid file type')); } },});router.post('/youtube-upload', upload.single('file'), uploadVideo);module.exports = router;Frontend Code:javascriptCopy codeconst handleClick = async (e) => { e.preventDefault(); const file = e.target.files[0]; const formData = new FormData(); formData.append('file', file); formData.append('fileName', file.name); if (file.type.startsWith('video/')) { try { const response = await fetch('/youtube-upload', { method: 'POST', body: formData, }); if (!response.ok) { throw new Error('Failed to upload video to YouTube'); } const data = await response.json(); console.log('YouTube upload successful', data); // Update state with the video URL or handle success } catch (error) { console.error('Error uploading video to YouTube:', error.message); // Handle error (e.g., show error message to user) } } else { // Handle non-video uploads }}; ```Despite these steps, I am getting the following error message:GaxiosError: UnauthorizedI have ensured that:The service account has the appropriate permissions.The JWT token is correctly generated and used.What am I missing or doing wrong? Any help would be greatly appreciated.