node-salesforce-jwt
raw JSON → 1.1.0 verified Sat Apr 25 auth: no javascript maintenance
Minimal implementation of the Salesforce OAuth 2.0 JWT Bearer Token Flow for server-to-server authentication. Version 1.1.0 is the current stable release with no recent updates (low maintenance cadence). Enables impersonating users via a connected app's private key and consumer key. Key differentiator: lightweight (no heavy SDK) and designed to integrate with jsforce by returning access_token and instance_url. No breaking changes reported; simple callback-based API.
Common errors
error Error: unable to get local issuer certificate ↓
cause Missing or outdated root CA certificates in Node.js environment.
fix
Set environment variable NODE_TLS_REJECT_UNAUTHORIZED=0 (not recommended) or update Node.js CA certificate bundle.
error {"error":"invalid_client_id","error_description":"client identifier invalid"} ↓
cause The clientId provided does not match a valid Salesforce Connected App Consumer Key.
fix
Verify the clientId is the Consumer Key from the connected app (not the Consumer Secret) and that the app is properly configured with the correct OAuth scopes.
error Error: PEM_read_bio:no start line ↓
cause The privateKey string does not contain a valid PEM-encoded key (e.g., missing header/footer).
fix
Ensure the private key file is correctly formatted with BEGIN and END RSA PRIVATE KEY lines. Read file with utf8 encoding.
Warnings
breaking The isTest option determines the token endpoint URL: test.salesforce.com vs login.salesforce.com. Incorrect value leads to 404 errors. ↓
fix Set isTest: true for sandbox/test instances, false for production. This is not automatically detected.
gotcha The privateKey must be a string (e.g., read via readFileSync with 'utf8'). Passing a Buffer or file path directly will cause errors. ↓
fix Ensure privateKey is a string: fs.readFileSync('./key.pem', 'utf8')
gotcha The clientId must be the Consumer Key from the connected app, not the Consumer Secret. Mixing them results in authentication failure. ↓
fix Use the Consumer Key (long string ending with .something) from your Salesforce Connected App definition.
Install
npm install node-salesforce-jwt yarn add node-salesforce-jwt pnpm add node-salesforce-jwt Imports
- getToken wrong
import { getToken } from 'node-salesforce-jwt';correctconst nsj = require('node-salesforce-jwt'); nsj.getToken(options, callback); - module.exports wrong
import nsj from 'node-salesforce-jwt';correctconst nsj = require('node-salesforce-jwt');
Quickstart
const nsj = require('node-salesforce-jwt');
const jsforce = require('jsforce');
const fs = require('fs');
const options = {
isTest: true,
clientId: process.env.SF_CONSUMER_KEY ?? '',
privateKey: fs.readFileSync('./private.key', 'utf8'),
user: 'admin@example.com'
};
nsj.getToken(options, (err, response) => {
if (err) { console.error(err); return; }
const conn = new jsforce.Connection();
conn.initialize({
instanceUrl: response.instance_url,
accessToken: response.access_token
});
conn.query('SELECT Id, Name FROM Account LIMIT 1', (err, result) => {
if (err) { console.error(err); return; }
console.log('First record:', result.records[0]);
});
});