# How to use OAuth for Google Calendar

Source: https://developer.nylas.com/docs/cookbook/calendar/google-calendar-oauth/

If your app reads or writes a user's Google Calendar, OAuth is the permission boundary. The user authorizes your app, Google returns a code, and your server turns that into long-lived access. The native Google Calendar API makes you own the full OAuth flow, token refresh, scope review, and quota behavior.

Nylas hosted OAuth gives you the same user-consent model, but your app stores a `grant_id` instead of provider tokens. Nylas handles the Google token lifecycle behind that grant, and the same pattern works later if you add Microsoft, iCloud, or Exchange calendars.

## Choose Google Calendar scopes

Google scopes are full URI strings. Request the smallest set that matches your feature because broader scopes add friction on the consent screen and can lengthen Google's verification review.

| Task | Google scope |
| --- | --- |
| List calendars or check Free/Busy | `https://www.googleapis.com/auth/calendar.readonly` |
| Read events | `https://www.googleapis.com/auth/calendar.events.readonly` |
| Create, update, delete, or respond to event invitations | `https://www.googleapis.com/auth/calendar.events` |
| Manage calendars and events | `https://www.googleapis.com/auth/calendar` |

The [granular scopes reference](/docs/dev-guide/scopes/) lists the exact scope for every Nylas calendar endpoint. Google classifies Calendar scopes as sensitive, so production apps need Google OAuth verification. If you request Gmail restricted scopes in the same connector, you may also need a security assessment.

## Start the hosted OAuth flow

Send the user to `/v3/connect/auth` with your Nylas client ID, callback URI, provider, and state value. Set `provider=google` so the flow opens the Google consent screen.

```bash
https://api.us.nylas.com/v3/connect/auth?
  client_id=<NYLAS_CLIENT_ID>
  &redirect_uri=https://app.example.com/oauth/callback
  &response_type=code
  &provider=google
  &state=<SIGNED_USER_STATE>
```

Use `state` to bind the callback to the user who clicked Connect. Store a signed nonce or session ID, not a raw user ID by itself. When Google redirects back, check `state` before exchanging the code.

The Node.js SDK can build the URL:

```js [googleCalendarOAuth-Node.js SDK]
const authUrl = nylas.auth.urlForOAuth2({
  clientId: process.env.NYLAS_CLIENT_ID,
  provider: "google",
  redirectUri: "https://app.example.com/oauth/callback",
  loginHint: user.email,
  state: signedState,
});

res.redirect(authUrl);
```

## Exchange the code for a grant

After the user approves access, Google redirects to your callback with a `code`. Exchange it with Nylas to create the grant.

```bash
curl --request POST \
  --url 'https://api.us.nylas.com/v3/connect/token' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "client_id": "<NYLAS_CLIENT_ID>",
    "redirect_uri": "https://app.example.com/oauth/callback",
    "code": "<OAUTH_CODE>",
    "grant_type": "authorization_code"
  }'
```

The response includes a grant ID. Save that ID on your user or workspace record:

```json
{
  "grant_id": "<NYLAS_GRANT_ID>",
  "provider": "google",
  "email": "maya@example.com"
}
```

Use the grant ID for Calendar API calls. Your server authenticates with your Nylas API key, while the grant tells Nylas which Google Calendar account to act on.

```bash
curl --request GET \
  --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/events?calendar_id=primary' \
  --header 'Authorization: Bearer <NYLAS_API_KEY>'
```

## Handle token refresh and re-authentication

Nylas refreshes the underlying Google access token for the grant, so your app doesn't run a refresh-token job. A grant can still expire if the user revokes access, changes a password, or an admin policy invalidates tokens.

Subscribe to the `grant.expired` webhook and handle `401` responses on API calls. When a grant expires, send the user through hosted OAuth again. Re-authentication keeps the same account relationship and avoids losing your local sync mappings.

## Fix common Google Calendar OAuth errors

| Error or symptom | Likely cause | Fix |
| --- | --- | --- |
| `redirect_uri_mismatch` | Callback URI differs from the registered URI | Match the URI exactly in Google, your Nylas app, and the auth request |
| Unverified app warning | Google OAuth consent screen isn't verified | Add test users for development or complete Google verification |
| `403` after a successful connection | Connector requested read-only scope but your app calls a write endpoint | Add `calendar.events` or `calendar`, then re-authenticate the grant |
| User sees the wrong Google account | Browser session picked an existing login | Pass `login_hint` and let the user choose the correct account |
| Grant later expires | User or admin revoked provider access | Re-authenticate the same grant and listen for `grant.expired` |

The broader [OAuth troubleshooting guide](/docs/cookbook/use-cases/build/troubleshoot-oauth-errors/) covers Microsoft errors and token-level failures too.

## Things to know about Google Calendar OAuth

**Calendar scopes are separate from Gmail scopes.** Connecting Gmail doesn't automatically grant calendar access. Add the calendar scope before the user authenticates.

**Use `calendar.events.readonly` when you only display events.** Don't request write scopes until your app creates, updates, deletes, or responds to event invitations.

**Use service accounts only for Workspace-wide calendar access.** Per-user SaaS apps usually use hosted OAuth. Google Workspace service accounts are a separate admin-controlled model, and they support Google Calendar only.

**Keep the API key server-side.** Browser code can start OAuth, but Calendar API requests with your Nylas API key should happen from your server.

## What's next

- [Connect user accounts with OAuth](/docs/cookbook/use-cases/build/connect-user-accounts-oauth/) for the provider-agnostic OAuth flow
- [OAuth scopes for email and calendar](/docs/cookbook/use-cases/build/oauth-scopes-email-calendar/) for Google and Microsoft scope sets
- [Google provider guide](/docs/provider-guides/google/) for connector setup and consent-screen requirements
- [Google verification and security assessment](/docs/provider-guides/google/google-verification-security-assessment-guide/) for production approval
- [Create Google calendar events](/docs/cookbook/calendar/events/create-events-google/) after you connect the grant