Skip to content

GitHub App authentication for JavaScript

License

Notifications You must be signed in to change notification settings

bgpo/auth-app.js

 
 

Repository files navigation

auth-app.js

GitHub App authentication for JavaScript

@latest Build Status

@octokit/auth-app implements authentication for GitHub Apps using JSON Web Token and installation access tokens.

For other GitHub authentication strategies see octokit/auth.js.

Usage

Browsers

Load @octokit/auth-app directly from cdn.skypack.dev

<script type="module">
  import { createAppAuth } from "https://cdn.skypack.dev/@octokit/auth-app";
</script>
Node

Install with npm install @octokit/auth-app

const { createAppAuth } = require("@octokit/auth-app");
// or: import { createAppAuth } from "@octokit/auth-app";

⚠️ For usage in browsers: The private keys provided by GitHub are in PKCS#1 format, but the WebCrypto API only supports PKCS#8. You need to convert it first:

openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private-key.pem -out private-key-pkcs8.key

No conversation is needed in Node, both PKCS#1 and PKCS#8 format will work.

const auth = createAppAuth({
  appId: 1,
  privateKey: "-----BEGIN PRIVATE KEY-----\n...",
  installationId: 123,
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef12341234567890abcdef1234",
});

// Retrieve JSON Web Token (JWT) to authenticate as app
const appAuthentication = await auth({ type: "app" });
// resolves with
// {
//   type: 'app',
//   token: 'jsonwebtoken123',
//   appId: 123,
//   expiresAt: '2018-07-07T00:09:30.000Z'
// }

// Retrieve installation access token
const installationAuthentication = await auth({ type: "installation" });
// resolves with
// {
//   type: 'token',
//   tokenType: 'installation',
//   token: 'token123',
//   installationId: 123,
//   createdAt: '2018-07-07T00:00:00.000Z'
//   expiresAt: '2018-07-07T00:59:00.000Z'
// }

// Retrieve an oauth-access token
const oauthAuthentication = await auth({ type: "oauth", code: "123456" });
// resolves with
// {
//   type: 'token',
//   tokenType: 'oauth',
//   token: 'token123',
//   scopes: []
// }

createAppAuth(options)

name type description
appId number Required. Find App ID on the app’s about page in settings.
privateKey string Required. Content of the *.pem file you downloaded from the app’s about page. You can generate a new private key if needed.
installationId number Default installationId to be used when calling auth({ type: "installation" }).
clientId string The Client ID of the GitHub App.
clientSecret string The Client Secret of the GitHub App.
request function You can pass in your own @octokit/request instance. For usage with enterprise, set baseUrl to the hostname + /api/v3. Example:
const { request } = require("@octokit/request");
createAppAuth({
  appId: 1,
  privateKey: "-----BEGIN PRIVATE KEY-----\n...",
  request: request.defaults({
    baseUrl: "https://ghe.my-company.com/api/v3",
  }),
});
cache object Installation tokens expire after an hour. By default, @octokit/auth-app is caching up to 15000 tokens simultaneously using lru-cache. You can pass your own cache implementation by passing options.cache.{get,set} to the constructor. Example:
const CACHE = {};
createAppAuth({
  appId: 1,
  privateKey: "-----BEGIN PRIVATE KEY-----\n...",
  cache: {
    async get(key) {
      return CACHE[key];
    },
    async set(key, value) {
      CACHE[key] = value;
    },
  },
});
log object You can pass in your preferred logging tool by passing option.log to the constructor. If you would like to make the log level configurable using an environment variable or external option, we recommend the console-log-level package. For example:
createAppAuth({
  appId: 1,
  privateKey: "-----BEGIN PRIVATE KEY-----\n...",
  log: require("console-log-level")({ level: "info" }),
});

auth(options)

name type description
type string Required. Must be either "app", "installation", or "oauth".
installationId number Required if type is set to "installation" unless a default installationId was passed to createAppAuth(). ID of installation to retrieve authentication for.
repositoryIds array of string Only relevant if type is set to "installation".

The `id`s of the repositories that the installation token can access.
permissions object Only relevant if type is set to "installation".

The permissions granted to the access token. The permissions object includes the permission names and their access type. For a complete list of permissions and allowable values, see GitHub App permissions.
factory function Only relevant if `type` is set to `"installation"`.

When the factory option is, the auth({type: "installation", installationId, factory }) call with resolve with whatever the factory function returns. The factory function will be called with all the strategy option that auth was created with, plus the additional options passed to auth, besides type and factory.

For example, you can create a new auth instance for an installation which shares the internal state (especially the access token cache) with the calling auth instance:

const appAuth = createAppAuth({
  appId: 1,
  privateKey: "-----BEGIN PRIVATE KEY-----\n...",
});

const installationAuth123 = await appAuth({
  type: "installation",
  installationId: 123,
  factory: createAppAuth,
});
refresh boolean Only relevant if type is set to "installation".

Installation tokens expire after one hour. By default, tokens are cached and returned from cache until expired. To bypass and update a cached token for the given installationId, set refresh to true.

Defaults to false.
code string Only relevant if type is set to "oauth".

The authorization code which was passed as query parameter to the callback URL from the OAuth web application flow.
redirectUrl string Only relevant if type is set to "oauth".

The URL in your application where users are sent after authorization. See redirect urls.
state string Only relevant if type is set to "oauth".

The unguessable random string you provided in Step 1 of the OAuth web application flow.

Authentication object

There are three possible results

  1. JSON Web Token (JWT) authentication
  2. Installation access token authentication
  3. OAuth access token authentication

JSON Web Token (JWT) authentication

name type description
type string "app"
token string The JSON Web Token (JWT) to authenticate as the app.
appId number GitHub App database ID.
expiresAt string Timestamp in UTC format, e.g. "2018-07-07T00:09:30.000Z". A Date object can be created using new Date(authentication.expiresAt).

Installation access token authentication

name type description
type string "token"
token string The installation access token.
tokenType string "installation"
installationId number Installation database ID.
createdAt string Timestamp in UTC format, e.g. "2018-07-07T00:00:00.000Z". A Date object can be created using new Date(authentication.expiresAt).
expiresAt string Timestamp in UTC format, e.g. "2018-07-07T00:59:00.000Z". A Date object can be created using new Date(authentication.expiresAt).
repositoryIds array of numbers Only present if repositoryIds option passed to auth(options).
permissions object An object where keys are the permission name and the value is either "read" or "write". See the list of all GitHub App Permissions.
singleFileName string If the single file permission is enabled, the singleFileName property is set to the path of the accessible file.

OAuth access token authentication

name type description
type string "token"
token string The personal access token
tokenType string "oauth"
scopes array of strings array of scope names enabled for the token

auth.hook(request, route, parameters) or auth.hook(request, options)

auth.hook() hooks directly into the request life cycle. It amends the request to authenticate either as app or as installation based on the request URL. It also automatically sets the "machine-man" preview which is currently required for all endpoints requiring JWT authentication.

The request option is an instance of @octokit/request. The arguments are the same as for the request() method.

auth.hook() can be called directly to send an authenticated request

const { data: installations } = await auth.hook(
  request,
  "GET /app/installations"
);

Or it can be passed as option to request().

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

const { data: installations } = await requestWithAuth("GET /app/installations");

Note that auth.hook() does not create and set an OAuth authentication token. But you can use @octokit/auth-oauth-app for that functionality. And if you don't plan on sending requests to routes that require authentication with client_id and client_secret, you can just retrieve the token and then create a new instance of request() with the authentication header set:

const { token } = await auth({
  type: "oauth",
  code: "123456",
});
const requestWithAuth = request.defaults({
  headers: {
    authentication: `token ${token}`,
  },
});

Implementation details

When creating a JSON Web Token, it sets the "issued at time" (iat) to 30s in the past as we have seen people running situations where the GitHub API claimed the iat would be in future. It turned out the clocks on the different machine were not in sync.

Installation access tokens are valid for 60 minutes. This library invalidates them after 59 minutes to account for request delays.

License

MIT

About

GitHub App authentication for JavaScript

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 100.0%