Using Azure Blob storage to store data from confluence pages - Forge App


I am writing a Forge app that makes use of page content data in a space to generate custom content. So far my app makes calls to the Confluence REST API and extracts the page texts from HTML tags. For security, I would like to store the page data as blob in an Azure Blob container. I am using this Azure Blob Storage cofig for NodeJs documentation as my step by step reference, however, I am unsure how to configure authentication to my Azure storage container inside Forge ( I assume I need to modify/add an element/module inside the manifest.yml file for my app but I am not sure what exactly). I also couldn’t find information in Forge docs about this. Did anyone else manage to successfully integrate blob storage as their db for the app? Could you provide me with resources or feedback on how to approach this? Here’s my code which words outside index.jsx but generates errors when I try to use it within index.jsx or use it as an import:

import { BlobServiceClient } from "@azure/storage-blob";
import { v1 as uuidv1 } from 'uuid';
import { DefaultAzureCredential } from '@azure/identity';

// works
export const createBlobStorage = async () => {
    Creates a container on Azure Blob storage 
    Input: None
    Output: Blob service client object , container client object
  const storageAccountName = 'keywisestorage';
  const sasToken = process.env.AZURE_SAS_TOKEN;
  // Create the BlobServiceClient object with connection string
  const blobServiceClient = new BlobServiceClient(
  // Create a unique name for the container
  const containerName = 'pagescontainer' + uuidv1();
  console.log('\nCreating container...');
  console.log('\t', containerName);
  // Get a reference to a container
  const containerClient = blobServiceClient.getContainerClient(containerName);
  // Create the container
  const createContainerResponse = await containerClient.createIfNotExists({
    access: 'container',
  `Container was created successfully.\n\trequestId:${createContainerResponse.requestId}\n\tURL: ${containerClient.url}`
  return {blobServiceClient, containerClient};
  // works
  // containerClient: ContainerClient object
  // blobName: string, includes file extension if provided
  // fileContentsAsString: blob content
  export const uploadBlobFromString = async (containerClient, blobID, fileContentsAsString) => {
    Uloads a string text as a blob into the container
      // Create a unique name for the blob
    const blobName = 'page' + blobID + '.txt';
    // Display blob name and url
    `\nUploading to Azure storage as blob\n\tname: ${blobName}:\n\tURL: ${blockBlobClient.url}`
    // Create blob client from container client
    const blockBlobClient = containerClient.getBlockBlobClient(blobName);
    await blockBlobClient.upload(fileContentsAsString, fileContentsAsString.length);

Thank you very much in advance.

A React component is not a great place to put this kind of code: this should be in a resolver.

Keep in mind that everything that sits in your React components will be visible to the user, including your storage account name and token, which you definitely don’t want to be accessible.

Once you have configured your resolver, you can then invoke it from React (it’s all explained in the linked documentation).
Authentication is fairly easy: you can just set your environment variables for the token and possibly for the storage account and get them from process.env – of course this should happen on the backend. If you try and do this from the frontend, you’re gonna have a bad time and everything that you store will be viewable and editable by anybody.

1 Like

Thank you for your prompt response @PaoloCampanelli :slight_smile: . Is the resolver approach available for apps that are not using a custom UI?

Hi @AsmaaHadir I’m curious as you don’t mention it. Have you looked at Forge Storage to handle this storage for you?

If so why have you decided to build your own storage?

1 Like