npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@octokit/oauth-app

v7.1.3

Published

GitHub OAuth toolset for Node.js

Downloads

2,993,949

Readme

oauth-app.js

GitHub OAuth toolset for Node.js

@latest Build Status

Usage

Browsers

@octokit/oauth-app is not meant for browser usage.

Node

Install with npm install @octokit/oauth-app

[!IMPORTANT] As we use conditional exports, you will need to adapt your tsconfig.json by setting "moduleResolution": "node16", "module": "node16".

See the TypeScript docs on package.json "exports". See this helpful guide on transitioning to ESM from @sindresorhus

For OAuth Apps

import { OAuthApp, createNodeMiddleware } from "@octokit/oauth-app";
import { createServer } from "node:http";

const app = new OAuthApp({
  clientType: "oauth-app",
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef1234567890abcdef12345678",
});

app.on("token", async ({ token, octokit }) => {
  const { data } = await octokit.request("GET /user");
  console.log(`Token retrieved for ${data.login}`);
});

createServer(createNodeMiddleware(app)).listen(3000);
// can now receive user authorization callbacks at /api/github/oauth/callback
// See all endpoints at https://github.com/octokit/oauth-app.js#middlewares

For GitHub Apps

GitHub Apps do not support scopes. If the GitHub App has expiring user tokens enabled, the token used for the octokit instance will be refreshed automatically, and the additional refresh-related properties will be passed to the "token" event handler.

import { OAuthApp, createNodeMiddleware } from "@octokit/oauth-app";
import { createServer } from "node:http";

const app = new OAuthApp({
  clientType: "github-app",
  clientId: "lv1.1234567890abcdef",
  clientSecret: "1234567890abcdef1234567890abcdef12345678",
});

app.on("token", async ({ token, octokit, expiresAt }) => {
  const { data } = await octokit.request("GET /user");
  console.log(`Token retrieved for ${data.login}`);
});

createServer(createNodeMiddleware(app)).listen(3000);
// can now receive user authorization callbacks at /api/github/oauth/callback
// See all endpoints at https://github.com/octokit/oauth-app.js#middlewares

Examples

OAuthApp.defaults(options)

Create a new OAuthApp with custom defaults for the constructor options

const MyOAuthApp = OAuthApp.defaults({
  Octokit: MyOctokit,
});
const app = new MyOAuthApp({ clientId, clientSecret });
// app.octokit is now an instance of MyOctokit

Constructor options

Only relevant when clientType is set to "oauth-app".

Sets the default scopes value for app.getWebFlowAuthorizationUrl(options). See available scopes

You can pass in your own Octokit constructor with custom defaults and plugins. The Octokit Constructor must use an authentication strategy that is compatible with`@octokit/auth-oauth-app.

For usage with enterprise, set baseUrl to the hostname + /api/v3. Example:

import { Octokit } from "@octokit/core";
new OAuthApp({
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef1234567890abcdef12345678",
  Octokit: Octokit.defaults({
    baseUrl: "https://ghe.my-company.com/api/v3",
  }),
});

Defaults to @octokit/oauth-app's own Octokit constructor which can be imported separately from OAuthApp. It's @octokit/core with the @octokit/auth-oauth-user authentication strategy.

app.on(eventName, eventHandler)

Called whenever a new OAuth access token is created for a user. It accepts two parameters, an event name and a function with one argument

app.on("token.created", async (context) => {
  const { data } = await context.octokit.request("GET /user");
  app.log.info(`New token created for ${data.login}`);
});

The eventName can be one of (or an array of)

  • token.created
  • token.reset
  • token.refreshed (GitHub Apps only)
  • token.scoped (GitHub Apps only)
  • token.deleted
  • authorization.deleted

All event handlers are awaited before continuing.

context can have the following properties

The OAuth authentication object. See https://github.com/octokit/auth-oauth-user.js/#authentication-object

Authenticated instance using the Octokit option passed to the constructor and @octokit/auth-oauth-user as authentication strategy.

The octokit instance is unauthenticated for "token.deleted" and "authorization.deleted" events.

app.octokit

Octokit instance with OAuth App authentication. Uses Octokit constructor option

app.getUserOctokit(options)

const octokit = await app.getUserOctokit({ code: "code123" });

options are the same as in app.createToken(options)

The octokit instance is authorized using the user access token if the app is an OAuth app and a user-to-server token if the app is a GitHub app. If the token expires it will be refreshed automatically.

app.getWebFlowAuthorizationUrl(options)

Returns and object with all options and a url property which is the authorization URL. See https://github.com/octokit/oauth-methods.js/#getwebflowauthorizationurl

const { url } = app.getWebFlowAuthorizationUrl({
  state: "state123",
  scopes: ["repo"],
});

app.createToken(options)

The method can be used for both, the OAuth Web Flow and the OAuth Device Flow.

For OAuth Web flow

For the web flow, you have to pass the code from URL redirect described in step 2.

const { token } = await app.createToken({
  code: "code123",
});

Resolves with an user authentication object

For OAuth Device flow

For the device flow, you have to pass a onVerification callback function, which prompts the user to enter the received user code at the received authorization URL.

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 = createOAuthUserAuth({
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef1234567890abcdef12345678",
  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");
  },
});

Only relevant if app.type is "oauth-app". Scopes are not supported by GitHub apps.

Array of OAuth scope names that the user access token should be granted. Defaults to no scopes ([]).

Resolves with an user authentication object

app.checkToken(options)

try {
  const { created_at, app, user } = await app.checkToken({ token });
  console.log(
    `token valid, created on %s by %s for %s`,
    created_at,
    user.login,
    app.name,
  );
} catch (error) {
  // token invalid or request error
}

Resolves with response body from "Check a token" request with an additional authentication property which is a user authentication object.

app.resetToken(options)

const { data, authentication } = await app.resetToken({
  token: "token123",
});
// "token123" is no longer valid. Use `token` instead

Resolves with response body from "Reset a token" request with an additional authentication property which is a user authentication object.

app.refreshToken(options)

Expiring tokens are only supported by GitHub Apps, and only if expiring user tokens are enabled.

const { data, authentication } = await app.refreshToken({
  refreshToken: "refreshtoken123",
});

Resolves with response body from "Renewing a user token with a refresh token" request (JSON) with an additional authentication property which is a user authentication object.

app.scopeToken(options)

Scoping a token is only supported by GitHub Apps. "Scoping" in this context means to limit access to a selected installation, with a subset of repositories and permissions.

const { data, authentication } = await app.scopeToken({
  clientType: "github-app",
  clientId: "lv1.1234567890abcdef",
  clientSecret: "1234567890abcdef12347890abcdef12345678",
  token: "usertoken123",
  target: "octokit",
  repositories: ["oauth-app.js"],
  permissions: {
    issues: "write",
  },
});

Options

Resolves with response body from "Create a scoped access token" request with an additional authentication property which is a user authentication object.

app.deleteToken(options)

await app.deleteToken({
  token: "token123",
});
// "token123" is no longer valid.

Resolves with response body from "Delete a token" request.

app.deleteAuthorization(options)

await app.deleteAuthorization({
  token: "token123",
});
// "token123" is no longer valid, and no tokens can be created until the app gets re-authorized.

Resolves with response body from "Delete an app authorization" request.

Middlewares

A middleware is a method or set of methods to handle requests for common environments.

By default, all middlewares expose the following routes

| Route | Route Description | | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | GET /api/github/oauth/login | Redirects to GitHub's authorization endpoint. Accepts optional ?state and ?scopes query parameters. ?scopes is a comma-separated list of supported OAuth scope names | | GET /api/github/oauth/callback | The client's redirect endpoint. This is where the token event gets triggered | | POST /api/github/oauth/token | Exchange an authorization code for an OAuth Access token. If successful, the token event gets triggered. | | GET /api/github/oauth/token | Check if token is valid. Must authenticate using token in Authorization header. Uses GitHub's POST /applications/{client_id}/token endpoint | | PATCH /api/github/oauth/token | Resets a token (invalidates current one, returns new token). Must authenticate using token in Authorization header. Uses GitHub's PATCH /applications/{client_id}/token endpoint. | | PATCH /api/github/oauth/refresh-token | Refreshes an expiring token (invalidates current one, returns new access token and refresh token). Must authenticate using token in Authorization header. Uses GitHub's POST https://github.com/login/oauth/access_token OAuth endpoint. | | POST /api/github/oauth/token/scoped | Creates a scoped token (does not invalidate the current one). Must authenticate using token in Authorization header. Uses GitHub's POST /applications/{client_id}/token/scoped endpoint. | | DELETE /api/github/oauth/token | Invalidates current token, basically the equivalent of a logout. Must authenticate using token in Authorization header. | | DELETE /api/github/oauth/grant | Revokes the user's grant, basically the equivalent of an uninstall. must authenticate using token in Authorization header. |

createNodeMiddleware(app, options)

Native http server middleware for Node.js

import { OAuthApp, createNodeMiddleware } from "@octokit/oauth-app";
import { createServer } from "node:http";

const app = new OAuthApp({
  clientType: "oauth-app",
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef1234567890abcdef12345678",
});

const middleware = createNodeMiddleware(app, {
  pathPrefix: "/api/github/oauth",
});

createServer(middleware).listen(3000);
// can now receive user authorization callbacks at /api/github/oauth/callback

All exposed paths will be prefixed with the provided prefix. Defaults to "/api/github/oauth"

createWebWorkerHandler(app, options)

Event handler for web worker environments (Cloudflare workers or Deno).

// worker.js
import { OAuthApp, createWebWorkerHandler } from "@octokit/oauth-app";
const app = new OAuthApp({
  clientType: "oauth-app",
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef1234567890abcdef12345678",
});

const handleRequest = createWebWorkerHandler(app, {
  pathPrefix: "/api/github/oauth",
});

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});
// can now receive user authorization callbacks at /api/github/oauth/callback

All exposed paths will be prefixed with the provided prefix. Defaults to "/api/github/oauth"

createAWSLambdaAPIGatewayV2Handler(app, options)

Event handler for AWS Lambda using API Gateway V2 HTTP integration.

// worker.js
import {
  OAuthApp,
  createAWSLambdaAPIGatewayV2Handler,
} from "@octokit/oauth-app";
const app = new OAuthApp({
  clientType: "oauth-app",
  clientId: "1234567890abcdef1234",
  clientSecret: "1234567890abcdef1234567890abcdef12345678",
});

export const handler = createAWSLambdaAPIGatewayV2Handler(app, {
  pathPrefix: "/api/github/oauth",
});

// can now receive user authorization callbacks at /api/github/oauth/callback

All exposed paths will be prefixed with the provided prefix. Defaults to "/api/github/oauth"

Build Custom Middlewares

When above middlewares do not meet your needs, you can build your own using the exported handleRequest function.

handleRequest function is an abstract HTTP handler which accepts an OctokitRequest and returns an OctokitResponse if the request matches any predefined route.

Different environments (e.g., Node.js, Cloudflare Workers, Deno, etc.) exposes different APIs when processing HTTP requests (e.g., IncomingMessage for Node.js, Request for Cloudflare workers, etc.). Two HTTP-related types (OctokitRequest and OctokitResponse) are generalized to make an abstract HTTP handler possible.

To share the behavior and capability with the existing Node.js middleware (and be compatible with OAuth user authentication strategy in the browser), it is better to implement your HTTP handler/middleware based on handleRequest function.

handleRequest function takes three parameters:

All exposed paths will be prefixed with the provided prefix. Defaults to "/api/github/oauth"

Implementing an HTTP handler/middleware for a certain environment involves three steps:

  1. Write a function to parse the HTTP request (e.g., IncomingMessage in Node.js) into an OctokitRequest object. See node/parse-request.ts for reference.
  2. Write a function to render an OctokitResponse object (e.g., as ServerResponse in Node.js). See node/send-response.ts for reference.
  3. Expose an HTTP handler/middleware in the dialect of the environment which performs three steps:
    1. Parse the HTTP request using (1).
    2. Process the OctokitRequest object using handleRequest.
    3. Render the OctokitResponse object using (2).

Contributing

See CONTRIBUTING.md

License

MIT