{"id":16673,"library":"remix-auth-github","title":"GitHub Authentication Strategy for Remix Auth","description":"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.","status":"active","version":"3.0.2","language":"javascript","source_language":"en","source_url":"https://github.com/sergiodxa/remix-auth-github","tags":["javascript","remix","remix-auth","auth","authentication","strategy","github"],"install":[{"cmd":"npm install remix-auth-github","lang":"bash","label":"npm"},{"cmd":"yarn add remix-auth-github","lang":"bash","label":"yarn"},{"cmd":"pnpm add remix-auth-github","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core authentication framework that this strategy extends and requires for operation.","package":"remix-auth","optional":false}],"imports":[{"note":"remix-auth-github is an ESM-first package. Use ES Modules import syntax.","wrong":"const GitHubStrategy = require('remix-auth-github');","symbol":"GitHubStrategy","correct":"import { GitHubStrategy } from 'remix-auth-github';"},{"note":"Authenticator is a named export from the `remix-auth` peer dependency and is essential for setting up any authentication strategy.","wrong":"import Authenticator from 'remix-auth';","symbol":"Authenticator","correct":"import { Authenticator } from 'remix-auth';"},{"note":"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.","symbol":"GitHubProfile","correct":"import type { GitHubProfile } from 'remix-auth-github';"}],"quickstart":{"code":"import { Authenticator } from 'remix-auth';\nimport { GitHubStrategy } from 'remix-auth-github';\nimport { createCookieSessionStorage } from '@remix-run/node'; // or '@remix-run/cloudflare/sessions'\nimport type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node'; // or '@remix-run/cloudflare'\n\n// 1. Define your User type (to be stored in session)\ninterface User {\n  id: string;\n  name: string;\n  accessToken: string;\n  refreshToken: string | null;\n  // Potentially other GitHub profile data\n}\n\n// 2. Setup session storage\nconst sessionStorage = createCookieSessionStorage({\n  cookie: {\n    name: \"_session\",\n    sameSite: \"lax\",\n    path: \"/\",\n    httpOnly: true,\n    secrets: [process.env.SESSION_SECRET ?? 's3cr3t-dev-key'], // IMPORTANT: Use a strong secret in production\n    secure: process.env.NODE_ENV === \"production\",\n  },\n});\n\n// 3. Setup Authenticator instance\nexport const authenticator = new Authenticator<User>(sessionStorage);\n\n// 4. Configure GitHub Strategy\nconst GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID ?? '';\nconst GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET ?? '';\nconst GITHUB_REDIRECT_URI = process.env.GITHUB_REDIRECT_URI ?? 'http://localhost:3000/auth/github/callback'; // Must match your GitHub App's callback URL\n\nauthenticator.use(\n  new GitHubStrategy(\n    {\n      clientId: GITHUB_CLIENT_ID,\n      clientSecret: GITHUB_CLIENT_SECRET,\n      redirectURI: GITHUB_REDIRECT_URI,\n      scopes: [\"user:email\", \"read:user\"], // Optional scopes\n    },\n    async ({ tokens, request }) => {\n      // In this function, you receive the OAuth tokens.\n      // Since v3.0.0, you must manually fetch user profile data if needed.\n      console.log('Received GitHub Tokens:', tokens);\n\n      const githubProfileResponse = await fetch('https://api.github.com/user', {\n        headers: {\n          Authorization: `token ${tokens.accessToken()}`,\n        },\n      });\n      const githubProfile = await githubProfileResponse.json();\n      console.log('GitHub Profile:', githubProfile);\n\n      // This is where you would lookup/create a user in your database\n      // based on the GitHub profile ID or email, and return your internal 'User' object.\n      return {\n        id: githubProfile.id.toString(),\n        name: githubProfile.name || githubProfile.login,\n        accessToken: tokens.accessToken(),\n        refreshToken: tokens.hasRefreshToken() ? tokens.refreshToken() : null,\n      };\n    }\n  ),\n  \"github\" // This is the strategy name used in `authenticator.authenticate`\n);\n\n// 5. Example Route: Initiate GitHub Login (e.g., app/routes/auth.github.tsx action)\n/*\nexport async function action({ request }: ActionFunctionArgs) {\n  await authenticator.authenticate(\"github\", request, {\n    successRedirect: \"/dashboard\",\n    failureRedirect: \"/login\",\n  });\n}\n*/\n\n// 6. Example Route: Handle GitHub Callback (e.g., app/routes/auth.github.callback.tsx loader)\n/*\nexport async function loader({ request }: LoaderFunctionArgs) {\n  const user = await authenticator.authenticate(\"github\", request, {\n    successRedirect: \"/dashboard\",\n    failureRedirect: \"/login\",\n  });\n  // User object is now in the session\n  return user; \n}\n*/","lang":"typescript","description":"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."},"warnings":[{"fix":"Update your `remix-auth` dependency to `^4.0.0`. Review and adapt your `GitHubStrategy` configuration options. Modify your `verify` callback to explicitly fetch user profile information from GitHub's API using the provided access token.","message":"Version 3.0.0 introduced significant breaking changes. It mandates `remix-auth` v4 (supporting Remix and React Router v7). Strategy options were altered, and the strategy now uses `arctic.js` internally. Crucially, it no longer automatically fetches the user's GitHub profile; only OAuth tokens are provided, requiring manual API calls for profile data.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Ensure your Remix application is running in an environment that provides `globalThis.crypto`, such as Node.js v18 or newer, or compatible Cloudflare Workers/other serverless runtimes. Upgrade Node.js if necessary.","message":"Version 2.0.0 introduced a breaking change: the underlying `OAuth2Strategy` now relies on `globalThis.crypto` being supported by the runtime. This can affect environments with older Node.js versions or specific serverless configurations.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Within the `verify` callback, perform an HTTP `GET` request to `https://api.github.com/user` (or other relevant GitHub API endpoints) including the `Authorization: Bearer ${tokens.accessToken()}` header to retrieve the user's profile data.","message":"Since v3.0.0, the `GitHubStrategy`'s `verify` callback receives `tokens` but *not* a pre-fetched `profile` object. If your application needs GitHub user profile data (like `name`, `email`, `avatar`), you must use the `tokens.accessToken()` to make a subsequent `fetch` request to GitHub's user API (e.g., `https://api.github.com/user`).","severity":"gotcha","affected_versions":">=3.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Update your Node.js version to 18 or newer, or ensure your deployment environment (like Cloudflare Workers) natively supports `globalThis.crypto`.","cause":"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.","error":"ReferenceError: globalThis.crypto is not defined"},{"fix":"Verify 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'.","cause":"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\")`).","error":"Error: Authenticator is not configured for provider \"github\""},{"fix":"Carefully 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.","cause":"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.","error":"Error: invalid_request: The redirect_uri provided is not valid for the client."},{"fix":"Ensure 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.","cause":"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.","error":"TypeError: Cannot read properties of undefined (reading 'authenticate')"}],"ecosystem":"npm"}