From f64ed61868a2f2a8a01f96288fb505355bd4808e Mon Sep 17 00:00:00 2001 From: matthewkmartin Date: Fri, 11 Sep 2026 10:42:02 -0400 Subject: [PATCH 1/2] ONEID-4689 Document OAuth2 client credentials auth and mark it as preferred Co-Authored-By: Claude Sonnet 5 --- README.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/README.md b/README.md index f0b62e1..afbc21b 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,65 @@ numbers.Site.list(function(err, sites){ ``` +## Authentication + +The SDK supports two authentication methods: OAuth2 client credentials (**preferred**) and basic auth (username/password). + +### OAuth2 Client Credentials (Preferred) + +```js +var numbers = require("@bandwidth/numbers"); + +//Using client directly +var client = new numbers.Client("accountId", null, null, "clientId", "clientSecret"); +numbers.Site.list(client, function(err, sites){...}); + +//Or you can use default client instance (do this only once) +numbers.Client.globalOptions.accountId = "accountId"; +numbers.Client.globalOptions.clientId = "clientId"; +numbers.Client.globalOptions.clientSecret = "clientSecret"; + +//Now you can call any functions without first arg 'client' + +numbers.Site.list(function(err, sites){ + //Default client will be used to do this call +}); + +``` + +When `clientId`/`clientSecret` are set, the client automatically fetches and refreshes an OAuth2 access token in the background, and transparently retries a request once if it gets a `401` response. If both OAuth credentials and a username/password are configured, the OAuth bearer token is used. + +To manage the token yourself instead of relying on auto-refresh, pass `{ autoRefreshToken: false }` as the client's `options` argument along with a `tempAccessToken`: + +```js +var client = new numbers.Client("accountId", null, null, "clientId", "clientSecret", { + autoRefreshToken: false, + tempAccessToken: "existingAccessToken" +}); +``` + +### Basic Auth + +```js +var numbers = require("@bandwidth/numbers"); + +//Using client directly +var client = new numbers.Client("accountId", "userName", "password"); +numbers.Site.list(client, function(err, sites){...}); + +//Or you can use default client instance (do this only once) +numbers.Client.globalOptions.accountId = "accountId"; +numbers.Client.globalOptions.userName = "userName"; +numbers.Client.globalOptions.password = "password"; + +//Now you can call any functions without first arg 'client' + +numbers.Site.list(function(err, sites){ + //Default client will be used to do this call +}); + +``` + ## Async Methods Each API Call also contains an async method that returns a promise for use with `.then` or `async`/`await`. From 40f8dd7b887fe01e89a0a58a01048e7c85049302 Mon Sep 17 00:00:00 2001 From: matthewkmartin Date: Fri, 11 Sep 2026 10:44:58 -0400 Subject: [PATCH 2/2] ONEID-4689 Note credentials should be loaded from env vars, not hard coded Co-Authored-By: Claude Sonnet 5 --- README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index afbc21b..e55c814 100644 --- a/README.md +++ b/README.md @@ -65,19 +65,26 @@ numbers.Site.list(function(err, sites){ The SDK supports two authentication methods: OAuth2 client credentials (**preferred**) and basic auth (username/password). +**Never hard code credentials in source code.** Load `clientId`/`clientSecret` (or `userName`/`password`) from a secure source such as environment variables or a secrets manager, e.g.: + +```js +numbers.Client.globalOptions.clientId = process.env.BANDWIDTH_CLIENT_ID; +numbers.Client.globalOptions.clientSecret = process.env.BANDWIDTH_CLIENT_SECRET; +``` + ### OAuth2 Client Credentials (Preferred) ```js var numbers = require("@bandwidth/numbers"); //Using client directly -var client = new numbers.Client("accountId", null, null, "clientId", "clientSecret"); +var client = new numbers.Client("accountId", null, null, process.env.BANDWIDTH_CLIENT_ID, process.env.BANDWIDTH_CLIENT_SECRET); numbers.Site.list(client, function(err, sites){...}); //Or you can use default client instance (do this only once) numbers.Client.globalOptions.accountId = "accountId"; -numbers.Client.globalOptions.clientId = "clientId"; -numbers.Client.globalOptions.clientSecret = "clientSecret"; +numbers.Client.globalOptions.clientId = process.env.BANDWIDTH_CLIENT_ID; +numbers.Client.globalOptions.clientSecret = process.env.BANDWIDTH_CLIENT_SECRET; //Now you can call any functions without first arg 'client' @@ -104,13 +111,13 @@ var client = new numbers.Client("accountId", null, null, "clientId", "clientSecr var numbers = require("@bandwidth/numbers"); //Using client directly -var client = new numbers.Client("accountId", "userName", "password"); +var client = new numbers.Client("accountId", process.env.BANDWIDTH_USERNAME, process.env.BANDWIDTH_PASSWORD); numbers.Site.list(client, function(err, sites){...}); //Or you can use default client instance (do this only once) numbers.Client.globalOptions.accountId = "accountId"; -numbers.Client.globalOptions.userName = "userName"; -numbers.Client.globalOptions.password = "password"; +numbers.Client.globalOptions.userName = process.env.BANDWIDTH_USERNAME; +numbers.Client.globalOptions.password = process.env.BANDWIDTH_PASSWORD; //Now you can call any functions without first arg 'client'