How do you authenticate a GitHub App in Node.js?
Asked Answered
C

2

8

I've created a new GitHub App and I'm trying to authenticate from Node. I'm new to GitHub Apps, for example, I don't know what "installationId" is supposed to be. Is that the App ID?

I successfully get a token using a private key, but when I try using the API, I get an error both from Node and from curl.

import { createAppAuth } from '@octokit/auth-app';
import { request } from '@octokit/request';

const privateKey = fs.readFileSync(__dirname + 'file.pem');
const auth = createAppAuth({
 id: 1,
 privateKey,
 installationId: 12345,
 clientId: 'xxx.xxxxxx',
 clientSecret: 'xxxxxx',
});

const appAuthentication = await auth({ type: 'app' });
console.log(`Git repo token: ` + appAuthentication.token);

const result = await request('GET /orgs/:org/repos', {
      headers: {
                 authorization: 'token ' + appAuthentication.token,
               },
               org: 'orgname',
               type: 'public',
      });
return res.status(200).json({ message: 'Git result: ' + result });

Here is the curl example I tried after getting the token from the Node code above.

curl -i -X POST -H "Authorization: Bearer xxxxxxxxxx" -H "Accept: application/vnd.github.machine-man-preview+json" https://api.github.com/app

The result in Node: "Git result: Git repo error: HttpError: Bad credentials"

Result in curl: { "message": "Integration not found", "documentation_url": "https://developer.github.com/v3" }

Cleek answered 11/2, 2020 at 2:9 Comment(3)
Re-check your request headers, you are using 'token '. I believe you may have to use 'Bearer ' insteadJariah
@Jariah thanks for the suggestion. I did try that. You'll see the curl example above uses Bearer.Cleek
Can you try following: To identify installation_id: Get Installations Authenticating as GithubApp - check authentication as installation sectionJariah
D
12

The JSON Web Token (JWT) authentication can only be used for a few endpoints of GitHub's REST API. Mostly the ones listed on https://developer.github.com/v3/apps/

For all others, you need an installation access token.

Can you try this instead?

const { token } = await auth({ type: "installation" });
const result = await request("GET /orgs/:org/repos", {
  headers: {
    authorization: "token " + token
  },
  org: "orgname",
  type: "public"
});

Note that the installationId option must be set to a valid installation ID. You get the installation ID when you install the GitHub app on github.com. For example, you can install the WIP app at https://github.com/apps/wip on your account or any organization you have admin access to. The installation URLs look like this:

https://github.com/settings/installations/90210

In the example above, the installation ID is 90210.

To simplify your code, you can use the auth.hook feature in which case the correct authentication will be set automatically based on the URL

import { createAppAuth } from "@octokit/auth-app";
import { request } from "@octokit/request";

const privateKey = fs.readFileSync(__dirname + "file.pem");
const auth = createAppAuth({
  id: 1,
  privateKey,
  installationId: 12345
});

const requestWithAuth = request.defaults({
  request: {
    hook: auth.hook
  }
})

const result = await requestWithAuth("GET /orgs/:org/repos", {
  org: "orgname",
  type: "public"
});

See https://github.com/octokit/request.js/#authentication for more examples

Decency answered 24/2, 2020 at 19:31 Comment(2)
Thx! I’ll try this tonight. Really really appreciate the clarificationCleek
Thx again. It worked with your revised/simplified code once I understood where to get the Installation ID.Cleek
S
4

Anyone landing here and using Octokit, here is a newer way of doing it:

const config = {
  appId: process.env.GITHUB_APP_ID,
  privateKey: base64ToAscii(process.env.GITHUB_PRIVATE_KEY),
  webhooks: {
    secret: process.env.GITHUB_SIGNING_SECRET,
  },
};

const app = new App(config);

// Get installationId from the installed app or a webhook event
const octokit =
  await app.getInstallationOctokit(installationId);
const { data: user } = await octokit.rest.users.getByUsername({
  username: login,
});
Seleucia answered 1/11, 2023 at 15:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.