GitHub App authentication for JavaScript
@octokit/auth-app
implements authentication for GitHub Apps using JSON Web Token, installation access tokens, and OAuth user-to-server access tokens.
createAppAuth(options)
or new Octokit({ auth })
auth(options)
or octokit.auth(options)
auth.hook(request, route, parameters)
or auth.hook(request, options)
⚠️ @octokit/auth-app
is not meant for usage in the browser. A private key and client secret must not be exposed to users.
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
The OAuth APIs to create user-to-server tokens cannot be used because they do not have CORS enabled.
If you know what you are doing, load @octokit/auth-app
directly from esm.sh
<script type="module"> import { createAppAuth } from "https://esm.sh/@octokit/auth-app"; </script>Node
Install with npm install @octokit/auth-app
import { createAppAuth } from "@octokit/auth-app";Authenticate as GitHub App (JSON Web Token)
const auth = createAppAuth({ appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", clientId: "lv1.1234567890abcdef", 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" }Authenticate as OAuth App (client ID/client secret)
The OAuth Application APIs require the app to authenticate using clientID/client as Basic Authentication
const auth = createAppAuth({ appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", clientId: "lv1.1234567890abcdef", clientSecret: "1234567890abcdef12341234567890abcdef1234", }); const appAuthentication = await auth({ type: "oauth-app", });
resolves with
{ "type": "oauth-app", "clientId": "lv1.1234567890abcdef", "clientSecret": "1234567890abcdef1234567890abcdef12345678", "headers": { "authorization": "basic bHYxLjEyMzQ1Njc4OTBhYmNkZWY6MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3OA==" } }Authenticate as installation
const auth = createAppAuth({ appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", clientId: "lv1.1234567890abcdef", clientSecret: "1234567890abcdef12341234567890abcdef1234", }); // Retrieve installation access token const installationAuthentication = await auth({ type: "installation", installationId: 123, });
resolves with
{ "type": "token", "tokenType": "installation", "token": "token123", "installationId": 123, "createdAt": "2018-07-07T00:00:00.000Z", "expiresAt": "2018-07-07T00:59:00.000Z" }
const auth = createAppAuth({ appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", clientId: "lv1.1234567890abcdef", clientSecret: "1234567890abcdef12341234567890abcdef1234", }); // Retrieve an oauth-access token const userAuthentication = await auth({ type: "oauth-user", code: "123456" });
Resolves with
{ "type": "token", "tokenType": "oauth", "token": "token123" }
Browsers
⚠️ @octokit/auth-app
is not meant for usage in the browser. A private key and client secret must not be exposed to users.
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
The OAuth APIs to create user-to-server tokens cannot be used because they do not have CORS enabled.
If you know what you are doing, load @octokit/auth-app
and @octokit/core
(or a compatible module) directly from esm.sh
<script type="module"> import { createAppAuth } from "https://esm.sh/@octokit/auth-app"; import { Octokit } from "https://esm.sh/@octokit/core"; </script>
Node
Install with npm install @octokit/core @octokit/auth-app
. Optionally replace @octokit/core
with a compatible module
import { Octokit } from "@octokit/core"; import { createAppAuth, createOAuthUserAuth } from "@octokit/auth-app";
const appOctokit = new Octokit({ authStrategy: createAppAuth, auth: { appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", clientId: "1234567890abcdef1234", clientSecret: "1234567890abcdef1234567890abcdef12345678", }, }); // Send requests as GitHub App const { slug } = await appOctokit.request("GET /app"); console.log("authenticated as %s", slug); // Send requests as OAuth App await appOctokit.request("POST /application/{client_id}/token", { client_id: "1234567890abcdef1234", access_token: "existingtoken123", }); console.log("token is valid"); // create a new octokit instance that is authenticated as the user const userOctokit = await appOctokit.auth({ type: "oauth-user", code: "code123", factory: (options) => { return new Octokit({ authStrategy: createOAuthUserAuth, auth: options, }); }, }); // Exchanges the code for the user access token authentication on first request // and caches the authentication for successive requests const { data: { login }, } = await userOctokit.request("GET /user"); console.log("Hello, %s!", login);
In order to create an octokit
instance that is authenticated as an installation, with automated installation token refresh, set installationId
as auth
option
const installationOctokit = new Octokit({ authStrategy: createAppAuth, auth: { appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", installationId: 123, }, }); // transparently creates an installation access token the first time it is needed // and refreshes it when it expires await installationOctokit.request("POST /repos/{owner}/{repo}/issues", { owner: "octocat", repo: "hello-world", title: "title", });
createAppAuth(options)
or new Octokit({ auth })
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. If your private key contains escaped newlines (`\\n`), they will be automatically replaced with actual newlines. installationId
number
Default installationId
to be used when calling auth({ type: "installation" })
. clientId
string
The client ID of the GitHub App. clientSecret
string
A client secret for the GitHub App. request
function
Automatically set to octokit.request
when using with an Octokit
constructor.
For standalone usage, you can pass in your own @octokit/request
instance. For usage with enterprise, set baseUrl
to the hostname + /api/v3
. Example:
import { request } from "@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 toad-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:
import consoleLogLevel from "console-log-level"; createAppAuth({ appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", log: consoleLogLevel({ level: "info" }), });
auth(options)
or octokit.auth(options)
The async auth()
method accepts different options depending on your use case
Authenticate as the GitHub app to list installations, repositories, and create installation access tokens.
name type descriptiontype
string
Required. Must be either "app"
.
Create, reset, refresh, delete OAuth user-to-server tokens
name type descriptiontype
string
Required. Must be either "oauth-app"
. Installation authentication name type description type
string
Required. Must be "installation"
. installationId
number
Required unless a default installationId
was passed to createAppAuth()
. ID of installation to retrieve authentication for. repositoryIds
array of numbers
The id
of the repositories that the installation token can access. Also known as a databaseID
when querying the repository object in GitHub's GraphQL API. This option is **(recommended)** over repositoryNames
when needing to limit the scope of the access token, due to repositoryNames
having the possibility of changing. Additionally, you should only include either repositoryIds
or repositoryNames
, but not both. repositoryNames
array of strings
The name
of the repositories that the installation token can access. As mentioned in the repositoryIds
description, you should only include either repositoryIds
or repositoryNames
, but not both. permissions
object
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
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
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
.
Exchange code received from the web flow redirect described in step 2 of GitHub's OAuth web flow
name type descriptiontype
string
Required. Must be "oauth-user"
. factory
function
The auth({type: "oauth-user", 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:
import { createAppAuth, createOAuthUserAuth } from "@octokit/auth-oauth-app"; const appAuth = createAppAuth({ appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", clientId: "lv1.1234567890abcdef", clientSecret: "1234567890abcdef1234567890abcdef12345678", }); const userAuth = await appAuth({ type: "oauth-user", code, factory: createOAuthUserAuth, }); // will create token upon first call, then cache authentication for successive calls, // until token needs to be refreshed (if enabled for the GitHub App) const authentication = await userAuth();
code
string
The authorization code
which was passed as query parameter to the callback URL from the OAuth web application flow. redirectUrl
string
The URL in your application where users are sent after authorization. See redirect urls. state
string
The unguessable random string you provided in Step 1 of the OAuth web application flow. User authentication (device flow)
Create a token using GitHub's device flow.
The device flow does not require a client secret, but it is required as strategy option for @octokit/auth-app
, even for the device flow. If you want to implement the device flow without requiring a client secret, use @octokit/auth-oauth-device
.
type
string
Required. Must be "oauth-user"
. onVerification
function
Required. A function that is called once the device and user codes were retrieved.
The onVerification()
callback can be used to pause until the user completes step 2, which might result in a better user experience.
const auth = auth({ type: "oauth-user", onVerification(verification) { console.log("Open %s", verification.verification_uri); console.log("Enter code: %s", verification.user_code); await prompt("press enter when you are ready to continue"); }, });
factory
function
The auth({type: "oauth-user", 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:
import { createAppAuth, createOAuthUserAuth } from "@octokit/auth-oauth-app"; const appAuth = createAppAuth({ appId: 1, privateKey: "-----BEGIN PRIVATE KEY-----\n...", clientId: "lv1.1234567890abcdef", clientSecret: "1234567890abcdef1234567890abcdef12345678", }); const userAuth = await appAuth({ type: "oauth-user", code, factory: createOAuthUserAuth, }); // will create token upon first call, then cache authentication for successive calls, // until token needs to be refreshed (if enabled for the GitHub App) const authentication = await userAuth();
Depending on on the auth()
call, the resulting authentication object can be one of
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)
. name type description type
string
"oauth-app"
clientType
string
"github-app"
clientId
string
The client ID as passed to the constructor. clientSecret
string
The client secret as passed to the constructor. headers
object
{ authorization }
. 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)
. repositoryNames
array of strings
Only present if repositoryNames
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. GitHub APP user authentication token with expiring disabled name type description type
string
"token"
tokenType
string
"oauth"
clientType
string
"github-app"
clientId
string
The app's Client ID
clientSecret
string
One of the app's client secrets token
string
The user access token GitHub APP user authentication token with expiring enabled name type description type
string
"token"
tokenType
string
"oauth"
clientType
string
"github-app"
clientId
string
The app's Client ID
clientSecret
string
One of the app's client secrets token
string
The user access token refreshToken
string
The refresh token expiresAt
string
Date timestamp in ISO 8601 standard. Example: 2022-01-01T08:00:0.000Z
refreshTokenExpiresAt
string
Date timestamp in ISO 8601 standard. Example: 2021-07-01T00:00:0.000Z
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. Although the "machine-man"
preview has graduated to the official API, https://developer.github.com/changes/2020-08-20-graduate-machine-man-and-sailor-v-previews/, it is still required in versions of GitHub Enterprise up to 2.21 so it automatically sets the "machine-man"
preview 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-user", code: "123456", }); const requestWithAuth = request.defaults({ headers: { authentication: `token ${token}`, }, });
import { // strategy options StrategyOptions, // auth options AuthOptions, AppAuthOptions, OAuthAppAuthOptions, InstallationAuthOptions, OAuthWebFlowAuthOptions, OAuthDeviceFlowAuthOptions, // authentication objects Authentication, AppAuthentication, OAuthAppAuthentication, InstallationAccessTokenAuthentication, GitHubAppUserAuthentication, GitHubAppUserAuthenticationWithExpiration, } from "@octokit/auth-app";
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.
All OAuth features are implemented internally using @octokit/auth-oauth-app.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4