Authenticate with Glean from the command line or JavaScript, with tenant discovery, OAuth login, and automatic token refresh.
Requires Node.js 22.12.0 or newer.
npm install @gleanwork/authThe JavaScript API is ESM-only.
Sign in with your work email and request the scopes your application needs:
npx glean-auth login --email you@example.com --scopes searchPrint the current token for a shell command or non-JavaScript application:
export GLEAN_API_TOKEN="$(
npx glean-auth token --email you@example.com --scopes search
)"You can also run the CLI without installing it in a project:
npx -y @gleanwork/auth login --email you@example.com --scopes search| Command | Description |
|---|---|
login |
Sign in with OAuth and save credentials. |
status |
Show local authentication status without printing credentials. |
token |
Print the current access token. |
logout |
Remove the matching saved OAuth credentials. |
npx glean-auth status --email you@example.com --scopes search
npx glean-auth status --email you@example.com --scopes search --json
npx glean-auth token --email you@example.com --scopes search
npx glean-auth logout --email you@example.com --scopes searchtoken prints only the token and a trailing newline to stdout. It does not start an interactive login. Run login first or set GLEAN_API_TOKEN.
| Option | Description |
|---|---|
--email <address> |
Discover the Glean tenant associated with an email address. |
--server-url <url> |
Use the complete Glean backend origin instead of tenant discovery. |
--scopes <scope,...> |
Request OAuth scopes. Repeatable; preserves scope casing. |
Use lowercase scope names such as search, chat, or mcp. Glean can return lowercase Client API scope grants when a request uses enum-style uppercase names. This package compares those grant names case-insensitively and still requires every requested scope.
Scope casing remains part of the saved state identity. Use the same casing for login, status, token, logout, and the JavaScript provider. Changing casing (for example, SKILLS to skills) requires a separate login for that scope identity; this package does not migrate or merge existing state.
Run npx glean-auth --help for shared options and the command list. Run npx glean-auth <command> --help for command-specific options.
OAuth is the recommended authentication method. login uses Authorization Code with PKCE and opens a browser for approval. If the tenant permits Dynamic Client Registration, the CLI registers a client automatically. Set GLEAN_OAUTH_CLIENT_ID when an administrator has provisioned a public OAuth client instead.
For CI or another non-interactive environment, set a user-scoped API token and the Glean backend URL:
export GLEAN_SERVER_URL=https://your-company-be.glean.com
export GLEAN_API_TOKEN=your-api-tokenA non-empty GLEAN_API_TOKEN takes precedence when the package retrieves a token. The package does not validate the scopes or expiration of an API token.
The CLI chooses a tenant in this order:
--server-url--emailGLEAN_SERVER_URL
OAuth always requests openid and offline_access in addition to the scopes passed through --scopes. A saved OAuth grant is reused only when it includes every requested scope.
The package exports two runtime functions and their supporting TypeScript types.
import { createGleanTokenProvider, discoverGleanTenant } from "@gleanwork/auth";
const tenant = await discoverGleanTenant("you@example.com");
const getAccessToken = createGleanTokenProvider({
serverUrl: tenant.serverUrl,
scopes: ["search"],
});
const token = await getAccessToken();discoverGleanTenant(email) returns the authoritative backend origin and a display identity for the tenant associated with an email address. Canonical *-be.glean.com and custom vanity backend origins are preserved exactly.
When using --server-url or GLEAN_SERVER_URL, pass the complete backend origin shown under Server instance (QE) on the Glean About page. Do not pass the Glean web app URL or derive a backend hostname from it.
createGleanTokenProvider(options) returns a non-interactive () => Promise<string> callback. It uses GLEAN_API_TOKEN when set. Otherwise, it reuses or refreshes credentials created by glean-auth login.
The callback can be passed directly to the Glean TypeScript SDK:
import { Glean } from "@gleanwork/api-client";
import { createGleanTokenProvider } from "@gleanwork/auth";
const glean = new Glean({
serverURL: "https://your-company-be.glean.com",
apiToken: createGleanTokenProvider({
serverUrl: "https://your-company-be.glean.com",
scopes: ["search"],
}),
});The CLI stores OAuth credentials under $XDG_STATE_HOME/glean-auth when XDG_STATE_HOME is an absolute path. Otherwise, it uses ~/.local/state/glean-auth.
On Unix, state directories use mode 0700 and credential files use mode 0600. The package does not read or write project .env files. status never prints tokens; token intentionally writes a token to stdout for scripts and pipelines.
See CONTRIBUTING.md for development setup and quality checks.
MIT, see LICENSE.