So integrieren Sie die Outlook Calendar API in Ihre App

Veröffentlicht am

In unserem vorherigen Artikel darüber, wie Sie die Google Calendar API in Ihre Anwendung integrieren, haben wir Schritt für Schritt gezeigt, wie ein Entwickler Google Calendar an seine App anbindet.

In diesem Artikel machen wir dasselbe für die Outlook Calendar API. Wir gehen die Azure-App-Registrierung, die Scopes, die Verifizierung, typische Stolperfallen und praxisnahe Code-Beispiele durch.

Voraussetzungen

Diese Anleitung setzt voraus, dass Sie bereits ein Microsoft-Arbeits- oder -Entwicklerkonto mit Zugriff auf Azure Active Directory (heute Microsoft Entra ID) haben.

Beachten Sie, dass Anwendungen nicht mehr außerhalb eines Verzeichnisses erstellt werden können. Falls Sie noch kein Verzeichnis haben, treten Sie dem Microsoft 365 Developer Program bei oder registrieren Sie sich für Azure.

So verwenden und integrieren Sie die Outlook Calendar API in Ihre App

Schritt 1: Beim Microsoft Azure-Portal anmelden

Öffnen Sie die Anmeldeseite des Microsoft Azure-Portals und melden Sie sich mit Ihrem Konto an.

Die Seite des Microsoft Azure-Portals.

Sign in to the Microsoft Azure Portal

Schritt 2: Eine neue Anwendung registrieren

Nachdem Sie sich beim Microsoft Azure-Portal angemeldet haben:

  1. Navigieren Sie zu Azure Active Directory Azure App Directory Home
  2. Suchen Sie in der Suchleiste nach „ App RegistrationsSearch App Registrations
  3. Klicken Sie auf „ App RegistrationsClick App Registrations
  4. Klicken Sie auf „ New registrationClick New Registration
  5. Füllen Sie die erforderlichen Felder aus: Azure Active Directory - Register the application
    1. Das erste Feld ist der Name Ihrer Anwendung. Diesen Namen sehen die Nutzer auf dem Consent-Screen.
    2. Wählen Sie anschließend die unterstützten Kontotypen . Die richtige Auswahl hängt davon ab, welchen Anwendungstyp Sie entwickeln (nur intern oder mandantenfähig). In diesem Beispiel wähle ich „ Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) “, damit Benutzer aus beliebigen Organisationen (einschließlich Outlook.com-Benutzer) meine App verwenden können. Das ist die beste Option für SaaS-Produkte und andere mandantenfähige Anwendungen.
    3. Geben Sie die Redirect URI an: Dieses Feld ist optional, weil nicht jeder Anwendungstyp es braucht. Entwickeln Sie eine Web-Anwendung, benötigen Sie es in der Regel, da Azure die OAuth-Antworten an diese URI sendet. Wählen Sie im Dropdown „Select a platform“ den Eintrag Web und tragen Sie die Redirect URI ein (z. B. https://ihreapp.com/auth/callback ). Für einen serverseitigen Auth-Flow ist eine Web-Redirect-URI die richtige Wahl. Achten Sie darauf, dass die Domain erreichbar ist und Ihnen gehört.
    4. Klicken Sie auf „Register“ .
    5. Nach dem Klick erstellt Azure Active Directory Ihre Anwendung und leitet Sie zur Übersichtsseite weiter, auf der Sie Client ID und Tenant ID kopieren können. Die Application (client) ID ist eine GUID, die Ihre App identifiziert. Die Directory (tenant) ID brauchen Sie nicht immer. Bei mandantenfähigen Apps nutzen Sie normalerweise den Endpunkt common , für Tests im eigenen Mandanten ist die Tenant ID aber praktisch. Application Created

Schritt 3: API-Berechtigungen konfigurieren

Sobald Ihre App registriert ist, legen Sie die Kalenderberechtigungen fest. Diese Berechtigungen werden im OAuth-Flow angezeigt. So sieht der Nutzer, welche Scopes Ihre Anwendung anfordert, bevor er den Zugriff auf seine Kalender gewährt.

Standardmäßig erhält Ihre Anwendung nur die Berechtigung „User.Read“. Wenn Sie den Nutzer lediglich anmelden und sein Profil lesen wollen, können Sie diesen Schritt überspringen.

So fügen Sie API-Berechtigungen hinzu:

  1. Klicken Sie im linken Seitenmenü auf „Manage“ .
  2. Wählen Sie „API Permissions“ . Click API Permissions
  3. Klicken Sie auf „+ Add a permission“ . Click _Add a permission_ button
  4. Suchen Sie die Kachel „Microsoft Graph“ (normalerweise die erste Kachel in der Leiste, die sich rechts öffnet, nachdem Sie auf „Add a permission“ geklickt haben). Click the _Microsoft Graph_ card
  5. Entscheiden Sie sich zwischen „Delegated permissions“ und „Application permissions“ . Delegierte Berechtigungen sind die richtige Wahl, wenn Ihre Anwendung die API im Namen des angemeldeten Nutzers aufruft. Anwendungsberechtigungen nutzt man dagegen, wenn Ihre Anwendung als Hintergrunddienst ohne angemeldeten Nutzer läuft. In diesem Beispiel nutze ich „Delegated permissions“ . Click _Delegated Permissions_
  6. Suchen Sie nach „Calendars“ : Die Suche zeigt alle kalenderbezogenen Berechtigungen. Wählen Sie nur die Berechtigungen, die Ihre Anwendung wirklich braucht. In den meisten Fällen sind das „Calendars.ReadWrite“ und „Calendars.ReadWrite.Shared“ (falls Sie Zugriff auf freigegebene Kalender brauchen). Kalender-Scopes erfordern normalerweise keine Admin-Zustimmung, da sie nutzerdelegiert sind. Manche Organisationen schränken die Nutzerzustimmung jedoch ein. Darf ein Nutzer aus einem externen Mandanten nicht selbst zustimmen, muss ein Admin dieses Mandanten Ihrer App zustimmen (meist über einen Admin-Consent-Prompt oder eine URL). Search for _Calendars Permissions_

Schritt 4: ID-Tokens aktivieren

Nicht jede App braucht diesen Schritt. Wenn Sie aber auf Profilinformationen wie Name, E-Mail oder Profilbild-URL zugreifen möchten, müssen Sie die Option ID-Tokens unter Verwalten -> Authentifizierung aktivieren.

Mit ID-Tokens kann Ihre App den Benutzer direkt nach dem Verbinden des Kalenders identifizieren, ohne einen zusätzlichen API-Aufruf zu machen.

Enable ID Tokens option

Schritt 5: Ein Client Secret erstellen

Wir empfehlen, alle Kalenderoperationen (Lesen, Schreiben, Updates usw.) serverseitig auszuführen. Dafür brauchen Sie ein Client Secret.

So erzeugen Sie ein Client Secret:

  1. Klicken Sie auf den Tab „Certificates & secrets“ Click the “Certificates & secrets tab”
  2. Klicken Sie auf „New client secret“ Click “New client secret”
  3. Geben Sie eine Beschreibung und ein Ablaufdatum an Enter a description and an expiration date

Kopieren Sie das Client Secret direkt nach dem Erstellen und bewahren Sie es sicher auf (üblicherweise in Ihrer .env-Datei).

Schritt 6: Branding und Verifizierung

Im Bereich „Branding & Properties“ der App-Registrierung können Sie ein Logo und Informationen (App-Beschreibung, Nutzungsbedingungen-URL usw.) festlegen. Das ist optional, aber wir empfehlen es für einen professionellen Consent-Screen. Wichtig ist, eine Publisher Domain (in der Regel Ihre eigene, in Azure AD verifizierte Domain) zu setzen. Sie verhindert, dass die App bei der Zustimmung als „unverified“ erscheint. Für mandantenfähige Apps erwartet Microsoft inzwischen eine Publisher-Verifizierung. Ohne diese Verifizierung können Benutzer außerhalb Ihres Mandanten wegen der Sicherheitsrichtlinien vom November 2020 blockiert werden.

Branding & Properties screen

Schritt 7: Mit der Outlook Graph API vertraut machen

Sobald die Anwendung eingerichtet ist, können Sie die Microsoft Calendar Graph API erkunden und die Endpunkte zum Erstellen, Aktualisieren und Löschen von Terminen kennenlernen.

Schritt 8: Überlegen Sie, einen Unified-Calendar-API-Dienst zu nutzen, um alle Kalenderanbieter über eine einzige API zu integrieren

Die Microsoft Graph API ist recht gut dokumentiert. Trotzdem empfehlen wir, einen Blick auf eine Unified Calendar API zu werfen, mit der Sie alle Kalenderanbieter über eine einzige API in Ihre Anwendung einbinden.

Mit einer Unified Calendar API implementieren Sie nur eine API und unterstützen trotzdem alle Kalenderanbieter, unabhängig von deren Einschränkungen oder API-Unterschieden.

Ein weiterer Vorteil einer einzigen API für alle Kalender: Sie müssen nicht mehrere Anbieter-Integrationen pflegen, sich nicht um Breaking Changes kümmern und keine Edge-Cases behandeln, an die Sie nie gedacht hätten.

Die Apiroc Unified Calendar API

Beispiel eines Outlook Calendar-Autorisierungsflows

Das folgende Flussdiagramm zeigt einen einfachen OAuth-Flow für Outlook Calendar, über den Benutzer ihren Outlook-Kalender mit Ihrer App verbinden.

Outlook OAuth 2.0 Flow

Wenn Sie mehr über den Microsoft-OAuth2-Flow erfahren möchten, schauen Sie in die Microsoft-Dokumentation zum OAuth 2.0-Autorisierungscode-Flow.

Client-Seite (UI)

const microsoftOauthUrl = getMicrosoftOAuthUrl()
<button href="microsoftOauthUrl"   rel="noopener noreferrer"> Connect Outlook Calendar </button>
export const SCOPES = [
  "openid",
  "email",
  "profile",
  "offline_access",
  "Calendars.ReadWrite",
  "User.Read",
];

export interface ClientState {
  session: Session;
  returnUrl?: string;
}

export function stateToB64(session: ClientState): string {
  return encode(JSON.stringify(session));
}

export function getMicrosoftOAuthUrl(
  state: ClientState,
) {
  const nonce = uuid();
  const TENANT_ID = process.env.NEXT_PUBLIC_MICROSOFT_TENANT_ID;
  const params = new URLSearchParams({
    client_id: process.env.MICROSOFT_CLIENT_ID || "",
    redirect_uri: `${getHostName()}/api/connect/microsoft`,
    response_type: "code id_token",
    scope: SCOPES.join(" "),
    prompt: "consent",
    response_mode: "form_post",
    state: stateToB64(state),
    nonce,
  });
  return `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/authorize?${params}`;
}
  • Der Parameter „prompt“ akzeptiert einen von vier Werten: login , none , consent oder select_account .
  • Der Parameter „response_mode“ akzeptiert query , fragment oder form_post . Wir wählen form_post , weil Microsoft dann eine POST-Anfrage an unsere Redirect URI (auf dem Server) sendet.

API-Seite (Backend)

Als Nächstes bauen wir den API-Handler. Er empfängt den Code und die Scopes vom Microsoft-Server und tauscht sie gegen Tokens aus.

In diesem Beispiel verwenden wir zod für die Validierung.

const successSchema = z.object({
  code: z.string(),
  state: z.string(),
  id_token: z.string(),
  session_state: z.string().optional(),
});

const errorSchema = z.object({
  error: z.string(),
  error_description: z.string().optional(),
});
type ErrorParams = z.infer<typeof errorSchema>;

const querySchema = z.union([successSchema, errorSchema]);

function isError(query: Record<string, any>): query is ErrorParams {
  return Boolean(query.error);
}

const microsoftHandler: NextApiHandler = async (req, res) => {
  try {
    const result = querySchema.parse(req.body);
    if (isError(result)) {
      const q = new URLSearchParams({
        error: "ACCESS_DENIED",
        provider: CalendarProvider.MICROSOFT,
      });

      console.error({ result });
      return res.redirect(302, `/?${q}`);
    }

    const { session, returnUrl } = stateFromB64(result.state);
    const { email } = decodeIdToken(result.id_token);
    const { access_token, refresh_token, expires_in, scope } =
      await exchangeCodeForTokens(result.code);

    const connection = await upsertConnection(
      {
        email,
        accessToken: access_token,
        refreshToken: refresh_token,
        expiresInSeconds: expires_in,
        status: ConnectionStatus.ACTIVE,
        provider: CalendarProvider.MICROSOFT,
        scopes: scope,
      },
      session.user
    );

    const q = new URLSearchParams({
      cid: connection.id,
    });
    if (returnUrl) q.append("returnUrl", returnUrl);

    res.redirect(302, returnUrl ? returnUrl : `/calendars/microsoft?${q}`);
  } catch (e: any) {
    let error = JSON.stringify(e);

    const querystr =
      typeof req.query === "string" ? req.query : JSON.stringify(req.query);

    const q = new URLSearchParams({
      error,
      provider: CalendarProvider.MICROSOFT,
    });
    return res.redirect(302, `/?${q}`);
  }
};

export default microsoftHandler;

Wie auf der Client-Seite empfehlen wir kleine Hilfsfunktionen, etwa zum Austauschen des Codes gegen Tokens.

const TENANT_ID = process.env.MICROSOFT_TENANT_ID;

export async function exchangeCodeForTokens(code: string) {
  const data = new FormData();
  data.append("client_id", process.env.MICROSOFT_CLIENT_ID || "");
  data.append("scope", SCOPES.join(" "));
  data.append("code", code);
  data.append("redirect_uri", `${getHostName()}/api/connect/microsoft`);
  data.append("grant_type", "authorization_code");
  data.append("client_secret", process.env.MICROSOFT_CLIENT_SECRET || "");

  try {
    const result = await fetch(
      `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`,
      {
        method: "POST",
        body: data,
      }
    );

    const json = await result.json();
    if (json.error) throw json;

    const parsed = responseSchema.parse(json);
    return parsed;
  } catch (e) {
    console.error("Exchange failed");
    throw e;
  }
}

Stolperfallen bei der Outlook Calendar API-Integration

  • Verifizierung kann dauern und frustrierend sein : Tausende, wenn nicht Millionen Entwickler bauen auf Outlook auf, daher prüft Microsoft täglich sehr viele Einreichungen. Füllen Sie alle Angaben gewissenhaft aus und planen Sie die Verifizierungszeit in Ihrer Roadmap ein.

  • Fordern Sie nur die Scopes an, die Sie wirklich brauchen : Das Microsoft-Team prüft Apps sehr gründlich, also fordern Sie nur an, was Ihre Anwendung wirklich braucht. Das erleichtert die Freigabe und hilft auch, wenn Nutzer Ihrer App Zugriff gewähren. Nutzer sind verwirrt, wenn eine App Scopes anfordert, die nichts mit ihren eigentlichen Funktionen zu tun haben.

  • Webhooks laufen ab, erneuern Sie sie rechtzeitig : Registrieren Sie Webhooks, um Kalenderänderungen zu verfolgen, richten Sie einen Hintergrund-Job ein, der alle paar Stunden läuft und jedes bald ablaufende Abonnement erneuert.

  • Rate Limiting und Throttling : Microsoft hat strenge Regeln für Rate Limiting und Throttling. Vermeiden Sie Einzelabrufe und implementieren Sie eigenes Rate Limiting für Ihre API-Aufrufe, damit Sie nicht in die bekannten „MailboxConcurrency“-Fehler läufst. Die folgende Tabelle fasst die Rate Limits und Throttling-Grenzen zusammen:

    BereichLimitHinweise
    Pro Postfach (App-ID & Postfach)10.000 Anfragen / 10 Min. und 4 gleichzeitige Anfragen.Der bekannte „MailboxConcurrency“-Fehler.
    Upload150 MB PATCH/POST/PUT pro 5 Min. pro Postfach.Kann bei großen ICS-Dateien oder Anhängen zuschlagen.
    Global (Graph)130.000 Anfragen / 10 s pro App über alle Mandanten.Selten, aber große SaaS-Backfills können es auslösen.
    Retry-VerhaltenBei 429 oder 503/504 den Retry-After-Header beachten und exponentiell zurückweichenDie Graph API drosselt weiter, wenn Sie sie jede Sekunde bombardieren.
  • Zeitzonen-Tücken : In Outlook können Nutzer ihre Zeitzone manuell eintippen (Sie ahnen, worauf das hinausläuft). Stellen Sie sicher, dass Ihr Code auch diesen Fall behandelt.

  • Consent- & Berechtigungsprobleme : Wie im Abschnitt zu den Scopes erwähnt, ist Calendars.ReadWrite nutzerdelegiert. Viele Mandanten erlauben die Nutzerzustimmung, manche aber nicht. Rechnen Sie mit dem Fehler „ admin consent required “ und zeigen Sie einen freundlichen „Bitte Admin fragen“-Flow.

Integrieren Sie alle Kalenderanbieter in Ihre App mit der Apiroc Unified Calendar API

Kalenderintegrationen sind unser Kerngeschäft. Unser Team arbeitet seit Jahren mit Google Calendar, Outlook und iCloud Calendar und hat Kalenderintegrationen gebaut, die Milliarden von API-Aufrufen verarbeiten.

Die Erfahrungen aus der Arbeit mit allen großen Kalender-APIs sind in die Apiroc Unified Calendar API eingeflossen. Sie spart Entwicklern Hunderte Stunden bei Kalenderproblemen, damit sie sich auf die Features konzentrieren können, die ihr Produkt voranbringen.

Registrieren Sie sich bei Apiroc, um die Unified Calendar API auszuprobieren und mehrere Kalenderanbieter über eine einzige API zu integrieren. Für den kostenlosen Plan ist keine Kreditkarte nötig.

Häufig gestellte Fragen

Welches Konto brauche ich, um die Outlook Calendar API zu nutzen?

Sie benötigen ein Microsoft-Arbeits- oder Entwicklerkonto mit Zugriff auf Azure Active Directory.

Welche Berechtigungsbereiche sollte ich für vollen Kalenderzugriff hinzufügen?

Fügen Sie in Microsoft Graph Calendars.ReadWrite hinzu (und Calendars.ReadWrite.Shared, falls Sie freigegebene Kalender brauchen).

Warum sollte ich eine Publisher-Domain und ein Branding festlegen?

Die Publisher-Verifizierung und ein gebrandeter Consent-Screen verhindern, dass Ihre App als „nicht verifiziert“ erscheint. Für die meisten mandantenfähigen Apps werden sie inzwischen erwartet.

Wie oft muss ich Outlook-Webhook-Abonnements erneuern?

Graph-Kalender-Webhooks laufen nach wenigen Stunden ab. Planen Sie daher einen Hintergrund-Job ein, der jedes bald auslaufende Abonnement rechtzeitig erneuert.

Unterstützt die Outlook Calendar API Push-Benachrichtigungen?

Ja. Erstellen Sie ein Microsoft Graph-Abonnement, dann erhalten Sie Änderungsbenachrichtigungen und müssen kein Polling betreiben.

Gibt es einen einfacheren Weg, Outlook-, Google- und iCloud-Kalender zu integrieren?

Ja. Eine Unified Calendar API wie Apiroc fasst alle großen Anbieter hinter einer einheitlichen JSON-Schnittstelle zusammen. Mit der Apiroc Unified Calendar API müssen Sie nicht für jeden Kalenderanbieter eine eigene Integration entwickeln und pflegen.