Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
GitHubStrategy
✓ import { GitHubStrategy } from 'remix-auth-github';
✗ const GitHubStrategy = require('remix-auth-github');
remix-auth-github is an ESM-first package. Use ES Modules import syntax.
Authenticator
✓ import { Authenticator } from 'remix-auth';
✗ import Authenticator from 'remix-auth';
Authenticator is a named export from the `remix-auth` peer dependency and is essential for setting up any authentication strategy.
GitHubProfile
✓ import type { GitHubProfile } from 'remix-auth-github';
While the strategy itself doesn't fetch the profile directly since v3.0.0, the `GitHubProfile` type might be useful for defining the expected structure of profile data fetched manually.
This quickstart demonstrates the full setup of `remix-auth-github`. It includes creating session storage, instantiating the `Authenticator`, configuring `GitHubStrategy` with environment variables, and illustrating how to handle the `verify` callback to manually fetch user profile data from the GitHub API using the obtained tokens, as required since v3.0.0.
import { Authenticator } from 'remix-auth';
import { GitHubStrategy } from 'remix-auth-github';
import { createCookieSessionStorage } from '@remix-run/node'; // or '@remix-run/cloudflare/sessions'
import type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node'; // or '@remix-run/cloudflare'
// 1. Define your User type (to be stored in session)
interface User {
id: string;
name: string;
accessToken: string;
refreshToken: string | null;
// Potentially other GitHub profile data
}
// 2. Setup session storage
const sessionStorage = createCookieSessionStorage({
cookie: {
name: "_session",
sameSite: "lax",
path: "/",
httpOnly: true,
secrets: [process.env.SESSION_SECRET ?? 's3cr3t-dev-key'], // IMPORTANT: Use a strong secret in production
secure: process.env.NODE_ENV === "production",
},
});
// 3. Setup Authenticator instance
export const authenticator = new Authenticator<User>(sessionStorage);
// 4. Configure GitHub Strategy
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID ?? '';
const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET ?? '';
const GITHUB_REDIRECT_URI = process.env.GITHUB_REDIRECT_URI ?? 'http://localhost:3000/auth/github/callback'; // Must match your GitHub App's callback URL
authenticator.use(
new GitHubStrategy(
{
clientId: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET,
redirectURI: GITHUB_REDIRECT_URI,
scopes: ["user:email", "read:user"], // Optional scopes
},
async ({ tokens, request }) => {
// In this function, you receive the OAuth tokens.
// Since v3.0.0, you must manually fetch user profile data if needed.
console.log('Received GitHub Tokens:', tokens);
const githubProfileResponse = await fetch('https://api.github.com/user', {
headers: {
Authorization: `token ${tokens.accessToken()}`,
},
});
const githubProfile = await githubProfileResponse.json();
console.log('GitHub Profile:', githubProfile);
// This is where you would lookup/create a user in your database
// based on the GitHub profile ID or email, and return your internal 'User' object.
return {
id: githubProfile.id.toString(),
name: githubProfile.name || githubProfile.login,
accessToken: tokens.accessToken(),
refreshToken: tokens.hasRefreshToken() ? tokens.refreshToken() : null,
};
}
),
"github" // This is the strategy name used in `authenticator.authenticate`
);
// 5. Example Route: Initiate GitHub Login (e.g., app/routes/auth.github.tsx action)
/*
export async function action({ request }: ActionFunctionArgs) {
await authenticator.authenticate("github", request, {
successRedirect: "/dashboard",
failureRedirect: "/login",
});
}
*/
// 6. Example Route: Handle GitHub Callback (e.g., app/routes/auth.github.callback.tsx loader)
/*
export async function loader({ request }: LoaderFunctionArgs) {
const user = await authenticator.authenticate("github", request, {
successRedirect: "/dashboard",
failureRedirect: "/login",
});
// User object is now in the session
return user;
}
*/
Errors
Common errors & fixes
ReferenceError: globalThis.crypto is not defined
The runtime environment (e.g., an older Node.js version or a specific serverless function) lacks support for the `globalThis.crypto` API, which became a dependency for the internal `OAuth2Strategy` starting from v2.0.0.
fixUpdate your Node.js version to 18 or newer, or ensure your deployment environment (like Cloudflare Workers) natively supports `globalThis.crypto`.
Error: Authenticator is not configured for provider "github"
The strategy name provided to `authenticator.authenticate("provider-name", ...)` does not match the name specified when the `GitHubStrategy` was added to the authenticator instance (e.g., `authenticator.use(strategy, "my-github")`).
fixVerify that the string used as the first argument in `authenticator.authenticate` (e.g., 'github') precisely matches the custom name you provided as the second argument to `authenticator.use` for `GitHubStrategy`. If no custom name was provided, the default is 'github'.
Error: invalid_request: The redirect_uri provided is not valid for the client.
The `redirectURI` configured in your `GitHubStrategy` options within your Remix application does not exactly match one of the 'Authorization callback URL(s)' defined in your GitHub OAuth App settings on GitHub's developer portal.
fixCarefully check and ensure that the `redirectURI` value in your `GitHubStrategy` configuration (e.g., `process.env.GITHUB_REDIRECT_URI`) is an exact, character-for-character match for an authorized callback URL registered with your GitHub OAuth App.
TypeError: Cannot read properties of undefined (reading 'authenticate')
The `authenticator` instance has not been properly initialized or is not correctly exported/imported and accessible within the Remix route where `authenticator.authenticate` is being called.
fixEnsure your `Authenticator` instance is correctly initialized with session storage (e.g., `export const authenticator = new Authenticator<User>(sessionStorage);`) and that it is properly imported into your Remix `loader` or `action` file.
Audit
Dependencies
remix-authrequiredCore authentication framework that this strategy extends and requires for operation.