LinkedIn 0auth2.0 implementation - easy way
Welcome to My First Post!
Hello! I’m Raymond Umukoro, and I’m thrilled to share my very first article here on Hashnode. In this post, we’ll explore how to integrate LinkedIn OAuth 2.0 into your app—a topic I recently tackled myself—and highlight some common pitfalls to avoid. Let's dive in and break it down step by step!
Understanding OAuth 2.0
Imagine you're giving a friend a key to your house. You trust them, but you don't want them to have a permanent copy. That's where OAuth 2.0 comes in.
OAuth 2.0 is like a digital key that you give to apps. When you log into an app with your Google, Facebook, LinkedIn or another account, you're essentially giving that app a temporary key to access certain parts of your online life. This key is called an access token.
Key Components of OAuth 2.0:
Resource Owner: The person or entity that owns the data (e.g., a user).
Resource Server: The system that hosts the data (e.g., a web server).
Client Application: The third-party application that requests access to the data.
Authorization Server: The system that authorizes access to the data.
OAuth 2.0 Flow:
Authorization Request: The client application sends an authorization request to the authorization server, specifying the desired scope of access (e.g., read-only, profile, write etc.).
User Consent: The authorization server prompts the resource owner to grant or deny access to the client application.
Authorization Code: If the user grants access, the authorization server redirects the user back to the client application with an authorization code.
Token Exchange: The client application exchanges the authorization code for an access token at the authorization server.
Resource Access: The client application uses the access token to access the protected resources on the resource server.
The Importance of OAuth 2.0
Why is this important?
Security: Instead of sharing your full password with every app you use, OAuth 2.0 lets you grant specific permissions. This means you're less likely to get hacked because your sensitive information isn't being shared everywhere.
Convenience: It's easier to remember one password for multiple apps than a unique password for each one.
Control: You can revoke access to an app at any time, meaning you can "take back" the key if you no longer trust it.
Implementation of LinkedIn OAuth 2.0
Setting up a LinkedIn Developer account.
Before you can integrate LinkedIn OAuth 2.0 into your application, you’ll need to set up a LinkedIn Developer account and create an app. Here’s a step-by-step guide to get you started:
Sign in to LinkedIn Developer:
- Go to LinkedIn Developer and log in with your LinkedIn credentials. If you don’t have an account, you’ll need to create one first.
Create a New App:
Once logged in, click on the Create App button.
You’ll be prompted to enter basic details about your app, such as:
App Name: Choose a meaningful name that represents your project.
LinkedIn Page: You will need to have created a linkedIn page for your app, search for it on the tab provided.
Privacy Policy Url: Optional.
App Logo: Upload a logo that will represent your app on LinkedIn.
After filling in the required details, accept LinkedIn’s API terms and click Create App.
Configure OAuth Settings:
Navigate first to Settings tab to verify your application by generating a url and following the link, this is to give you access to products linkedIn avails you. Use the same LinkedIn account you used to create your linkedIn page to verify your app. After verification, refresh the page.
Navigate to Products tab and request access to “Sign In with LinkedIn using OpenID Connect“
Navigate to the Auth tab and refresh the page, you will see the scopes under OAuth2.0 scope section of the page.
Scopes determine what information your app can access. These must exactly match the scopes you selected when creating your LinkedIn app (e.g., profile data, email).
Still under the OAuth 2.0 Auth tab, you will need to configure:
You will see both the client secret and ID, copy and save in your application variables.
Authorized Redirect URLs: This is the URL where LinkedIn will redirect users after they authorize your app. Make sure this URL matches the callback URL in your code (e.g.,
http://localhost:4500/auth/linkedin/callback
).
Code Implementation
- Create your environment variables (.env file)
LINKEDIN_CLIENT_ID=********************
LINKEDIN_CLIENT_SECRET=*****************
LINKEDIN_CALLBACKURL=http://localhost:4500/auth/linkedin/callback
Explanation:
These values are critical for securely communicating with LinkedIn. We keep them in the
.env
file to avoid hardcoding sensitive information in our code.Client ID: This uniquely identifies your app to LinkedIn.
Client Secret: A password that your app uses to authenticate with LinkedIn (keep it private!).
Callback URL: After LinkedIn verifies the user, it will redirect them back to this URL in your app. Make sure this matches the URL you’ve configured in your LinkedIn app settings under Authorized Redirect URLs.
Note: Your LinkedIn app must have the same callback URL configured; otherwise, the authentication process will fail.
Install Packages.
For this implementation, I used the query string and axios packages. You will need to install both.
npm install qs axios
Controller Setup (auth.controller.ts)
However you set up your code, it is up to you. The major take-away is understanding the code implementation.
import { Request, Response, NextFunction } from 'express';
import axios from 'axios';
import qs from 'qs';
import Configuration from '../../config';
const { linkedIn: { linkedin_client_id,
linkedin_callback_url, linkedin_client_secret } } = Configuration;
class AuthController {
linkedInAuthHandler = async (req: Request, res: Response, next: NextFunction) => {
try {
// Generate the LinkedIn authorization URL with the required query parameters
const authorizeUrl = `https://www.linkedin.com/oauth/v2/authorization?${qs.stringify({
response_type: 'code',
client_id: linkedin_client_id,
redirect_uri: linkedin_callback_url,
scope: 'openid profile email', // Must match the scopes selected when creating the LinkedIn app
})}`;
// Send the URL as a response to the client
res.json({ url: authorizeUrl });
} catch (error: any) {
console.error('Error generating LinkedIn authorization URL:', error.response?.data || error.message);
res.status(500).json({ message: 'Failed to generate LinkedIn authorization URL.' });
}
};
linkedInSignInHandler = async (req: Request, res: Response, next: NextFunction) => {
const code = req.query.code as string;
if (!code) {
return res.status(400).json({ message: 'Authorization code is missing.' });
}
try {
const tokenResponse = await axios.post('https://www.linkedin.com/oauth/v2/accessToken', qs.stringify({
grant_type: 'authorization_code',
code,
redirect_uri: linkedin_callback_url,
client_id: linkedin_client_id,
client_secret: linkedin_client_secret
}), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const { access_token } = tokenResponse.data;
if (!access_token) {
return res.status(500).json({ message: 'Failed to retrieve access token.' });
}
const userinfoRes = await axios.get('https://api.linkedin.com/v2/userinfo', {
headers: { Authorization: `Bearer ${access_token}` },
});
const userInfo = userinfoRes.data;
res.json({ userinfo: userInfo });
} catch (error: any) {
console.error('Error during LinkedIn token exchange:', error.response?.data || error.message);
return res.status(500).json({ message: 'Failed to retrieve access token.' });
}
};
}
export default new AuthController();
Explanation:
We import the LinkedIn OAuth credentials (
client_id
,client_secret
, andcallback_url
) from the.env
file, using theConfiguration
object for convenience.This helps us reference these values throughout the application without exposing them directly in the code.
The function linkedInAuthHandler generates an authorization URL for LinkedIn, which prompts the user to log in and grant your app access. The URL includes necessary parameters like the response type ('code') and scopes ('openid profile email') to obtain the required user information.
The function linkedInSignInHandler handles the entire authorization process with LinkedIn. It starts by obtaining the authorization code from LinkedIn after user approval. Then, it exchanges this code for an access token by sending a request to LinkedIn's token endpoint with necessary parameters and headers. Finally, using the access token, it fetches user information from LinkedIn's userinfo endpoint. Errors are handled by logging and returning an appropriate response. Note: You can choose to do whatever you want with the user information e.g save to your database etc.
Defining Routes (auth.routes.ts).
import { Router } from 'express'; import authController from './auth.controller'; const { linkedInAuthHandler, linkedInSignInHandler } = authController; const authRouter = Router(); authRouter.get("/auth/linkedin", linkedInAuthHandler); //Step 1: User clicks LinkedIn login authRouter.get("/auth/linkedin/callback", linkedInSignInHandler); //Step 2: LinkedIn redirects back here after auth export default authRouter;
Explanation:
Route 1 (
/auth/linkedin
): This is where the user starts the LinkedIn login process. When they visit this URL, thelinkedInAuthHandler
function generates the authorization URL and redirects the user to LinkedIn.Route 2 (
/auth/linkedin/callback
): After the user authorizes your app, LinkedIn sends them back to this URL. ThelinkedInSignInHandler
then processes the authorization code, gets the access token, and fetches the user’s information.
Result:
The result appears as JSON in my browser because that was the response sent from my server. As mentioned earlier, you can choose to do whatever you want with this information. For example, you can display the name on the screen, save the details to a database, etc.
Closing Remarks
And there you have it—implementing LinkedIn OAuth 2.0 doesn’t have to be daunting! By following these steps, you can seamlessly integrate LinkedIn’s powerful authentication into your application, enhancing user experience and streamlining login processes.
But remember, LinkedIn offers much more than just user authentication. With LinkedIn’s extensive suite of products, you can explore features like sharing content, accessing marketing insights, and leveraging professional networking tools. The potential is vast, and integrating LinkedIn’s capabilities can truly elevate your application.
I hope this guide has made the process clearer and more manageable. If you have any questions or run into any issues along the way, feel free to reach out or leave a comment below. I’d love to hear about your experiences and any additional tips you might have. Thanks for reading, and happy coding!
Additional Resources.
OAuth 2.0 RFC: The official specification for OAuth 2.0: https://datatracker.ietf.org/doc/html/rfc6749
Node.js HTTP Client: If you prefer a more granular approach, leverage the built-in http
or https
modules to make direct requests to OAuth endpoints. The Node.js documentation provides comprehensive information on these modules: https://nodejs.org/api/http.html, https://nodejs.org/api/https.html
Simple-OAuth2: A lightweight and easy-to-use library for OAuth 2.0 authentication: https://www.npmjs.com/package/simple-oauth2
Stack Overflow: A valuable resource for finding answers to specific questions and troubleshooting OAuth 2.0 implementations: https://stackoverflow.com/
Subscribe to my newsletter
Read articles from Raymond Umukoro directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Raymond Umukoro
Raymond Umukoro
Raymond is a dedicated full-stack web developer with 3+ years of experience crafting innovative web solutions. His core expertise lies in Node.js, PHP, JavaScript, TypeScript, and React, allowing him to build robust and scalable applications. Beyond coding, Raymond is passionate about writing, sharing his knowledge, and contributing to the developer community.