GitHub
OAuth 2.0 provider for GitHub Apps and OAuth Apps.
Also see the OAuth 2.0 guide.
Initialization
The redirect URI is optional but required by GitHub if there are multiple URIs defined.
import { GitHub } from "arctic";
const github = new GitHub(clientId, clientSecret, null);
const github = new GitHub(clientId, clientSecret, redirectURI);
Create authorization URL
import { generateState } from "arctic";
const state = generateState();
const scopes = ["user:email", "repo"];
const url = github.createAuthorizationURL(state, scopes);
Validate authorization code
validateAuthorizationCode()
will either return an OAuth2Tokens
, or throw one of OAuth2RequestError
, ArcticFetchError
, or a standard Error
(parse errors). OAuth Apps will only return an access token (no expiration).
import { OAuth2RequestError, ArcticFetchError } from "arctic";
try {
const tokens = await github.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
} catch (e) {
if (e instanceof OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
const code = e.code;
// ...
}
if (e instanceof ArcticFetchError) {
// Failed to call `fetch()`
const cause = e.cause;
// ...
}
// Parse error
}
If you're using GitHub Apps, GitHub will provide an expiration for the access token alongside a refresh token.
const tokens = await github.validateAuthorizationCode(code);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
The refresh token expiration is returned as refresh_token_expires_in
.
const tokens = await github.validateAuthorizationCode(code);
if (
"refresh_token_expires_in" in tokens.data &&
typeof tokens.data.refresh_token_expires_in === "number"
) {
const refreshTokenExpiresIn = tokens.data.refresh_token_expires_in;
}
Refresh access tokens
For GitHub Apps, use refreshAccessToken()
to get a new access token using a refresh token. The behavior is identical to validateAuthorizationCode()
.
import { OAuth2RequestError, ArcticFetchError } from "arctic";
try {
const tokens = await github.refreshAccessToken(refreshToken);
const accessToken = tokens.accessToken();
const accessTokenExpiresAt = tokens.accessTokenExpiresAt();
const refreshToken = tokens.refreshToken();
} catch (e) {
if (e instanceof OAuth2RequestError) {
// Invalid authorization code, credentials, or redirect URI
}
if (e instanceof ArcticFetchError) {
// Failed to call `fetch()`
}
// Parse error
}
Get user profile
Use the /user
endpoint.
const response = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const user = await response.json();
Get user email
Add the email
scope and use the /user/emails
endpoint.
const scopes = ["user:email"];
const url = github.createAuthorizationURL(state, scopes);
const response = await fetch("https://api.github.com/user/emails", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const emails = await response.json();