GitHub Authentication Strategy for Remix Auth

3.0.2 · active · verified Wed Apr 22

remix-auth-github is a strategy for `remix-auth` that facilitates implementing login with GitHub in Remix applications. The current stable version is 3.0.2, and the package sees active maintenance with recent updates focused on bug fixes and dependency management. Key differentiators include its tight integration with the `remix-auth` ecosystem, providing a streamlined OAuth2 flow for GitHub. Since version 3.0.0, it relies on `arctic.js` for OAuth2 client functionality and has shifted its responsibility to primarily provide access tokens, requiring developers to explicitly fetch user profile data from GitHub's API if needed. It supports both Node.js and Cloudflare runtimes, making it versatile for various Remix deployment targets. This strategy focuses on providing the necessary tokens, allowing developers full control over how user data is retrieved and managed post-authentication.

Common errors

Warnings

Install

Imports

Quickstart

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; 
}
*/

view raw JSON →