Microsoft Graph Subscriptions & Webhooks

Introduction

Welcome to the world of Microsoft Graph, an incredibly versatile API that serves as your gateway to a wealth of data and functionalities within the Microsoft 365 ecosystem. Whether you’re dealing with Outlook emails, OneDrive files, Teams conversations, SharePoint documents, or more, Microsoft Graph provides a unified interface to access and interact with this diverse data. For beginners, think of Microsoft Graph as a bridge connecting you to the vast array of Microsoft 365 services. One of its standout features is the ability to keep you informed about changes in your data across these services. How does it do this? Through something called Microsoft Graph Subscriptions and Webhooks. Let’s break it down:

Subscriptions

Imagine you want to be notified whenever a specific event happens – like when a new email arrives in your Outlook inbox, or a file is changed in OneDrive. Subscriptions in Microsoft Graph let you define exactly what you’re interested in. You specify the type of data (resource), the kind of change you want to track (like creation, update, or deletion), where you want the notifications sent (your notification URL), and how long you want the subscription to stay active.

Webhooks

These are the destinations for the notifications triggered by your subscriptions. A webhook is essentially a URL in your application that is ready to receive and process these notifications. When a subscribed event occurs, Microsoft Graph sends a notification to this URL. Your application can then react in real-time, whether that’s by sending alerts, updating a dashboard, syncing data, or triggering other workflows.

In this blog post, we’re going to guide you through the process of creating and managing these subscriptions and webhooks using Microsoft Graph. We’ll also dive into how to handle incoming notifications in your webhook. To make things practical and easier to understand, we’ll include code examples using the Microsoft Graph SDKs for both .NET and JavaScript. This will be a hands-on journey, ideal for beginners and seasoned developers alike, to harness the real-time capabilities of Microsoft Graph in your applications. Let’s get started!

Creating and managing subscriptions

To create a subscription, you need to make a POST request to the /subscriptions endpoint of Microsoft Graph and provide the subscription properties in the request body. For example, the following request creates a subscription to the messages resource of the signed-in user and specifies that the notification URL is https://mywebhook.azurewebsites.net/api/notify, and the subscription expires in one hour.

POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json

Authorization: Bearer {access-token}
{
    "resource": "me/messages",
    "changeType": "created,updated",
    "notificationUrl": "http://mywebhook.azurewebsites.net/api/notify",
    "expirationDateTime": "2023-06-30T11:00:00.0000000Z"
}

The response will contain the subscription object with an ID, which you can use to manage the subscription later. For example, you can update the subscription properties by making a PATCH request to the /subscriptions/{id} endpoint, or delete the subscription by making a DELETE request to the same endpoint.

You can also list all the subscriptions for the signed-in user by making a GET request to the /subscriptions endpoint, or get a specific subscription by making a GET request to the /subscriptions/{id} endpoint.

To create and manage subscriptions using the Microsoft Graph SDKs, you can use the SubscriptionRequestBuilder and SubscriptionRequest classes. For example, the following code snippet in C# creates a subscription to the messages resource of the signed-in user, using the same parameters as the previous request.

var graphClient = new GraphServiceClient(authProvider);
var subscription = new Subscription {
  Resource = "me/messages",
    ChangeType = "created,updated",
    NotificationUrl = "https://mywebhook.azurewebsites.net/api/notify",
    ExpirationDateTime = DateTimeOffset.Parse("2023-06-30T11:00:00.0000000Z")
};
var result = await graphClient.Subscriptions
  .Request()
  .AddAsync(subscription);
Console.WriteLine($"Created subscription with id: {result.Id}");

Handling notifications in your webhook

Once you have created a subscription, Microsoft Graph will send notifications to your webhook whenever the data changes according to the subscription criteria. The notifications will contain the subscription ID, the resource URL, and the change type. You can use this information to retrieve the updated data from Microsoft Graph or perform any other action based on your logic.

To handle the notifications in your webhook, you need to implement the following steps.

  • Validate the notification URL: When you create a subscription, Microsoft Graph will send a validation request to your webhook, with a validationToken query parameter. You need to respond with a 200 OK status code and the validation token value in the response body. This is to ensure that you own the webhook and prevent spoofing.
  • Validate the notification payload: When you receive a notification, you need to validate the payload by checking the signature header. The signature header contains a SHA256 hash of the payload, encrypted with a certificate that you can download from Microsoft Graph. You need to decrypt the signature header using the certificate and compare it with the hash of the payload. This is to ensure that the notification is authentic and not tampered with.
  • Acknowledge the notification: After you validate the notification, you need to respond with a 202 Accepted status code within 30 seconds. This is to acknowledge that you have received the notification and prevent Microsoft Graph from resending it. If you do not respond within 30 seconds, or respond with an error code, Microsoft Graph will retry the delivery up to three times, with an exponential back-off interval.
  • Process the notification: After you acknowledge the notification, you can process it according to your logic. For example, you can use the resource URL in the notification to get the updated data from Microsoft Graph, trigger a workflow, update a dashboard, send an alert, or anything else that your application requires.

To handle the notifications using the Microsoft Graph SDKs, you can use the ChangeNotification and ChangeNotificationCollection classes. For example, the following code snippet in JavaScript validates and processes the notifications in a Node.js webhook, using the Express framework.

const express = require('express');
const crypto = require('crypto');
const graph = require('@microsoft/microsoft-graph-client');
const app = express();

app.use(express.json());

// Load the certificate from Microsoft Graph
const certificate = fs.readFileSync('certificate.pem');

// Handle the validation request
app.get('/api/notify', (req, res) => {
  const validationToken = req.query.validationToken;
  if (validationToken) {
    res.send(validationToken);
  } else {
    res.sendStatus(400);
  }
});

// Handle the notification request
const notification = req.body.value[0];
app.post('/api/notify', (req, res) => {
  const signature = req.headers['x-microsoft-signature'];
  if (validateNotification(notification, signature)) {
    res.sendStatus(202);
    processNotification(notification);
  } else {
    res.sendStatus(403);
  }
});

// Validate the notification payload
function validateNotification(notification, signature) {
  const payload = JSON.stringify(notification);
  const hash = crypto.createHash('sha256').update(payload).digest('hex');
  const decryptedSignature = crypto.publicDecrypt(certificate, Buffer.from(signature, 'base64')).toString('hex');
  return hash === decryptedSignature;
}

// Process the notification
async function processNotification(notification) {
  const subscriptionId = notification.subscriptionId;
  const resource = notification.resource;
  const changeType = notification.changeType;
  console.log(`Received notification for subscription ${subscriptionId} on resource ${resource} with change type ${changeType}`);

  // Get the updated data from Microsoft Graph
  const client = graph.Client.init({
    authProvider: (done) => {
      done(null, {
        access - token
      }); // Get the access token from your auth provider
    }
  });

  const data = await client.api(resource).get();
  console.log(data);
  // Do something with the data, such as triggering a workflow, updating a dashboard, sending an alert, etc.
}

// Start the server
app.listen(3000, () => {
  console.log('Server is listening on port 3000');
});

In this blog post, we have learned how to use Microsoft Graph Subscriptions and Webhooks to get real-time notifications from Microsoft 365 services. We have seen how to create and manage subscriptions using Microsoft Graph API and SDKs, and how to handle and process the notifications in our webhook. We have also shown some code examples using .NET and JavaScript to illustrate the concepts. We hope that this blog post has helped you to understand the benefits and possibilities of using Microsoft Graph Subscriptions and Webhooks in your applications.

To learn more, you can visit the official Microsoft site and receive change notifications through webhooks – Microsoft Graph | Microsoft Learn


Similar Articles