Skip to content
Skip to main content

Integrate Google Identity with @nylas/connect

Last updated:

Google Identity Services (GIS) provides OAuth 2.0 authentication for Google accounts. This guide shows you how to use Google as your identity provider with @nylas/connect so your users can sign in with their Google account and connect their email through Nylas.

The Google integration differs slightly from other IdPs because Google Identity Services returns a credential (ID token) directly rather than an access token from an SDK method. You store this credential and pass it to @nylas/connect.

You need a Google Cloud OAuth 2.0 client and a Nylas application configured to work together.

Before connecting your identity provider, configure the IDP settings in the Nylas Dashboard:

  1. Navigate to your application in the Nylas Dashboard.
  2. Go to Hosted AuthenticationIdentity Providers.
  3. Configure the following settings:
    • Allowed Origins: Add the domains where your application will be hosted (e.g., http://localhost:3000, https://yourapp.com). These origins will be allowed to make requests to Nylas with your IDP tokens.
    • Callback URIs: Add the redirect URIs that Nylas will use after authentication (e.g., http://localhost:3000/auth/callback). These must match the redirectUri configured in your NylasConnect instance.

You can access the Identity Provider settings page directly at:

https://dashboard-v3.nylas.com/applications/<YOUR_APP_ID>/hosted-authentication/idp-settings
  1. In the Google Cloud Console, navigate to APIs & ServicesCredentials.
  2. Create or select an OAuth 2.0 Client ID.
  3. Configure the following settings:
    • Application type: Select “Web application”
    • Authorized JavaScript origins: Add your application’s origins (e.g., http://localhost:3000, https://yourapp.com)
    • Authorized redirect URIs: Add your application’s callback URLs (e.g., http://localhost:3000, https://yourapp.com)
  4. Save your Client ID for use in your application.

Add this script tag to your HTML:

<script src="https://accounts.google.com/gsi/client" async defer></script>

No npm package is required for the vanilla JavaScript integration. The library loads from Google’s CDN.

Initialize Google Sign-In and @nylas/connect together. Unlike other IdPs, Google Identity Services provides a credential through a callback rather than an SDK method, so you store it and return it from identityProviderToken:

import { NylasConnect } from "@nylas/connect";
let googleCredential: string | null = null;
function initializeGoogleSignIn() {
google.accounts.id.initialize({
client_id: "<GOOGLE_CLIENT_ID>",
callback: handleGoogleResponse,
});
google.accounts.id.renderButton(
document.getElementById("googleSignInButton"),
{ theme: "outline", size: "large" },
);
}
function handleGoogleResponse(response: any) {
googleCredential = response.credential;
localStorage.setItem("google_credential", googleCredential);
console.log("Google authentication successful");
}
const nylasConnect = new NylasConnect({
clientId: "<NYLAS_CLIENT_ID>",
redirectUri: "http://localhost:3000/auth/callback",
identityProviderToken: async () => {
try {
return localStorage.getItem("google_credential");
} catch {
return null;
}
},
});
async function connectEmail() {
try {
const result = await nylasConnect.connect({
method: "popup",
provider: "google",
});
console.log("Email connected:", result.grantInfo?.email);
} catch (error) {
console.error("Failed to connect email:", error);
}
}
async function logout() {
await nylasConnect.logout();
google.accounts.id.disableAutoSelect();
localStorage.removeItem("google_credential");
googleCredential = null;
}

Google Identity Services returns a signed ID token and no user object, so the sub claim has to come out of the token itself. Decode it base64url-safe: JWT payloads use - and _, which atob() rejects outright, so passing the raw segment straight to atob() throws on a subset of tokens.

function decodeSub(token: string): string {
const part = token.split(".")[1] ?? "";
const base64 = part
.replace(/-/g, "+")
.replace(/_/g, "/")
.padEnd(Math.ceil(part.length / 4) * 4, "=");
return JSON.parse(atob(base64)).sub ?? "";
}
async function fetchEmails() {
const token = localStorage.getItem("google_credential") ?? "";
const response = await fetch(
"https://api.us.nylas.com/v3/grants/me/messages",
{
headers: {
Authorization: `Bearer ${token}`,
"X-Nylas-External-User-Id": decodeSub(token),
},
},
);
return await response.json();
}

Two headers do the work. Authorization carries your identity provider’s access token, and X-Nylas-External-User-Id carries the user’s sub claim, which is the same ID your application already stores. Nylas resolves /v3/grants/me to the mailbox linked to that ID, so no grant_id appears in the request.

The same 2 headers work across the Email, Calendar, and Contacts endpoints. Swap /messages for /events or /contacts and nothing else changes. For how the linkage is established, and when to use it instead of storing grant IDs, see use your own user IDs instead of grant IDs.

Things to know about Google Identity Services

Section titled “Things to know about Google Identity Services”
  • Token type: Google Identity Services returns an ID token (JWT), not an OAuth access token. This token contains user profile claims like sub, email, and name.
  • Token lifetime: Google ID tokens expire after about one hour. The google.accounts.id library does not automatically refresh them. You may need to re-prompt the user or use the google.accounts.id.prompt() method.
  • One Tap sign-in: You can enable Google One Tap for a smoother sign-in experience by calling google.accounts.id.prompt() after initialization.
  • Credential storage: The example above stores the credential in localStorage. For production apps, consider your security requirements around client-side token storage.