So integrieren Sie die Google Calendar API in Ihre App

Veröffentlicht am

In diesem Leitfaden erklären wir Schritt für Schritt, wie Sie die Google-Calendar-API in Ihre App integrieren. Wir behandeln die Einrichtung des Google-Cloud-Projekts, die benötigten Scopes, typische Stolperfallen und ein praktisches Beispiel für den Autorisierungsablauf.

Voraussetzungen

Sie benötigen eine E-Mail-Adresse, eine Domain, die Sie bei der Einrichtung des Google-Cloud-Projekts verwenden können, etwas Programmiererfahrung und eine ungefähre Vorstellung davon, was Sie bauen möchten.

Der Leitfaden ist auch nützlich, wenn Sie noch nie mit der Google-Calendar-API gearbeitet haben und jeden Schritt verstehen wollen, der für die Integration nötig ist.

So nutzen und integrieren Sie die Google-Calendar-API in Ihre App

1. Registrieren Sie sich in der Google Developer Console

Falls Sie noch kein Konto in der Google Developer Console haben, erstellen Sie eines unter https://console.cloud.google.com/.

2. Erstellen Sie ein neues oder wählen Sie ein bestehendes Google-Cloud-Projekt

In Google Cloud können Entwickler und Organisationen mehrere Projekte anlegen. Stellen Sie sicher, dass Sie sich bei den folgenden Schritten im richtigen Projekt befinden.

Klicken Sie oben links auf den Projekt-Drop-down. Der Name entspricht üblicherweise dem Projektnamen.

Google Cloud Home

Wählen Sie ein bestehendes Projekt oder klicken Sie auf „Neues Projekt“ oben rechts im Dialog, um ein neues anzulegen.

Google Cloud - Select Project

3. Aktivieren Sie die Google-Calendar-API-Dienste

Nachdem Sie ein Konto erstellt und das richtige Projekt ausgewählt haben, aktivieren Sie die Google-Calendar-API:

  1. Öffnen Sie die Google Cloud Console
  2. Klicken Sie auf „APIs & Dienste“ Google Cloud - Click APIs and Services
  3. Klicken Sie auf „APIs und Dienste aktivieren“ Google Cloud - Enable APIs and services
  4. Suchen Sie nach „Google Calendar API“ Search for Google Calendar API service
  5. Klicken Sie auf „Aktivieren“, um den Dienst freizuschalten. Enable Google Calendar API service

4. Richten Sie den OAuth-Zustimmungsbildschirm ein

Nachdem die API-Dienste aktiviert sind, richten Sie als Nächstes den OAuth-Zustimmungsbildschirm ein. Das ist der Bildschirm, den Endnutzer sehen, wenn sie ihren Kalender mit Ihrer App verbinden. Er zeigt unter anderem Ihr App-Logo, den App-Namen und die angeforderten Berechtigungen.

  1. Klicken Sie auf den Tab „OAuth-Zustimmungsbildschirm“. Click OAuth Consent Screen
  2. Klicken Sie auf „Los geht’s“. Click Get Started
  3. Füllen Sie den Abschnitt „App-Informationen“ aus. Geben Sie Ihren App-Namen und eine Support-E-Mail-Adresse an. Fill in the “App Information” section
  4. Wählen Sie die Zielgruppe. Intern, wenn die App nicht öffentlich ist und nur Personen Ihrer Organisation sich verbinden dürfen, oder extern, wenn beliebige Google-Konten zugreifen sollen. Choose the audience
  5. Geben Sie Ihre Kontaktinformationen an. Google informiert Sie bei Änderungen am Projekt. How to Integrate Google Calendar API Into Your App
  6. Aktivieren Sie das Kontrollkästchen „Google API Services: User Data Policy akzeptieren“. Check the Agree to the Google API Services
  7. Klicken Sie auf „Erstellen“ . Click “Create”

5. Erstellen Sie Ihren OAuth-Client

Sobald der Zustimmungsbildschirm eingerichtet ist, können Sie den OAuth-Client für Ihr Projekt anlegen. Klicken Sie im Tab „Clients“ auf „Client erstellen“ oder alternativ auf „OAuth-Client erstellen“ auf der Übersichtsseite.

Create OAuth Client

Für jede Plattform, auf der Ihre App läuft (z. B. Web-App und iOS-App), brauchen Sie eine eigene OAuth-Client-ID.

Google Cloud - Client Options

In diesem Beispiel erstellen wir einen „Webanwendung“-Client namens „Web Client“.

Google Cloud - Web Client

Hier tragen wir auch die autorisierten JavaScript-Ursprünge und Redirect-URIs ein.

Bei Autorisierten JavaScript-Ursprüngen geben Sie die Domain/URL Ihrer Web-App an, zum Beispiel: myapp.domain.com

Google Cloud - Authorized Domains

Unter Autorisierte Redirect-URIs tragen Sie alle URLs ein, zu denen Nutzer nach der Authentifizierung bei Google zurückgeleitet werden. Google hängt den Autorisierungscode an diese URL an, und die URL muss ein Protokoll enthalten.

Google Cloud - Setup Redirect URL

Nach dem Ausfüllen der Felder klicken Sie auf „Erstellen“. Google öffnet dann ein Dialogfenster mit der Client-ID und dem Client-Secret. Kopieren Sie beide Werte und bewahren Sie sie sicher auf (meist in Ihrer .env-Datei, da wir sie im Authentifizierungsablauf weiter unten verwenden). Sie können auch die JSON-Datei herunterladen und in einem Passwortmanager wie 1Password ablegen.

OAuth Client Created - Modal

6. Fügen Sie Testnutzer hinzu

Während der lokalen Entwicklung können nur freigegebene Testnutzer ihr Google-Calendar-Konto verbinden. Der Grund ist, dass Ihre App extern ist und noch nicht von Google verifiziert wurde.

So fügen Sie Testnutzer hinzu:

  1. Klicken Sie auf den Tab „Zielgruppe“. Google Cloud - Audience Tab
  2. Scrollen Sie zum Abschnitt „Testnutzer“. Test Users Section
  3. Klicken Sie auf „Nutzer hinzufügen“ und tragen Sie die E-Mail-Adresse ein. Add Test users by email

7. Fügen Sie die benötigten Kalender-Scopes hinzu

Welche Scopes Sie anfordern, hängt von Ihrem Anwendungsfall ab. Scopes sind Berechtigungen, die Sie von Nutzern anfordern, damit Ihre App auf private Daten ihres Google-Kontos zugreifen darf. Beispiele sind das Auflisten von Kalendern oder das Lesen von Kalender-Events.

Google unterscheidet zwischen sensiblen und nicht sensiblen Scopes. Wenn Sie sensible Scopes hinzufügen, muss Ihre App verifiziert werden. Das gilt auch, wenn Ihre App bereits verifiziert ist und Sie weitere sensible Scopes ergänzen.

So verwalten Sie Scopes:

  1. Klicken Sie auf den Tab „Datenzugriff“. Data Access Tab
  2. Klicken Sie auf „Scopes hinzufügen oder entfernen“. Add Or Remove Scopes Button
  3. Suchen und wählen Sie den gewünschten Scope aus. Select Scopes Section

8. Machen Sie sich mit der Google-Calendar-API vertraut

Jetzt, da der Google-Client eingerichtet ist und Nutzer ihre Kalender verbinden können, sollten Sie sich mit der Google-Calendar-API selbst vertraut machen. Wir empfehlen, die Übersichtsseite der Google-Calendar-API durchzugehen und sich die wichtigsten Endpunkte wie Events und Calendars anzusehen.

9. Nutzen Sie eine Einheitliche Kalender-API, um mehrere Anbieter über eine Schnittstelle einzubinden

Wenn Sie nur Google Calendar integrieren möchten, können Sie diesen Schritt überspringen. Andernfalls empfehlen wir eine Einheitliche Kalender-API, die Ihnen eine einzige API für alle Kalenderanbieter bietet.

Mit einer einheitlichen Kalender-API bauen und pflegen Sie nur eine Integration für alle Anbieter. Wenn Sie später Outlook oder iCloud unterstützen möchten, können Sie diese hinzufügen, ohne eine neue Integration zu schreiben.

Außerdem müssen Sie keine mehreren Integrationen warten, sich nicht mit Breaking Changes beschäftigen und nicht die Details jeder einzelnen Anbieter-API lernen.

Beispiel für einen Google-Calendar-Autorisierungsablauf

Die folgende Grafik zeigt einen einfachen OAuth-Flow, über den Nutzer ihren Google Calendar mit Ihrer App verbinden.

Google Calendar OAuth flow

Google bietet Client-Bibliotheken für Node.js, Python und weitere Sprachen an. Der Einfachheit halber verwenden wir hier nur einfache HTTP-Aufrufe und TypeScript.

Client-Seite (UI)

Der erste Teil ist die Client-Seite (UI). Dort zeigen wir einen Button „Google Calendar verbinden“ an:

const googleOauthUrl = getGoogleOAuthUrl()
<button href="googleOauthUrl"   rel="noopener noreferrer"> Connect Google Calendar </button>

Wir empfehlen eine Hilfsfunktion wie getGoogleOAuthUrl. Sie hält den Code lesbar und macht es einfach, Parameter wie den Client-State oder eine erzwungene Zustimmung zu übergeben.


const SCOPES = [
  "openid",
  "email",
  "<https://www.googleapis.com/auth/calendar.calendarlist>",
  "<https://www.googleapis.com/auth/calendar.events>",
  "<https://www.googleapis.com/auth/calendar.readonly>",
  // add more scopes as needed
];

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

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

export function getGoogleOAuthUrl(
  state: ClientState,
) {
  const params = new URLSearchParams({
    client_id: process.env.GOOGLE_CLIENT_ID || "",
    redirect_uri: `${getHostName()}/api/connect/google`, // change the redirect URL as needed
    response_type: "code",
    scope: SCOPES.join(" "),
    prompt: "consent",
    access_type: "offline",
    state: stateToB64(state),
  });
  return `https://accounts.google.com/o/oauth2/v2/auth?${params}`;
}

Der Parameter prompt kann einen von drei Werten haben: none, consent oder select_account.

Der Wert consent ist nützlich, wenn ein Nutzer seine Kalender bereits autorisiert hat, Google den Autorisierungsbildschirm aber trotzdem erneut anzeigen soll. Das ist zum Beispiel der Fall, wenn Sie neue Scopes zu Ihrer App hinzufügen und die Nutzer diese bestätigen sollen.

Ein weiterer Fall für consent ist, wenn der Nutzer nicht alle Scopes gewährt hat, die Ihre App benötigt, und Sie sie erneut anfordern möchten.

Der Wert select_account fordert den Nutzer auf, ein Konto auszuwählen.

Der Wert none zeigt keinen Authentifizierungs- oder Zustimmungsbildschirm an.

API-Seite (Backend)

Als Nächstes bauen wir den API-Handler. Er nimmt den Code und die Scopes von Google entgegen und tauscht den Code gegen Tokens. In diesem Beispiel verwenden wir zod zur Validierung.

import { z } from "zod";
const successSchema = z.object({
  code: z.string(),
  scope: z.string(),
  state: z.string(),
});

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

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

// Handler
const googleHanlder: NextApiHandler = async (req, res) => {
  try {
    const result = querySchema.parse(req.query);
    if (isError(result)) {
      const q = new URLSearchParams({
        error: "ACCESS_DENIED",
      });
      return res.redirect(`/?${q}`);
    }

    const { session, returnUr } = stateFromB64(
      result.state
    );

    if (!hasRequiredScopes(result.scope)) {
      const q = new URLSearchParams({
        error: "MISSING_REQUIRED_PERMISSIONS",
      });
      return res.redirect(`/?${q}`);
    }

    const { access_token, refresh_token, id_token, expires_in } =
      await exchangeCodeForTokens(result.code);
    const { email } = decodeIdToken(id_token);

		// Update or insert the calendar connection, depending on your use case
    const connection = await upsertConnection(
      {
        email,
        accessToken: access_token,
        refreshToken: refresh_token,
        expiresInSeconds: expires_in,
        status: ConnectionStatus.ACTIVE,
        provider: CalendarProvider.GOOGLE,
        scopes: result.scope,
        reminderCount: 0,
        lastRemindedAt: null,
      },
      session.user
    );

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

		// The API redirects back to the client side, returning the connection, or errors if any 
    res.redirect returnUrl ? returnUrl : `/calendars/google?${q}`
    );
  } catch (e: any) {
    let error = JSON.stringify(e);

      const querystr =
        typeof req.query === "string" ? req.query : JSON.stringify(req.query);
      console.error("Error in googleHandler", querystr);
      console.error("Failed to connect Google account", e);

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

Wie auf der Client-Seite empfehlen wir kleine Hilfsfunktionen, etwa exchangeCodeForTokens, decodeIdToken und stateFromB64:

export async function exchangeCodeForTokens(code: string) {
  const data = new FormData();
  data.append("code", code);
  data.append("client_id", process.env.GOOGLE_CLIENT_ID || "");
  data.append("client_secret", process.env.GOOGLE_CLIENT_SECRET || "");
  data.append("redirect_uri", `${getHostName()}/api/connect/google`); // your URL
  data.append("grant_type", "authorization_code");

  try {
    const result = await fetch("<https://oauth2.googleapis.com/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;
  }
}

export function decodeIdToken(idToken: string) {
  const data = jwt.decode(idToken);
  if (typeof data === "string" || !data?.email) {
    throw new Error(`Could not parse id_token: ${idToken}`);
  }

  return data;
}

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

export function stateFromB64(encoded: string): ClientState {
  const str = decode(encoded);

  return JSON.parse(str) as ClientState;
}

Stolperfallen bei der Google-Calendar-API-Integration

  • Die Verifizierung kann mehrere Wochen dauern. Planen Sie den Launch entsprechend und rechnen Sie damit, dass die erste Einreichung abgelehnt wird. Informieren Sie alle Beteiligten über diese mögliche Verzögerung.
  • Webhooks laufen nach etwa 24 Stunden ab. Erneuern Sie sie rechtzeitig, zum Beispiel mit einem Cron-Job, der Webhooks findet, die in den nächsten 20 Minuten ablaufen.
  • Fordern Sie nur die Scopes an, die Sie wirklich brauchen. Zu viele Scopes führen zu Ablehnungen bei der Verifizierung und schrecken Nutzer ab, wenn die Berechtigungen nicht zum Zweck der App passen.
  • Berücksichtigen Sie Quoten und Ratenlimits. Google hat eine Quote pro Minute und Projekt sowie eine Quote pro Minute, Projekt und Nutzer. Bei Überschreitung erhalten Sie 403 usageLimits oder 429 rateLimitExceeded. Nutzen Sie Exponential Backoff.
  • Loggen Sie keine personenbezogenen Daten. Loggen ist in Ordnung, aber entfernen Sie vorher persönliche Eventdaten wie Beschreibungen und E-Mail-Adressen von Teilnehmern.

Mehrere Kalenderanbieter integrieren mit der Apiroc Einheitlichen Kalender-API

Unser Team arbeitet seit Jahren mit Google Calendar, Outlook und iCloud Calendar und hat Kalenderintegrationen gebaut, die Milliarden von API-Aufrufen verarbeiten. Wir wissen, was es bedeutet, mehrere Anbieter zu integrieren, die Details jeder API zu lernen und jede Implementierung zuverlässig am Laufen zu halten.

Deshalb haben wir Apiroc gebaut, eine Einheitliche Kalender-API, die Google Calendar, Microsoft Outlook und iCloud Calendar von Haus aus unterstützt. So binden Sie alle großen Anbieter über eine einzige robuste und einfach nutzbare API an.

Sie können kostenlos starten, die API mit bis zu 10 End User Accounts testen, die Funktionen kennenlernen und später upgraden, wenn Sie mehr brauchen. Eine Kreditkarte ist nicht erforderlich.

Häufig gestellte Fragen

Warum muss ich Testbenutzer hinzufügen?

Eine nicht verifizierte externe App kann nur von freigegebenen Testkonten genutzt werden, solange Sie die App entwickeln und Google sie noch nicht genehmigt hat.

Wie lange bleiben Google-Kalender-Webhooks aktiv?

Abonnements für Push-Benachrichtigungen laufen nach etwa 24 Stunden ab. Ihr Backend sollte sie deshalb erneuern, bevor sie ungültig werden.

Gibt es später eine einfachere Möglichkeit, Outlook- oder iCloud-Kalender hinzuzufügen?

Ja. Eine einheitliche Kalender-API wie Apiroc integriert Google, Outlook und iCloud über eine einzige API. Das spart Ihnen Zeit und Kosten für separate Integrationen und deren Wartung.

Benötige ich „offline_access“ für Hintergrundjobs?

Ja. Wenn Sie access_type=offline in die Consent-URL aufnehmen, gibt Google ein Refresh-Token zurück. Damit kann Ihr Server die API auch dann aufrufen, wenn der Nutzer nicht aktiv ist.