Claude Skills Guide

Chrome Extension Outlook Calendar Integration: A Developer Guide

Building a Chrome extension that connects to Outlook Calendar opens up powerful productivity workflows. Whether you want to automatically log meeting details, sync calendar events across platforms, or create custom reminder systems, the Microsoft Graph API provides the foundation you need.

This guide walks you through the technical implementation of integrating Outlook Calendar into your Chrome extension, with practical code examples you can adapt for your own projects.

Understanding the Microsoft Graph API

Outlook Calendar access flows through Microsoft Graph, a unified API endpoint for Microsoft services. The API exposes calendar events, schedules, and availability through RESTful endpoints that support CRUD operations.

Before writing any code, you need to register your application in the Azure portal. This gives you a client ID and tenant ID required for authentication. The registration process also defines the permissions your extension will request—specifically Calendars.ReadWrite for calendar access.

Chrome extensions communicate with Microsoft Graph using OAuth 2.0 with the authorization code flow. This involves redirecting users to Microsoft’s login page, handling the callback with an authorization code, and exchanging that code for access and refresh tokens.

Setting Up Authentication

Your extension needs a background script to handle authentication. Here’s a practical implementation pattern:

// background.js - Authentication handler
const CLIENT_ID = 'your-client-id';
const REDIRECT_URI = chrome.identity.getRedirectURL();
const AUTH_URL = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
  client_id=${CLIENT_ID}
  &response_type=code
  &redirect_uri=${encodeURIComponent(REDIRECT_URI)}
  &scope=openid%20profile%20email%20Calendars.ReadWrite`;

chrome.identity.launchWebAuthFlow({
  url: AUTH_URL,
  interactive: true
}, (redirectUrl) => {
  if (chrome.runtime.lastError) {
    console.error('Auth failed:', chrome.runtime.lastError);
    return;
  }
  // Extract authorization code from redirect URL
  const code = new URL(redirectUrl).searchParams.get('code');
  exchangeCodeForTokens(code);
});

function exchangeCodeForTokens(code) {
  // Send to your backend or use token endpoint directly
  // Note: For production, proxy through your server to protect client secret
  fetch('https://login.microsoftonline.com/common/oauth2/v2.0/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      client_id: CLIENT_ID,
      code: code,
      redirect_uri: REDDIRECT_URI,
      grant_type: 'authorization_code'
    })
  }).then(res => res.json())
    .then(tokens => {
      chrome.storage.local.set({ msGraphTokens: tokens });
    });
}

The key insight here is using chrome.identity.launchWebAuthFlow, which handles the OAuth popup flow within the extension context. Store the resulting tokens securely using chrome.storage.local rather than localStorage for better security.

Reading Calendar Events

Once authenticated, fetching calendar events is straightforward with the Graph API:

// Fetch upcoming calendar events
async function getUpcomingEvents(accessToken, startDate, endDate) {
  const queryParams = new URLSearchParams({
    startDateTime: startDate.toISOString(),
    endDateTime: endDate.toISOString(),
    $select: 'id,subject,start,end,location,organizer',
    $orderby: 'start/dateTime'
  });

  const response = await fetch(
    `https://graph.microsoft.com/v1.0/me/calendar/events?${queryParams}`,
    {
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      }
    }
  );

  if (!response.ok) {
    throw new Error(`Graph API error: ${response.status}`);
  }

  const data = await response.json();
  return data.value;
}

This function retrieves events within a date range, selecting only the fields you need to minimize payload size. The API returns events with timezone-aware start and end times, which you’ll need to handle carefully when displaying them to users.

Creating Calendar Events

Creating events requires constructing the proper JSON payload:

async function createCalendarEvent(accessToken, eventDetails) {
  const eventPayload = {
    subject: eventDetails.subject,
    start: {
      dateTime: eventDetails.startTime, // ISO 8601 format
      timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
    },
    end: {
      dateTime: eventDetails.endTime,
      timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
    },
    body: {
      contentType: 'HTML',
      content: eventDetails.description || ''
    },
    location: eventDetails.location ? {
      displayName: eventDetails.location
    } : undefined,
    attendees: eventDetails.attendees?.map(email => ({
      emailAddress: { address: email },
      type: 'required'
    }))
  };

  const response = await fetch(
    'https://graph.microsoft.com/v1.0/me/calendar/events',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(eventPayload)
    }
  );

  return response.json();
}

The API accepts HTML content in the body, which gives you flexibility for formatting meeting agendas or including embedded links. Timezone handling uses the IANA timezone format, which JavaScript’s Intl API provides natively.

Implementing Token Refresh

Access tokens expire—typically within an hour. Your extension needs to handle refresh tokens to maintain uninterrupted functionality:

async function refreshAccessToken(refreshToken, clientId) {
  const response = await fetch(
    'https://login.microsoftonline.com/common/oauth2/v2.0/token',
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams({
        client_id: clientId,
        refresh_token: refreshToken,
        grant_type: 'refresh_token',
        scope: 'openid profile email Calendars.ReadWrite'
      })
    }
  );

  const tokens = await response.json();
  
  // Store updated tokens
  chrome.storage.local.set({ msGraphTokens: tokens });
  
  return tokens.access_token;
}

Call this function proactively before making API requests, or implement error handling that triggers refresh when you receive a 401 response.

Practical Use Cases

With the fundamentals in place, you can build several practical features:

Meeting Transcription Logging: Create a context menu option that captures the current page URL and meeting notes, then automatically creates a calendar event with the captured content as the description.

Cross-Platform Sync: Build a sync mechanism that compares events between Outlook Calendar and Google Calendar, creating corresponding events in the other system when differences are found.

Smart Reminders: Implement custom reminder logic that goes beyond what Outlook offers—perhaps sending browser notifications based on travel time to the meeting location.

Availability Checker: Query free/busy information for a group of colleagues and display optimal meeting times directly in your extension’s popup.

Security Considerations

When building calendar integrations, security deserves serious attention. Never store tokens in localStorage or plain chrome.storage without considering the implications. Use chrome.storage.session for sensitive temporary data, and encrypt tokens at rest if your threat model requires it.

The OAuth flow shown here uses the authorization code flow, which is more secure than the implicit flow. For production deployments, implement token storage on a backend server rather than in the extension itself, using the extension as a thin client that proxies requests through your server.

Testing Your Integration

Microsoft provides a Graph Explorer tool that lets you test API calls without writing code. Use this to validate your API requests before implementing them in the extension. The explorer shows exact request/response formats and helps troubleshoot authentication issues.

For extension testing, use Chrome’s developer mode to load your unpacked extension, and monitor network requests through the DevTools background script console. The Microsoft Graph authentication debugger also provides detailed error messages for common OAuth issues.

Building a Chrome extension with Outlook Calendar integration combines web development skills with Microsoft Graph expertise. The APIs are well-documented and the authentication flow follows standard OAuth patterns, making the implementation straightforward once you understand the specific Microsoft requirements.


Built by theluckystrike — More at zovo.one