DevelopmentDecember 2024

A Developer's Guide to Uploading Files to SharePoint with Node.js

Node.jsSharePointMicrosoft Entra IDIntegration

Programmatically interacting with SharePoint can significantly enhance your automation capabilities, enabling document backups and seamless integration with your business systems. One of the most common requirements developers face is uploading files directly to a SharePoint document library.

In this comprehensive guide, we'll walk through the entire process—from setting up the proper permissions in Microsoft Entra ID (formerly Azure Active Directory) to creating a Node.js script that authenticates and uploads files to a designated SharePoint folder. We'll utilize app-only authentication with a certificate, which is a highly secure method for server-to-server interactions.

Part 1: Configure Microsoft Entra ID and SharePoint

Before writing any code, we need to configure an application in Microsoft Entra ID to grant our script the necessary permissions and gather essential information from our SharePoint site.

Configure a Microsoft Entra OAuth App

Step 1: Register an Application

First, we'll create a new app registration in Microsoft Entra ID:

  1. Sign in to the Microsoft Entra Admin Center
  2. Navigate to Entra ID > App registrations
  3. Click + New registration
  4. On the "Register an application" page, enter the following:
    • Name: Give your application a descriptive name, such as "SharePoint File Uploader"
    • Supported account types: Select "Accounts in this organizational directory only (Single tenant)"
    • Redirect URI: Leave this blank for server-to-server applications
  5. Click Register to create the application

Step 2: Add API Permissions

Once your app is registered, you need to grant it permissions to access SharePoint:

  1. Navigate to the API permissions pane of your app
  2. Click Add a permission and select the SharePoint tile
  3. Choose Application permissions
  4. Select Sites.FullControl.All and User.Read.All
  5. After adding the permissions, click Grant Admin Consent for [company name] (this requires the Application Administrator role)

Step 3: Generate a Certificate

We'll use a certificate and private key for authentication. You can generate a self-signed certificate using OpenSSL. If you don't have OpenSSL installed, you can install Git for Windows, which includes Git Bash and OpenSSL.

Open a Git Bash terminal and run the following command to generate a private key and certificate signing request:

openssl req -nodes -newkey pkcs8:2048 -keyout azure-ad.key -out azure-ad.csr

Next, create the self-signed x509 certificate from your private key and CSR:

openssl req -new -x509 -key azure-ad.key -out azure-ad.cer

Step 4: Upload the Certificate

In your Microsoft Entra app registration, navigate to the Certificates & Secrets pane and upload the azure-ad.cer file you just created.

Step 5: Gather Your Credentials

You now have all the credentials needed for authentication. Make a note of the following:

  • Application (client) ID: Available in the Overview pane of your app registration
  • Directory (tenant) ID: Also in the Overview pane
  • Certificate Thumbprint: Visible in the Certificates & secrets pane after uploading your certificate
  • Private Key: The full content of the azure-ad.key file you generated

Gather SharePoint Information

You'll also need the following information about your SharePoint site:

SharePoint Site Domain: This is the domain of your SharePoint site, for example: yourcompany.sharepoint.com

Library and Folder Name:

  1. Your default document library is typically named "Documents". If you've configured a custom library, note its name.
  2. Navigate to the SharePoint folder where you want to upload files
  3. Look at the URL—it often contains an id parameter like ?id=%2FShared%20Documents%2FMy%20Folder
  4. Copy the URL-encoded path and use an online tool to URL-decode it. It will become something like /Shared Documents/My Folder
  5. Remove the leading slash to get the final folder path: Shared Documents/My Folder

You should now have all the configuration details ready. Let's start coding!

Part 2: The Node.js Code

Our script will have two main functions: one to acquire an access token from Microsoft Entra ID and another to use that token to upload a file to SharePoint.

Project Setup

First, create a new Node.js project and install the necessary packages:

npm init -y
npm install axios @azure/msal-node

We'll use axios for making HTTP requests and @azure/msal-node for authentication.

The Authentication Function

Create a file named index.js in your Node app directory and add the following code to authenticate with Microsoft Entra ID:

const msal = require('@azure/msal-node');
const axios = require('axios');
const fs = require('fs');
const path = require('path');

/**
 * Acquires an authentication token from Microsoft Entra ID.
 * @param {object} config - The configuration object.
 * @returns {Promise<string>} The access token.
 */
async function getToken(config) {
    const msalConfig = {
        auth: {
            clientId: config.clientId,
            authority: `https://login.microsoftonline.com/${config.tenantId}`,
            clientCertificate: {
                thumbprint: config.certificateThumbprint,
                privateKey: config.privateKey,
            }
        }
    };

    const client = new msal.ConfidentialClientApplication(msalConfig);

    const tokenRequest = {
        scopes: [`https://${config.sharepointSiteDomain}/.default`]
    };

    try {
        const response = await client.acquireTokenByClientCredential(tokenRequest);
        return response.accessToken;
    } catch (error) {
        console.error('Error acquiring token:', error.message);
        throw error;
    }
}

This function uses the Microsoft Authentication Library (MSAL) for Node to get an access token using the client ID, tenant ID, certificate thumbprint, and private key you gathered earlier.

The File Upload Function

Next, add the upload function that takes an access token and a file stream and uploads the file to the specified SharePoint folder:

/**
 * Uploads a file stream to SharePoint.
 * @param {object} config - The configuration object.
 * @param {string} accessToken - The authentication token.
 * @param {ReadableStream} dataStream - The file stream to upload.
 * @param {string} fileName - The name for the uploaded file.
 * @param {number} fileSize - The size of the file in bytes.
 * @returns {Promise<object>} The response data from SharePoint.
 */
async function uploadFile(config, accessToken, dataStream, fileName, fileSize) {
    const sharepointBaseUri = `https://${config.sharepointSiteDomain}/_api/web`;
    const uploadUrl = `${sharepointBaseUri}/GetFolderByServerRelativeUrl('${config.folder}')/Files/Add(url='${fileName}', overwrite=true)`;

    const axiosConfig = {
        headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/octet-stream',
            'Content-Length': fileSize
        }
    };

    try {
        const response = await axios.post(uploadUrl, dataStream, axiosConfig);
        console.log('File uploaded successfully!');
        return response.data;
    } catch (error) {
        console.error('Error uploading file:', error.response ? error.response.data : error.message);
        throw error;
    }
}

The SharePoint REST API endpoint we're using is _api/web/GetFolderByServerRelativeUrl('Your Folder Path')/Files/Add(url='filename.txt', overwrite=true).

Putting It All Together

Now, let's create the main script to run the process. Add the following code to your index.js file:

// --- Main execution ---
async function run() {
    // WARNING: In a real application, use a secure way to store and access credentials.
    // Do not hardcode them directly in the source code.
    const config = {
        clientId: "YOUR_CLIENT_ID",
        tenantId: "YOUR_TENANT_ID",
        sharepointSiteDomain: "yourcompany.sharepoint.com",
        privateKey: fs.readFileSync("path/to/your/azure-ad.key", "utf8"),
        certificateThumbprint: "YOUR_CERTIFICATE_THUMBPRINT",
        library: "Documents",
        folder: "Shared Documents/My Folder" // The path you determined earlier
    };

    const filePath = path.join(__dirname, 'sample.txt');
    const fileName = path.basename(filePath);
    const fileStats = fs.statSync(filePath);
    const fileSize = fileStats.size;
    const fileStream = fs.createReadStream(filePath);

    try {
        // 1. Get authentication token
        const accessToken = await getToken(config);
        console.log('Successfully acquired access token.');

        // 2. Upload the file
        const uploadResult = await uploadFile(config, accessToken, fileStream, fileName, fileSize);
        console.log('SharePoint upload response:', uploadResult);

    } catch (error) {
        console.error('An error occurred during the process.');
    }
}

// Create a dummy file for testing
fs.writeFileSync('sample.txt', 'This is a test file for SharePoint upload.');

run();

Remember to replace the placeholder values in the config object with your actual credentials. Important: In a production environment, never hardcode credentials directly in your source code. Use environment variables or a secure credential management system.

Running the Script

To run this script, open a terminal, navigate to your Node app directory, and execute:

node index.js

If everything is configured correctly, you should see a sample.txt file appear in your SharePoint folder!

What's Next?

This guide provides a solid foundation for interacting with the SharePoint REST API using Node.js. You can expand on this implementation to:

  • Add metadata to uploaded files
  • Download files from SharePoint
  • Manage list items and folders
  • Implement error handling and retry logic
  • Add support for large file uploads using chunking
  • Create, update, or delete documents programmatically

By mastering these techniques, you'll unlock a wide range of integration possibilities for your applications, enabling seamless document management and workflow automation across your organization's SharePoint environment.

Security Best Practices

Before deploying your solution to production, keep these security considerations in mind:

  1. Never commit credentials to version control: Use environment variables or Azure Key Vault to store sensitive information
  2. Implement proper error handling: Avoid exposing sensitive information in error messages
  3. Use the principle of least privilege: Only grant the minimum permissions necessary for your application to function
  4. Rotate certificates regularly: Set up a process to renew and rotate certificates before they expire
  5. Monitor and log authentication attempts: Keep track of when and how your application accesses SharePoint

Happy coding, and may your SharePoint integrations be smooth and secure!