Authentication
Authentication is configured through the auth field of the client config. It is a discriminated union — type picks the strategy, and the rest of the fields follow from it.
| Method | Use when | auth.type |
|---|---|---|
| Email + API token | Scripts, backends, personal automations | 'basic' |
| Bearer token | You already hold an access token and manage it yourself | 'bearer' |
| OAuth 2.0 (3LO) | Apps acting on behalf of users | 'oauth2' |
Self-hosted Jira takes a different set — a personal access token, a username and password, or its own OAuth 2.0 provider. See Jira Data Center.
JWT (Atlassian Connect) is not supported
6.0 dropped it, and there is no replacement. If you authenticate Connect installations with a shared secret, stay on jira.js@5 — see Migrating to 6.0.
Email + API token
The simplest method. Generate a token at id.atlassian.com/manage-profile/security/api-tokens.
import { createCloudClient } from 'jira.js';
const jira = createCloudClient({
host: 'https://your-domain.atlassian.net',
auth: {
type: 'basic',
email: 'email@example.com',
apiToken: 'YOUR_API_TOKEN',
},
});Bearer token
When something else already obtained an access token and you want the client to send it as-is:
const jira = createCloudClient({
host: 'https://your-domain.atlassian.net',
auth: { type: 'bearer', token: accessToken },
});Nothing is refreshed for you here. When the token expires, requests start failing with AuthError — use the OAuth 2.0 strategy if you want that handled.
OAuth 2.0 (3LO)
Hand over app credentials and a refresh token, and the client refreshes the access token before it expires, retries once on a 401, resolves the cloud id and routes through Atlassian's gateway. See the dedicated OAuth 2.0 guide.
const jira = createCloudClient({
auth: {
type: 'oauth2',
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET!,
refreshToken: storedRefreshToken,
onTokenRefresh: ({ refreshToken }) => tokenStore.save(refreshToken),
},
});host is optional here and ignored: 3LO tokens are not accepted on the site's own domain, so the client derives https://api.atlassian.com/ex/jira/{cloudId} itself.
Persisting the rotated refresh token is not optional. Atlassian invalidates the previous one on every refresh, so a process that forgets it will fail to authenticate after restart.
Rotating credentials at runtime
getAuthOn401 is called when a request comes back unauthorized, so a long-lived process can swap in fresh credentials without being rebuilt:
const jira = createCloudClient({
host,
auth,
getAuthOn401: async () => ({ type: 'basic', email, apiToken: await vault.currentToken() }),
});