Skip to content

Integrate a custom identity provider with Nylas Connect

Nylas Connect works with any identity provider that issues JWTs (JSON Web Tokens) and exposes a JWKS (JSON Web Key Set) endpoint. This means you can use open-source solutions like Keycloak or Ory, cloud services like Firebase Auth or Supabase Auth, or even your own custom JWT server.

If your identity provider isn’t Auth0, Clerk, Google, or WorkOS, this is the guide for you.

When you configure a custom identity provider, Nylas uses JWKS to verify the tokens your IDP issues:

  1. Your IDP signs JWTs with a private key.
  2. Your IDP exposes a JWKS endpoint (a public URL that serves the corresponding public keys).
  3. When Nylas receives a request with your IDP token, it fetches the public keys from your JWKS endpoint and verifies the token signature.

This means Nylas never needs your IDP’s private keys. It only needs the JWKS URL to verify that tokens are legitimate.

You need an identity provider with JWKS support 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

In addition to the standard Nylas Dashboard setup, you need to provide your JWKS endpoint URL:

  1. In the Nylas Dashboard, go to Hosted AuthenticationIdentity Providers.
  2. Enter your IDP’s JWKS URI (e.g., https://your-idp.com/.well-known/jwks.json).
  3. Save the configuration.

Your identity provider’s JWKS endpoint must:

  • Be publicly accessible over HTTPS (Nylas needs to fetch keys at runtime)
  • Serve a valid JWKS JSON document with RSA or EC public keys
  • Include the kid (key ID) header in issued JWTs that matches a key in the JWKS response
  • Issue JWTs with a sub claim that uniquely identifies the user

Common JWKS endpoint paths by provider:

ProviderJWKS endpoint
Keycloakhttps://<host>/realms/<realm>/protocol/openid-connect/certs
Ory / Hydrahttps://<host>/.well-known/jwks.json
Firebase Authhttps://www.googleapis.com/service_accounts/v1/jwk/[email protected]
Supabase Authhttps://<project-ref>.supabase.co/auth/v1/.well-known/jwks.json
Custom serverTypically https://your-domain.com/.well-known/jwks.json

The pattern is the same as any other IDP integration: pass your token to Nylas Connect through the identityProviderToken callback. The specifics of how you obtain the token depend on your IDP.

Here’s a generic example assuming your IDP provides a getToken() method:

import { NylasConnect } from "@nylas/connect";
async function getIdpToken(): Promise<string | null> {
// Replace this with your IDP's token retrieval method.
// Examples:
// Keycloak: keycloak.token
// Firebase: await firebase.auth().currentUser.getIdToken()
// Supabase: (await supabase.auth.getSession()).data.session?.access_token
// Custom: await fetch("/api/auth/token").then(r => r.json()).then(d => d.token)
return null;
}
const nylasConnect = new NylasConnect({
clientId: "<NYLAS_CLIENT_ID>",
redirectUri: "http://localhost:3000/auth/callback",
identityProviderToken: async () => {
try {
return await getIdpToken();
} catch (error) {
console.error("Failed to get IDP token:", error);
return null;
}
}
});
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();
// Also sign out from your IDP
}
import Keycloak from "keycloak-js";
import { NylasConnect } from "@nylas/connect";
const keycloak = new Keycloak({
url: "https://your-keycloak-server.com",
realm: "<REALM_NAME>",
clientId: "<KEYCLOAK_CLIENT_ID>"
});
await keycloak.init({ onLoad: "login-required" });
const nylasConnect = new NylasConnect({
clientId: "<NYLAS_CLIENT_ID>",
redirectUri: "http://localhost:3000/auth/callback",
identityProviderToken: async () => {
await keycloak.updateToken(30);
return keycloak.token || null;
}
});
import { getAuth } from "firebase/auth";
import { NylasConnect } from "@nylas/connect";
const auth = getAuth();
const nylasConnect = new NylasConnect({
clientId: "<NYLAS_CLIENT_ID>",
redirectUri: "http://localhost:3000/auth/callback",
identityProviderToken: async () => {
const user = auth.currentUser;
if (!user) return null;
return await user.getIdToken();
}
});

After the user authenticates with your IDP and connects their email, use the IDP token to make Nylas API requests. The pattern is the same as other providers: pass the token as a Bearer token and include the X-Nylas-External-User-Id header with the user’s sub claim:

function parseSubFromJwt(token: string): string | null {
try {
const base64Payload = token.split(".")[1];
const payload = JSON.parse(atob(base64Payload));
return payload?.sub || null;
} catch {
return null;
}
}
async function fetchEmails() {
const token = await getIdpToken();
const userId = parseSubFromJwt(token || "");
const response = await fetch(
`https://api.us.nylas.com/v3/grants/me/messages`,
{
headers: {
Authorization: `Bearer ${token}`,
"X-Nylas-External-User-Id": userId || ""
}
}
);
return await response.json();
}

Use https://api.us.nylas.com for US-hosted applications or https://api.eu.nylas.com for EU-hosted applications.

ProblemCauseSolution
401 Unauthorized on API callsNylas can’t verify the tokenConfirm your JWKS URI is correct and publicly accessible. Check that the kid in your JWT header matches a key in the JWKS response.
Token verification failsKey mismatchEnsure your IDP is using the same key pair for signing tokens as the one published at the JWKS endpoint.
sub claim missingToken format issueCheck that your IDP includes a sub claim in the JWT payload. Some IDPs use custom claim names.
JWKS endpoint unreachableNetwork or CORS issueThe JWKS endpoint must be publicly accessible over HTTPS. It doesn’t need CORS headers because Nylas fetches it server-side.