Skip to content

Instantly share code, notes, and snippets.

@debojyoti
Last active February 10, 2024 18:29
Show Gist options
  • Save debojyoti/ebe1783003258521ec19ac81594a8e38 to your computer and use it in GitHub Desktop.
Save debojyoti/ebe1783003258521ec19ac81594a8e38 to your computer and use it in GitHub Desktop.

Easy steps to implement social login with linkedin in Angular 7 (Angular 2+)

Note: The entire login process cannot be handled from client side, backend integration required for some steps (Explained at Step-3).

Step-1: Create your app in linkedin developer console

In order to start with linkedin login, we need to first create out app in linkedin.

Note: If you have already created your app, click on Go to My apps, select your app and then follow from step no 1.2

Click on the Create app button and fill up all the mandatory fields (App name, Company, Business email and App logo).

Note: In the company field you need to select a page from the dropdown results or create new company page. (For testing purpose, just type test and select any random page from the dropdown list)

At the end, accept the legal terms and click on the Create app button

1.2: Get the client id

Copy the client id from the Auth tab

1.3: Add a redirect url

We need to add a redirect url in order to get back the auth token provided by linkedin after successful authentication.

For example, if our app's web url is http://www.awesomeapp.com We can add redirect url as http://www.awesomeapp.com/linkedinLoginResponse (we will setup this route in the upcoming steps)

Linkedin setup done!

Step-2: Configure angular app to handle linkedin login

2.1: Setup 2 pages (components)

Minimum 2 pages (routes) required to handle LinkedIn login properly in our angular app. One page to place the Login with linkedin button and another one to handle linkedin redirection. Let say we are naming them as login & linkedInLoginResponse

The minimum content for the component login

login.component.html

<button (click)="login()">Login with LinkedIn</button>

login.component.ts

import { Component } from "@angular/core";
import { HttpClient, HttpHeaders } from "@angular/common/http";

@Component({
  selector: "LoginComponent",
  templateUrl: "./login.component.html",
  styleUrls: ["./login.component.css"]
})
export class LoginComponent {

  linkedInCredentials = {
    clientId: "************",
    redirectUrl: "https://y8pud.codesandbox.io/linkedInLogin",
    scope: "r_liteprofile%20r_emailaddress%20w_member_social" // To read basic user profile data and email
  };
  
  constructor(private http: HttpClient) {}
  
  login() {
    window.location.href = `https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=${
      this.linkedInCredentials.clientId
    }&redirect_uri=${this.linkedInCredentials.redirectUrl}&scope={this.linkedInCredentials.scope}`;
  }
}

The minimum content for the component linkedInLoginResponse

linkedinLoginResponse.component.html

<p>Your linkedIn code = {{ linkedInToken }}</p>

linkedinLoginResponse.component.ts

import { Component, OnInit } from "@angular/core";
import { Router, ActivatedRoute, Params } from "@angular/router";

@Component({
  selector: "LinkedinLoginResponse",
  templateUrl: "./linkedinLoginResponse.component.html",
  styleUrls: ["./linkedinLoginResponse.component.css"]
})
export class LinkedinLoginResponse implements OnInit {

  linkedInToken = "";
  
  constructor(private route: ActivatedRoute) {}
  
  ngOnInit() {
    this.linkedInToken = this.route.snapshot.queryParams["code"];
  }
  
}

2.2: Setup Routes in your app module

app.module.ts

...
import { Routes, RouterModule, Router } from "@angular/router";
...
import { LoginComponent } from "./login/login.component";
import { LinkedinLoginResponse } from "./linkedinLoginResponse/linkedinLoginResponse.component";

const routes: Routes = [
  { path: "", redirectTo: "/login", pathMatch: "full" },
  { path: "login", component: LoginComponent },
  { path: "linkedInLogin", component: LinkedinLoginResponse }
];

@NgModule({
  declarations: [AppComponent, LoginComponent, LinkedinLoginResponse],
  imports: [BrowserModule, RouterModule.forRoot(routes)],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

Don't forget to put router-outlet in app.component.html

app.component.html

<router-outlet></router-outlet>

Full code available: https://github.com/debojyoti/angular_linkedin_login

Step-3: Configure backend to complete the process

Once we get the authoriazation_code from linked in we need to send the authoriazation_code to our backend service which will exchange the auth token and get user details (name, email etc) from linkedin.

3.1: Send the authoriazation_code to backend service

3.2: Exchange auth token from linkedin

Send a post request to https://www.linkedin.com/oauth/v2/accessToken with params

{
    grant_type: "authorization_code",  // value of this field should always be: 'authorization_code'
    code: "The authorization code you received from client side",
    redirect_uri: "https://y8pud.codesandbox.io/linkedInLogin",  // The same redirect_url used in step 2.1 (in login.component.ts)
    client_id: 'Client ID of your linkedapp', // Follow step 1.2
    client_secret: 'secret key of your linkedapp'   // Follow step 1.2
}

A successful access token request returns a JSON object containing the following fields:

access_token — The access token for the application. This value must be kept secure as specified in the API Terms of Use. expires_in — The number of seconds remaining until the token expires. Currently, all access tokens are issued with a 60 day lifespan.

3.3: Get user details and access other linkedin rest APIs

For complete documentation, visit: https://developer.linkedin.com/docs/rest-api

@debojyoti
Copy link
Author

debojyoti commented Feb 22, 2021

Hi @kapilSoni101. Thanks for the information.
As I can check, linkedin has updated their social auth API a bit.

So now instead of a state, you need to send a scope.
Here is the updated url structure: https://www.linkedin.com/uas/oauth2/authorization?response_type=${linkedInConfig.response_type}&client_id=${<YOUR APP CLIENT ID>}&redirect_uri=${<YOUR APP REDIRECT URI>}&scope=${<SCOPES>}

For example if you need to get the email and basic information of the user, you can use this scope value = r_liteprofile%20r_emailaddress%20w_member_social

You can check more on scopes here: https://docs.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow

I have also updated the gist with scope param.

@kapilSoni101
Copy link

Hi @debojyoti thanks for ur update. now i have modified code and got new issue is generated please check below screenshort:

clinet-id

@paragnairdev
Copy link

Hi @debojyoti thanks for ur update. now i have modified code and got new issue is generated please check below screenshort:

clinet-id

Can you post the screenshot of this page (not the console). The screenshot of the page on LinkedIn which says "Bummer something went wrong" Shows you what you have requested. That will give me an Idea what has been sent wrong to LinkedIn.

Moreover, state is not Your Application ID. It can be any random string. Everytime you generate the URL, you should preferably generate a random string for state.
Refer Step 2: Request an Authorization Code
Also, it is very important for you to pass scopes which YOU have requested for the App. You will find this information in OAuth 2.0 scopes section of your App on LinkedIn. E.g: if you have the following settings for your app
Client Id: 57pk5wtpwynx7o
Callback Url: http://www.mywebsite.com/linkedin/callback

If your scopes are: r_emailaddress and r_liteprofile, your url to LinkedIn should be

https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=57pk5wtpwynx7o&redirect_uri=http://www.mywebsite.com/linkedin/callback&state=some-random-string&scope=r_liteprofile%20r_emailaddress

Hope this solves your problem

@kapilSoni101
Copy link

Hi @paragnairdev:
1.I have share screenshort of "Bummer something went wrong":
scopeerror

  1. I have properly set Client Id and Callback Url in the OAuth 2.0 scopes section of your App on LinkedIn.
  2. If i modified below url with my credentials got same error again
    https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=57pk5wtpwynx7o&redirect_uri=http://www.mywebsite.com/linkedin/callback&state=some-random-string&scope=r_liteprofile%20r_emailaddress

please check and let me know whats the wrong?

@paragnairdev
Copy link

paragnairdev commented Feb 22, 2021

Hi @paragnairdev:
1.I have share screenshort of "Bummer something went wrong":
scopeerror

  1. I have properly set Client Id and Callback Url in the OAuth 2.0 scopes section of your App on LinkedIn.
  2. If i modified below url with my credentials got same error again
    https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=57pk5wtpwynx7o&redirect_uri=http://www.mywebsite.com/linkedin/callback&state=some-random-string&scope=r_liteprofile%20r_emailaddress

please check and let me know whats the wrong?

It is telling you that your scope is wrong unauthorized_scope_error. It seems the scope you have set on your app on LinkedIn does not match the scopes you are requesting. The scopes should match what you have set on your app in OAuth 2.0 scopes section
image

You might have setup your app for r_basicprofile in place of r_liteprofile

@kapilSoni101
Copy link

kapilSoni101 commented Feb 22, 2021

Hi @paragnairdev ,
As per our last information i have added r_emailaddress and r_liteprofile in the OAuth 2.0 scopes section check below screenshort:

updated screeen

My code flow>

  1. Header componenet > After click login> model is showing then click linked> below code used after click:
 loginWithLinkedIn() {
    window.location.href = `https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=${
      this.linkedInCredentials.clientId
    }&redirect_uri=${this.linkedInCredentials.redirectUrl}&state=8983***&scope=${this.linkedInCredentials.scope}`;
  }  
  1. home component> in which we have to used as redirect_URL>
    ` console.log(this.route.snapshot.queryParams["code"]);

after call loginWithLinkedIn function in the URL code is showing but not received in the queryParams["code"] i received undefined again but in the URL its showing code check blow screenshort :

received ode
`
can you tell me what the issue on that?

@paragnairdev
Copy link

Hi @paragnairdev ,
As per our last information i have added r_emailaddress and r_liteprofile in the OAuth 2.0 scopes section check below screenshort:

updated screeen

My code flow>

  1. Header componenet > After click login> model is showing then click linked> below code used after click:
 loginWithLinkedIn() {
    window.location.href = `https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=${
      this.linkedInCredentials.clientId
    }&redirect_uri=${this.linkedInCredentials.redirectUrl}&state=8983***&scope=${this.linkedInCredentials.scope}`;
  }  
  1. home component> in which we have to used as redirect_URL>
    ` console.log(this.route.snapshot.queryParams["code"]);

after call loginWithLinkedIn function in the URL code is showing but not received in the queryParams["code"] i received undefined again but in the URL its showing code check blow screenshort :

received ode
`
can you tell me what the issue on that?

You should be using this.route.snapshot.queryParamMap.get('code') to get the code from the URL (route is of type ActivatedRoute)

@kapilSoni101
Copy link

kapilSoni101 commented Feb 23, 2021

Hi @paragnairdev,
After use this.route.snapshot.queryParamMap.get('code') i received null.
i notice that if am in below URL on that time HomeComponent is not triggered but after time HomeComponent is triggered but after home all data is removed:

http://localhost:4200/home?code=AQQUIxIaHUwg87qF3saD--DnRUyaHMKa_mdrJ0cdLU6Ywuo-FJQzBvuiJlTZ3ugASl-qpPyvpUqpHnUgxaNR2LX11F_IKKqCwqOt_cIOLmHnEKTa-o8fHy18t9-tlZ6-7AFFITs4grZTMhJpYwQMn__kZZBe7VYFHgs7x0uWoPXbPZRar1r87HlY3J_Rsqq09bO3RD7LCFhy8RlppbU&state=8983***

now can you tell me why showing nulll now?

@paragnairdev
Copy link

It seems like your routing is configured in a way which is redirecting that /home to some other component. Do you have a route home setup to load HomeComponent? Unfortunately, I cannot figure just looking at bits of your code. Is it possible for you to create a minimalistic public repository with your setup and share it? The issue you are facing no longer seems to be with LinkedIn SignIn, this seems beyond that, something with your angular routing.

@kapilSoni101
Copy link

Hi @paragnairdev:
Yes ur correct actually issue inside home component in ngOnInit function where i have load the home component again so its minor mistake at my code check below code snippet,after comment the code token is received properly without any issue and now linkedin is working correctly.

if(!this.service.isLoggedIn()){
    this.router.navigateByUrl('/home');
   }

once again thanks for ur valuable help.

@hkansal27
Copy link

Hi @debojyoti,

Thank you for your well written documentation. Using your documentation, I successfully integrated the LinkedIn login.

During integration, I find out that, you made a minor mistake in linkedIn OAuth URL. You forget to add $ symbol in the scope param. You write scope={this.linkedInCredentials.scope}, but it should be scope=${this.linkedInCredentials.scope}.

@anas012
Copy link

anas012 commented Jan 4, 2023

Hii.. I am getting cors error when trying to get access token from linkedin using angular.
here is the image of error.
Screenshot_1

@paragnairdev
Copy link

Hii.. I am getting cors error when trying to get access token from linkedin using angular. here is the image of error. Screenshot_1

looks like you are trying to make an ajax call to the accesstoken endpoint from javascript. If you see the example it says you need to configure your BACKEND which would be your server. In theory, the post request to https://www.linkedin.com/oauth/v2/accessToken needs to be made from your API (which might be in node or .net or some serverside language) not by your client side code.

@anas012
Copy link

anas012 commented Jan 4, 2023 via email

@RamandeepSidhu
Copy link

RamandeepSidhu commented Aug 30, 2023

@pacoyx
Copy link

pacoyx commented Feb 10, 2024

"scopes_supported": [
"openid",
"profile",
"email"
],

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment