Am creating node backend where user can upload file using the multer package, my upload.js:
const multer = require("multer");
const { google } = require("googleapis");
const fs = require("fs");
const path = require("path");
const router = require("express").Router();
const FOLDERS = require("../utils/folder.drive");
const upload = multer({ dest: "uploads/" });
// Load the service account credentials
const KEYFILEPATH = path.join(__dirname, "../json/drive-credentials.json");
const SCOPES = ["https://www.googleapis.com/auth/drive"];
let drive;
// Initialize Google Drive API
const initializeDrive = async () => {
try {
const auth = new google.auth.GoogleAuth({
keyFile: KEYFILEPATH,
scopes: SCOPES,
});
drive = google.drive({ version: "v3", auth });
} catch (error) {
console.error("Error initializing Google Drive API:", error);
throw new Error("Failed to initialize Google Drive API");
}
};
// Ensure the API is initialized before any route is used
initializeDrive();
// Upload file to Google Drive
const uploadFile = async (file, folderId) => {
if (!drive) {
throw new Error("Google Drive API not initialized");
}
const fileMetadata = {
name: file.originalname,
parents: [FOLDERS[folderId] || FOLDERS.test],
};
const media = {
mimeType: file.mimetype,
body: fs.createReadStream(file.path),
};
try {
const response = await drive.files.create({
resource: fileMetadata,
media: media,
fields: "id",
});
return response.data.id;
} catch (error) {
console.error("Error uploading file:", error);
throw new Error("Failed to upload file");
}
}
router.route("/").post(upload.single("file"), async (req, res) => {
// Get the folder id
const { folderId } = req.body;
// Try uploading
try {
const fileId = await uploadFile(req.file, folderId);
fs.unlinkSync(req.file.path); // Delete the file from the server after uploading
res.status(200).send({ success: true, fileId: fileId });
} catch (error) {
// Send error response if something goes wrong
res.status(500).send({ success: false, error: error.message });
}
});
module.exports = router;
Everything was working fine, files get uploaded to my Google Drive until in installed jsonwebtoken. anytime I upload a file to the backend from my frontend: fileUpload.js
import axios from "axios";
import API from "../config/api.config";
const uploadFile = async (file, folderId) => {
const formData = new FormData();
formData.append("file", file);
formData.append("folderId", folderId);
return await axios
.post(API.url + API.endpoints.upload, formData)
.then((res) => res.data)
.then((data) => {
return { success: true, data };
})
.catch((error) => {
return { success: false, error };
});
};
export default uploadFile;
I encounter this error:
Error uploading file: GaxiosError: invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim.
at Gaxios._request (C:\devfreeguy\projects\web\grajos\backend\node_modules\gaxios\build\src\gaxios.js:142:23)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async GoogleToken._GoogleToken_requestToken (C:\devfreeguy\projects\web\grajos\backend\node_modules\gtoken\build\src\index.js:241:19)
at async GoogleToken._GoogleToken_getTokenAsync (C:\devfreeguy\projects\web\grajos\backend\node_modules\gtoken\build\src\index.js:160:16)
at async JWT.refreshTokenNoCache (C:\devfreeguy\projects\web\grajos\backend\node_modules\google-auth-library\build\src\auth\jwtclient.js:173:23)
at async JWT.getRequestMetadataAsync (C:\devfreeguy\projects\web\grajos\backend\node_modules\google-auth-library\build\src\auth\oauth2client.js:333:17)
at async JWT.requestAsync (C:\devfreeguy\projects\web\grajos\backend\node_modules\google-auth-library\build\src\auth\oauth2client.js:418:23)
at async uploadFile (C:\devfreeguy\projects\web\grajos\backend\routes\upload.js:47:22)
at async C:\devfreeguy\projects\web\grajos\backend\routes\upload.js:64:20 {
config: {
method: 'POST',
url: 'https://www.googleapis.com/oauth2/v4/token',
data: {
grant_type: '<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.',
assertion: '<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.'
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'google-api-nodejs-client/9.14.0',
'x-goog-api-client': 'gl-node/20.17.0',
Accept: 'application/json'
},
responseType: 'json',
retryConfig: {
httpMethodsToRetry: [Array],
currentRetryAttempt: 0,
retry: 3,
noResponseRetries: 2,
retryDelayMultiplier: 2,
timeOfFirstRequest: 1725367689228,
totalTimeout: 9007199254740991,
maxRetryDelay: 9007199254740991,
statusCodesToRetry: [Array]
},
paramsSerializer: [Function: paramsSerializer],
body: '<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.',
validateStatus: [Function: validateStatus],
errorRedactor: [Function: defaultErrorRedactor]
},
response: {
config: {
method: 'POST',
url: 'https://www.googleapis.com/oauth2/v4/token',
data: [Object],
headers: [Object],
responseType: 'json',
retryConfig: [Object],
paramsSerializer: [Function: paramsSerializer],
body: '<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.',
validateStatus: [Function: validateStatus],
errorRedactor: [Function: defaultErrorRedactor]
},
data: {
error: 'invalid_grant',
error_description: 'Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values in the JWT claim.'
},
headers: {
'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
'cache-control': 'private',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=UTF-8',
date: 'Tue, 03 Sep 2024 13:55:16 GMT',
server: 'scaffolding on HTTPServer2',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin, Referer',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '0'
},
status: 400,
statusText: 'Bad Request',
request: { responseURL: 'https://www.googleapis.com/oauth2/v4/token' }
},
error: undefined,
status: 400,
[Symbol(gaxios-gaxios-error)]: '6.7.1'
}
when I read the error, it was related to jsonwebtoken
please help
googleapis
probably already includesjsonwebtoken
and at a specific version. What were you installing it for anyway?