Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

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

1.1: Go to https://developer.linkedin.com

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

@angelina-tsuboi
Copy link

angelina-tsuboi commented Feb 4, 2021

Thank you so much! Thanks to you Linkedin authentication works in my project :)

@kapilSoni101
Copy link

kapilSoni101 commented Feb 19, 2021

sir can you tell me which id put inside state ?

@paragnairdev
Copy link

paragnairdev commented Feb 19, 2021

sir can you tell me which id put inside state ?

It can be any unique id. It does not matter what it is, its just that the same id is returned to you with the authentication code when LinkedIn member authorizes your app. This is for you to check if the redirect response originated from your original LinkedIn sign in request.

@kapilSoni101
Copy link

kapilSoni101 commented Feb 20, 2021

@paragnairdev:ok sir now i have properly set the state id but i received undefined value in the linkedinLoginResponse component
i have set below url in the Redirect URL
http://localhost:4200/home
can you tell me why i received undeifined value instead of linkedInToken in linkedinLoginResponse component?

@paragnairdev
Copy link

paragnairdev commented Feb 20, 2021

@paragnairdev:ok sir now i have properly set the state id but i received undefined value in the linkedinLoginResponse component
i have set below url in the Redirect URL
http://localhost:4200/home
can you tell me why i received undeifined value instead of linkedInToken in linkedinLoginResponse component?

Difficult to say without looking at your source code. Do you have a sample of your code somewhere I can look and advise?

@debojyoti
Copy link
Author

debojyoti commented Feb 20, 2021

HI @kapilSoni101. Can you please specify what did you mean by which id put inside state
Are you asking about the client_id in

{
    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
}

@kapilSoni101
Copy link

kapilSoni101 commented Feb 22, 2021

Hi @debojyoti :
Actually i have only client_id and client_secret_key that the reason i asked about which id put inside state.i have properly done step1 and step2 but the step2 i received undefined linkedInToken.in above login function state=98765432
right now i have put state id from below URL

https://www.linkedin.com/developers/apps/898362**/auth
in the above url i used 898362** code as state id.
can you please tell me my state id is correct or not,if wrong so how to get correct state id and if i am correct so how to fix this issue?
and step 3 is still not implemented because i didn`t received the code: "The authorization code you received from client side"?

@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

kapilSoni101 commented Feb 22, 2021

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

paragnairdev commented Feb 22, 2021

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

kapilSoni101 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?

@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

paragnairdev 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?

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

paragnairdev commented Feb 23, 2021

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

kapilSoni101 commented Feb 23, 2021

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

hkansal27 commented Apr 29, 2021

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}.

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