GitHub OAuth Device authentication strategy for JavaScript
npm install @octokit/auth-oauth-device> GitHub OAuth Device authentication strategy for JavaScript


@octokit/auth-oauth-device is implementing one of GitHub’s OAuth Device Flow.
- Usage
- For OAuth Apps
- For GitHub Apps
- createOAuthDeviceAuth(options)
- auth(options)
- Authentication object
- OAuth APP user authentication
- GitHub APP user authentication with expiring tokens disabled
- GitHub APP user authentication with expiring tokens enabled
- auth.hook(request, route, parameters) or auth.hook(request, options)
- Types
- How it works
- Contributing
- License
Browsers | Load `` |
|---|---|
Node | Install with npm install @octokit/core @octokit/auth-oauth-device ` |
> [!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
`js
const auth = createOAuthDeviceAuth({
clientType: "oauth-app",
clientId: "1234567890abcdef1234",
scopes: ["public_repo"],
onVerification(verification) {
// verification example
// {
// device_code: "3584d83530557fdd1f46af8289938c8ef79f9dc5",
// user_code: "WDJB-MJHT",
// verification_uri: "https://github.com/login/device",
// expires_in: 900,
// interval: 5,
// };
console.log("Open %s", verification.verification_uri);
console.log("Enter code: %s", verification.user_code);
},
});
const tokenAuthentication = await auth({
type: "oauth",
});
// resolves with
// {
// type: "token",
// tokenType: "oauth",
// clientType: "oauth-app",
// clientId: "1234567890abcdef1234",
// token: "...", / the created oauth token /
// scopes: [] / depend on request scopes by OAuth app /
// }
`
GitHub Apps do not support scopes. Client IDs of GitHub Apps have a lv1. prefix. If the GitHub App has expiring user tokens enabled, the resulting authentication object has extra properties related to expiration and refreshing the token.
`js
const auth = createOAuthDeviceAuth({
clientType: "github-app",
clientId: "lv1.1234567890abcdef",
onVerification(verification) {
// verification example
// {
// device_code: "3584d83530557fdd1f46af8289938c8ef79f9dc5",
// user_code: "WDJB-MJHT",
// verification_uri: "https://github.com/login/device",
// expires_in: 900,
// interval: 5,
// };
console.log("Open %s", verification.verification_uri);
console.log("Enter code: %s", verification.user_code);
},
});
const tokenAuthentication = await auth({
type: "oauth",
});
// resolves with
// {
// type: "token",
// tokenType: "oauth",
// clientType: "github-app",
// clientId: "lv1.1234567890abcdef",
// token: "...", / the created oauth token /
// }
// or if expiring user tokens are enabled
// {
// type: "token",
// tokenType: "oauth",
// clientType: "github-app",
// clientId: "lv1.1234567890abcdef",
// token: "...", / the created oauth token /
// refreshToken: "...",
// expiresAt: "2022-01-01T08:00:0.000Z",
// refreshTokenExpiresAt: "2021-07-01T00:00:0.000Z",
// }
`
The createOAuthDeviceAuth method accepts a single options parameter
name | type | description |
|---|---|---|
clientId | string | Required. Find your OAuth app’s Client ID in your account’s developer settings. |
onVerification | function | Required. A function that is called once the device and user codes were retrieved The onVerification() ` await prompt("press enter when you are ready to continue"); |
clientType | string | Must be either oauth-app |
request | function | You can pass in your own @octokit/request instance. For usage with enterprise, set baseUrl to the API root endpoint. Example:` |
scopes | array of strings | Only relevant if clientType Array of scope names enabled for the token. Defaults to [] |
The async auth() method returned by createOAuthDeviceAuth(options) accepts the following options
name | type | description |
|---|---|---|
type | string | Required. Must be set to "oauth" |
scopes | array of strings | Only relevant if the clientType Array of scope names enabled for the token. Defaults to what was set in the strategy options. See available scopes |
refresh | boolean | Defaults to false |
The async auth(options) method resolves to one of three possible objects
1. OAuth APP user authentication
1. GitHub APP user authentication with expiring tokens disabled
1. GitHub APP user authentication with expiring tokens enabled
The differences are
1. scopes is only present for OAuth AppsrefreshToken
2. , expiresAt, refreshTokenExpiresAt are only present for GitHub Apps, and only if token expiration is enabled
name | type | description |
|---|---|---|
type | string | "token" |
tokenType | string | "oauth" |
clientType | string | "github-app" |
clientId | string | The app's Client ID |
token | string | The personal access token |
scopes | array of strings | array of scope names enabled for the token |
name | type | description |
|---|---|---|
type | string | "token" |
tokenType | string | "oauth" |
clientType | string | "github-app" |
clientId | string | The app's Client ID |
token | string | The personal access token |
name | type | description |
|---|---|---|
type | string | "token" |
tokenType | string | "oauth" |
clientType | string | "github-app" |
clientId | string | The app's Client ID |
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 |
or auth.hook(request, options)auth.hook() hooks directly into the request life cycle. It amends the request to authenticate correctly based on the request URL.
The request option is an instance of @octokit/request. The route/options parameters are the same as for the request() method.
auth.hook() can be called directly to send an authenticated request
`js`
const { data: user } = await auth.hook(request, "GET /user");
Or it can be passed as option to request().
`js
const requestWithAuth = request.defaults({
request: {
hook: auth.hook,
},
});
const { data: user } = await requestWithAuth("GET /user");
`
`ts`
import {
OAuthAppStrategyOptions,
OAuthAppAuthOptions,
OAuthAppAuthentication,
GitHubAppStrategyOptions,
GitHubAppAuthOptions,
GitHubAppAuthentication,
GitHubAppAuthenticationWithExpiration,
} from "@octokit/auth-oauth-device";
GitHub's OAuth Device flow is different from the web flow in two ways
1. It does not require a URL redirect, which makes it great for devices and CLI apps
2. It does not require the OAuth client secret, which means there is no user-owned server component required.
The flow has 3 parts (see GitHub documentation)
1. @octokit/auth-oauth-device requests a device and user code@octokit/auth-oauth-device` is sending requests in the background to retrieve the OAuth access token. Once the user completed step 2, the request will succeed and the token will be returned
2. Then the user has to open https://github.com/login/device (or it's GitHub Enterprise Server equivalent) and enter the user code
3. While the user enters the code,
See CONTRIBUTING.md