{"id":16888,"library":"remix-auth-linkedin","title":"Remix Auth Linkedin Strategy","description":"This library provides a LinkedIn authentication strategy for `remix-auth`, enabling users to log into Remix applications via their LinkedIn accounts. It extends `remix-auth-oauth2` and is currently at version 2.0.1, shipping with full TypeScript definitions for robust development. The package maintains a steady release cadence, with recent updates focused on dependency upgrades and critical API changes. A significant update in version 2.0.0 involved transitioning from LinkedIn's legacy OAuth 2.0 flow to the newer OpenID Connect standard, reflecting LinkedIn's evolving authentication protocols. This change required corresponding adjustments in application setup and profile handling. `remix-auth-linkedin` supports both Node.js and Cloudflare runtimes, making it versatile for various Remix deployment environments. Developers must register an OAuth application on the LinkedIn Developers page to obtain the necessary `clientID` and `clientSecret` for integration. It seamlessly integrates with `remix-auth`'s session management, leveraging `createCookieSessionStorage` or similar for authentication persistence.","status":"active","version":"2.0.1","language":"javascript","source_language":"en","source_url":"https://github.com/Lzok/remix-auth-linkedin","tags":["javascript","remix","remix-auth","auth","authentication","strategy","oauth2","oauth2-linkedin","remix-auth-linkedin","typescript"],"install":[{"cmd":"npm install remix-auth-linkedin","lang":"bash","label":"npm"},{"cmd":"yarn add remix-auth-linkedin","lang":"bash","label":"yarn"},{"cmd":"pnpm add remix-auth-linkedin","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core Remix server utilities, essential for any Remix application that handles server-side logic like authentication.","package":"@remix-run/server-runtime"},{"reason":"The foundational authentication library that `remix-auth-linkedin` extends to provide authentication capabilities.","package":"remix-auth"}],"imports":[{"note":"The `LinkedinStrategy` class is a named export, typically used in modern Remix applications with ESM. Avoid CommonJS `require`.","wrong":"const { LinkedinStrategy } = require(\"remix-auth-linkedin\");","symbol":"LinkedinStrategy","correct":"import { LinkedinStrategy } from \"remix-auth-linkedin\";"},{"note":"This is a named export from the core `remix-auth` library, not a default export.","wrong":"import Authenticator from \"remix-auth\";","symbol":"Authenticator","correct":"import { Authenticator } from \"remix-auth\";"},{"note":"While `remix` can be used as a shortcut, it's best practice to import from the specific runtime package like `@remix-run/node` or `@remix-run/cloudflare` for clarity and better tree-shaking.","wrong":"import { createCookieSessionStorage } from 'remix';","symbol":"createCookieSessionStorage","correct":"import { createCookieSessionStorage } from '@remix-run/node';"}],"quickstart":{"code":"import { createCookieSessionStorage } from '@remix-run/node';\nimport { Authenticator } from 'remix-auth';\nimport { LinkedinStrategy } from \"remix-auth-linkedin\";\n\n// Personalize this options for your usage.\nconst cookieOptions = {\n\tpath: '/',\n\thttpOnly: true,\n\tsameSite: 'lax' as const,\n\tmaxAge: 24 * 60 * 60 * 1000 * 30,\n\tsecrets: [process.env.SESSION_SECRET ?? 'fallback_secret_for_dev_only'], // Use env variable for production\n\tsecure: process.env.NODE_ENV !== 'development',\n};\n\nconst sessionStorage = createCookieSessionStorage({\n\tcookie: cookieOptions,\n});\n\nexport const authenticator = new Authenticator<string>(sessionStorage, {\n\tthrowOnError: true,\n});\n\nconst linkedinStrategy = new LinkedinStrategy(\n   {\n      clientID: process.env.LINKEDIN_CLIENT_ID ?? 'YOUR_CLIENT_ID_FROM_ENV',\n      clientSecret: process.env.LINKEDIN_CLIENT_SECRET ?? 'YOUR_CLIENT_SECRET_FROM_ENV',\n      callbackURL: process.env.LINKEDIN_CALLBACK_URL ?? 'https://example.com/auth/linkedin/callback',\n   },\n   async ({accessToken, refreshToken, extraParams, profile, context}) => {\n      // In a real application, you would interact with your database or API here\n      // For example, finding or creating a user based on the LinkedIn profile\n      console.log('LinkedIn Profile:', profile.id, profile.displayName, profile.emails[0].value);\n      console.log('Access Token:', accessToken);\n      // Simulate user data storage\n      return { id: profile.id, email: profile.emails[0].value, name: profile.displayName };\n   }\n);\n\nauthenticator.use(linkedinStrategy, 'linkedin');\n\n// app/routes/login.tsx\n// export default function Login() {\n//    return (\n//       <form action=\"/auth/linkedin\" method=\"post\">\n//          <button>Login with Linkedin</button>\n//       </form>\n//    )\n// }\n\n// app/routes/auth/linkedin.tsx\n// import { ActionFunction } from '@remix-run/node';\n// import { authenticator } from '~/linkedin.server'; // Adjust path\n//\n// export let loader: ActionFunction = () => { throw new Response(null, { status: 404 }); }; // Loader is not strictly needed here\n// export let action: ActionFunction = ({ request }) => {\n//    return authenticator.authenticate('linkedin', request);\n// };\n\n// app/routes/auth/linkedin/callback.tsx\n// import { LoaderFunction } from '@remix-run/node';\n// import { authenticator } from '~/linkedin.server'; // Adjust path\n//\n// export let loader: LoaderFunction = ({ request }) => {\n//    return authenticator.authenticate('linkedin', request, {\n//       successRedirect: '/dashboard',\n//       failureRedirect: '/login',\n//    });\n// };","lang":"typescript","description":"This code snippet demonstrates the setup of `LinkedinStrategy` with `remix-auth`, including session storage configuration and the essential authentication callback, providing a foundation for user login workflows."},"warnings":[{"fix":"Update your LinkedIn application configuration to support OpenID Connect and adjust your strategy callback function to handle the new `LinkedinProfile` structure and returned data.","message":"Version 2.0.0 of `remix-auth-linkedin` migrated from LinkedIn's traditional OAuth 2.0 implementation to OpenID Connect. This is a breaking change that requires re-evaluation of how user profile data is structured and potentially changes to your LinkedIn application settings.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure `callbackURL` is configured with a full URL like `https://your-domain.com/auth/linkedin/callback` and registered correctly in your LinkedIn developer application settings.","message":"The `callbackURL` provided to the `LinkedinStrategy` must be a complete, absolute URL (e.g., `https://example.com/auth/linkedin/callback`), not a relative path. LinkedIn's API expects a fully qualified URL for redirects.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Use environment variables (e.g., `process.env.LINKEDIN_CLIENT_ID` and `process.env.LINKEDIN_CLIENT_SECRET`) to securely provide these credentials to the `LinkedinStrategy` constructor.","message":"Client ID and Client Secret should never be hardcoded or exposed directly in client-side code. Always retrieve them from secure environment variables or a secrets management service to prevent security vulnerabilities.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Generate a strong, random, and unique secret string for production environments, ideally loaded from an environment variable (e.g., `process.env.SESSION_SECRET`) and ensure it's kept confidential.","message":"The `secrets` array for `createCookieSessionStorage` must contain robust, unique, and long-lived secret strings. Using placeholder values like `THISSHOULDBESECRET_AND_NOT_SHARED` in production is a significant security vulnerability.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Verify your `clientID` and `clientSecret` values against your LinkedIn developer application settings. Ensure they are correctly passed to the `LinkedinStrategy` constructor and are loaded from secure environment variables.","cause":"The `clientID` or `clientSecret` provided to `LinkedinStrategy` is incorrect or missing, preventing successful authentication with the LinkedIn API.","error":"Error: Missing or invalid client ID/secret"},{"fix":"Ensure the `callbackURL` passed to `LinkedinStrategy` (e.g., `https://example.com/auth/linkedin/callback`) exactly matches an authorized redirect URI in your LinkedIn developer application settings, including protocol, domain, and path.","cause":"The `callbackURL` configured in `LinkedinStrategy` does not precisely match one of the authorized redirect URIs configured in your LinkedIn developer application.","error":"Error: Invalid redirect_uri"},{"fix":"Confirm that `export const authenticator = new Authenticator(...)` is executed, that `authenticator.use(linkedinStrategy, 'linkedin')` is called, and that the strategy name 'linkedin' is consistently used in all `authenticator.authenticate` calls.","cause":"The `Authenticator` instance was not properly initialized, the `linkedinStrategy` was not correctly `use`d with the authenticator, or the strategy name ('linkedin') is misspelled in the `authenticate` call.","error":"TypeError: authenticator.authenticate is not a function"}],"ecosystem":"npm","meta_description":null}