Skip to content
Skip to main content

Integrate Clerk with @nylas/connect

Last updated:

Clerk is a modern authentication platform with prebuilt UI components, session management, and multi-factor authentication. This guide shows you how to use Clerk as your identity provider with @nylas/connect so your users can authenticate with Clerk and connect their email accounts through Nylas.

You need a Clerk application 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 your Clerk Dashboard, navigate to your application.
  2. Go to ConfigurePaths.
  3. Configure the following settings:
    • Sign-in URL: Set to your application’s sign-in page (e.g., /sign-in)
    • Sign-up URL: Set to your application’s sign-up page (e.g., /sign-up)
    • After sign-in URL: Set to where users should land after signing in (e.g., /)
    • After sign-up URL: Set to where users should land after signing up (e.g., /)
  4. In Domains, add your application’s domain (e.g., localhost:3000 for development, yourapp.com for production)
npm install @nylas/connect @clerk/clerk-js

Initialize Clerk and @nylas/connect together. The identityProviderToken callback retrieves the current session token from Clerk and passes it to @nylas/connect:

import { NylasConnect } from "@nylas/connect";
import Clerk from "@clerk/clerk-js";
const clerk = new Clerk("<CLERK_PUBLISHABLE_KEY>");
async function initializeClerk() {
await clerk.load();
}
const nylasConnect = new NylasConnect({
clientId: "<NYLAS_CLIENT_ID>",
redirectUri: "http://localhost:3000/auth/callback",
identityProviderToken: async () => {
try {
const token = await clerk.session?.getToken();
return token || null;
} catch (error) {
console.error("Failed to get Clerk token:", error);
return null;
}
},
});
async function loginWithClerk() {
await clerk.openSignIn();
}
async function connectEmail() {
try {
const result = await nylasConnect.connect({ method: "popup" });
console.log("Email connected:", result.grantInfo?.email);
} catch (error) {
console.error("Failed to connect email:", error);
}
}
async function logout() {
await nylasConnect.logout();
await clerk.signOut();
}

Once the user has connected a mailbox, call the API with the Clerk session token. Clerk’s user ID is the sub claim in the session token, so read it from clerk.user instead of decoding the JWT.

async function fetchEmails() {
const token = await clerk.session?.getToken();
const response = await fetch(
"https://api.us.nylas.com/v3/grants/me/messages",
{
headers: {
Authorization: `Bearer ${token}`,
"X-Nylas-External-User-Id": clerk.user?.id ?? "",
},
},
);
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.