I found a much better way to achieve the outcome using the PnPjs libraries. This abstracts away the complexity of getting the Bearer token using a JWT via the MSAL libraries.
Full working code below
import { spfi } from "@pnp/sp";
import { SPDefault } from "@pnp/nodejs";
import {
folderFromAbsolutePath,
folderFromServerRelativePath,
} from "@pnp/sp/folders/index.js";
import "@pnp/sp/files/index.js";
import "@pnp/sp/webs/index.js";
import { readFileSync, createReadStream } from "fs";
import "@azure/msal-node";
const sharepointTenant = `https://tenant.sharepoint.com`; // replace with your tenant
const sharepointSites = `${sharepointTenant}/sites/Foo`; // replace with your site
const folderUrl = "Shared Documents/Bar"; // replace with your folder
const sharePointFolder = `${sharepointSites}/${folderUrl}`;
/**
*
* @returns
*/
async function getSp() {
const tenantId = "XXXX"; // replace from Azure Entra ID
const clientId = "YYYY"; // replace from Azure Entra ID
const thumbprint = "ZZZZ"; // replace from Azure Entra ID
const buffer = readFileSync(
"private.key" // the private key for JWT signing
);
const config = {
auth: {
authority: `https://login.microsoftonline.com/${tenantId}/`,
clientId: clientId,
clientCertificate: {
thumbprint: thumbprint,
privateKey: buffer.toString(),
},
},
};
console.log(`Config: ${JSON.stringify(config)}\n\n`);
const sp = spfi().using(
SPDefault({
baseUrl: sharepointSites,
msal: {
config: config,
scopes: [`${sharepointTenant}/.default`],
},
})
);
const w = await sp.web.select("Title", "Description")();
console.log(`${JSON.stringify(w, null, 4)}\n\n`);
return sp;
}
try {
console.log(
`TENANT:\t${sharepointTenant}\nSITES:\t${sharepointSites}\nFOLDER:\t${sharePointFolder}\n`
);
const sp = await getSp();
const folderAbsolute = await folderFromAbsolutePath(sp.web, sharePointFolder);
const folderRelative = folderFromServerRelativePath(sp.web, folderUrl);
const folderInfo = await folderAbsolute();
//const relativeFolderInfo = await folderRelative();
console.log(`${JSON.stringify(folderInfo, null, 4)}\n\n`);
//console.log(`${JSON.stringify(folderInfo,null,4)}\n\n`);
const fileNamePath = "file.txt";
const file = readFileSync(`./${fileNamePath}`, "utf8");
const stream = createReadStream(fileNamePath);
let result = await sp.web
.getFolderByServerRelativePath(folderUrl)
.files.addUsingPath(encodeURI(fileNamePath), file, { Overwrite: true });
} catch (error) {
console.error(error);
}
Cheers,
Andrew