Skip to content

LinkedIn OAuth 2.0 authentication strategy for Passport with TypeScript support.

License

Notifications You must be signed in to change notification settings

Authial/authial-linkedin-strategy

Repository files navigation

LinkedIn OAuth 2.0 authentication strategy for Passport with TypeScript support

Authenticates users via LinkedIn’s 3-legged OAuth 2.0 flow, handling the authorization process and retrieval of user profile information.

Important notes

  • LinkedIn access tokens are typically valid for 60 days for non-MDP (Marketing Developer Platform) partners.
  • Refresh tokens are not provided unless your app is approved as an MDP partner.
  • You should calculate token expiration as current_date + 60 days and store it in your database.
  • When tokens expire, users must re-authenticate through the same OAuth flow.

Required options

  • clientID – Your LinkedIn application’s Client ID (from the LinkedIn Developer Portal).
  • clientSecret – Your LinkedIn application’s Client Secret (keep this secure).
  • callbackURL – The URL LinkedIn redirects to after user authorization.

Optional configuration

  • scope – Array of permissions (default: ['openid', 'profile', 'email']).
  • state – Enable CSRF protection (recommended: true).
  • userProfileURL – Custom profile endpoint (default: LinkedIn’s v2 userinfo).

Usage

Before using this application, you must first set up an app on LinkedIn Developer Portal. Here’s a step-by-step guide:

  1. Create a LinkedIn App:

    • Visit the LinkedIn Developer Portal.
    • Sign in with your LinkedIn account.
    • Click on "Create app" and fill in the required details such as your app's name, description, and logo.
  2. Get Your Client ID and Client Secret:

    • Once your app is created, you’ll find your Client ID and Client Secret in the app settings. Keep these credentials secure.
  3. Set Up Required Scopes:

    • In your app settings, navigate to the "Auth" tab.
    • Under the "OAuth 2.0 settings," you will find a list of available scopes. Choose the scopes as per your application's requirements and add the Redirect URI that will handle JSON responses from LinkedIn.
    • Default scopes such as openid, profile, and email are already included when you set up your app.
  4. Authentication:

    • Use the obtained Client ID and Client Secret in your application to authenticate users and access LinkedIn data as per the configured scopes.

Make sure you handle the authentication flow correctly in your application to ensure users can sign in and authorize access appropriately.

Example: basic usage with token expiration

import passport from 'passport';
import { Strategy as LinkedInStrategy } from '@authial/passport-linkedin';

passport.use(
  new LinkedInStrategy(
    {
      clientID: process.env.LINKEDIN_CLIENT_ID!,
      clientSecret: process.env.LINKEDIN_CLIENT_SECRET!,
      callbackURL: 'https://yourapp.com/auth/linkedin/callback',
      scope: ['openid', 'profile', 'email', 'w_member_social'],
      state: true, // Enable CSRF protection
    },
    async (accessToken, refreshToken, profile, done) => {
      try {
        // Calculate token expiration (60 days from now for non-MDP partners)
        const tokenExpiresAt = new Date();
        tokenExpiresAt.setDate(tokenExpiresAt.getDate() + 60);

        // Save user and token info to your database
        const user = await db.user.upsert({
          where: { linkedinId: profile.id },
          update: {
            accessToken,
            tokenExpiresAt, // Store when token expires
            email: profile.emails?.value,
            displayName: profile.displayName,
          },
          create: {
            linkedinId: profile.id,
            accessToken,
            tokenExpiresAt,
            email: profile.emails?.value,
            displayName: profile.displayName,
          },
        });

        // Note: refreshToken will be undefined for non-MDP partners
        return done(null, user);
      } catch (error) {
        return done(error);
      }
    },
  ),
);

Example: middleware to handle token expiration

// Middleware to check if LinkedIn token is still valid
async function validateLinkedInToken(req, res, next) {
  const user = await db.user.findUnique({ where: { id: req.user.id } });

  if (!user?.accessToken || Date.now() >= user.tokenExpiresAt.getTime()) {
    // Token expired - redirect or instruct client to re-auth
    return res.status(401).json({
      error: 'LinkedIn token expired',
      message: 'Please re-authorize with LinkedIn',
      redirectUrl: '/auth/linkedin', // Same OAuth flow
    });
  }

  req.user.accessToken = user.accessToken;
  next();
}

// Use in protected routes
app.get('/api/linkedin/profile', validateLinkedInToken, async (req, res) => {
  // Make LinkedIn API calls with a valid token
});

Authors

References

About

LinkedIn OAuth 2.0 authentication strategy for Passport with TypeScript support.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors