Let’s try to send a request to GitHub’s ‘GET /user’ API using the
@octokit/request
package.
// my-cli.js const { request } = require("@octokit/request"); const USERNAME = "octocat"; const PASSWORD = "secret"; request("GET /user", { headers: { authorization: `basic ${Buffer.from(`${USERNAME}:${PASSWORD}`).toString( "base64" )}` } }).then(response => console.log(response.data), console.error);
Depending on your GitHub security Settings, the above code will either log the user object for your account, or it will fail with a 401 response, including a ’X-GitHub-Otp’ header with the value set to ‘required; app’ or ‘required; sms’.
In order to retrieve your user account, you will need to send the same request again, including a header containing the OTP. OTP stands for one-time password. In GitHub’s case, you can use the OTP more than once, because it is actually a time-based password. It usually is valid for about a minute. 🤷.
If you use an authenticator app (you should!), you already know the right OTP to send along, the request code looks like this:
// my-cli.js const { request } = require("@octokit/request"); const USERNAME = "octocat"; const PASSWORD = "secret"; const OTP = "012345"; request("GET /user", { headers: { authorization: `basic ${Buffer.from(`${USERNAME}:${PASSWORD}`).toString( "base64" )}`, "x-github-otp": OTP } }).then(response => console.log(response.data), console.error);
If you have SMS setup for your two-factor authentication (you should not!), then you are out of luck. Not only do you not know the OTP at the time :of the first request, you won’t even receive an SMS with an OTP from GitHub. Why? Because only certain REST API routes trigger the SMS delivery. The OAuth Authorizations API routes, to be precise.
In order to workaround this problem, the recommend best practice is to not use basic authentication for every request. Instead, use it to create a personal access token, then use that token for the following requests.
And because you create a personal access token that you probably won’t need ever again, it’s a good practice to delete that token when you are done. However, the OTP you used to create the token might no longer be valid (time based, remember), so it’s well possible that GitHub will respond with a 401 asking for a new OTP.
You can see, this is getting complicated pretty quick, and it’s only the tip of the ice berg. For example, some requests require to be authenticated using your username and password, while for most others you can use the token. If you are curious, you can read trough the source code of @octokit/auth-basic to learn all about it. The tests will give you a pretty good summary.