Assuming you've created your app, added correct redirect URL and enabled "Sign In with LinkedIn" product for your app, the issue you are having is probably that the first call returns a login page where your users are supposed to authenticate.
- submit the request to
https://www.linkedin.com/oauth/v2/authorization
(you seem to have done that)
- parse response of step 1 and extract all form values, add username and password to simulate user login
- make POST request and use values from previous step as
x-www-form-urlencoded
data
- manually follow the redirect header from step 3
- make note of second redirect header but do not follow it - instead extract the code
- POST code from previous step to
https://www.linkedin.com/oauth/v2/accessToken
and get access_token in response
From here, I was able to successfully transition to the auth code by following the steps.
I am not sure if you use the online Postman, but here's my complete collection export file for reference:
{
"info": {
"_postman_id": "397761c9-4287-43f2-860a-3c34cb710d50",
"name": "Linkedin oAuth",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "01 request Login form",
"event": [
{
"listen": "test",
"script": {
"exec": [
"const $ = cheerio.load(pm.response.text());\r",
"var inputs = $('form').serializeArray();\r",
"var payload = '';\r",
"inputs.forEach(i => {\r",
" payload += encodeURIComponent(i.name)+ '=' + encodeURIComponent(i.value) + '&';\r",
"})\r",
"payload += 'session_key='+ encodeURIComponent(pm.collectionVariables.get('username')) + '&'\r",
"payload += 'session_password='+ encodeURIComponent(pm.collectionVariables.get('password'))\r",
"\r",
"pm.collectionVariables.set(\"form_data\", payload);"
],
"type": "text/javascript"
}
}
],
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id={{client_id}}&redirect_uri={{redirect_uri}}&scope=r_liteprofile&state={{$guid}}",
"protocol": "https",
"host": [
"www",
"linkedin",
"com"
],
"path": [
"oauth",
"v2",
"authorization"
],
"query": [
{
"key": "response_type",
"value": "code"
},
{
"key": "client_id",
"value": "{{client_id}}"
},
{
"key": "redirect_uri",
"value": "{{redirect_uri}}"
},
{
"key": "scope",
"value": "r_liteprofile"
},
{
"key": "state",
"value": "{{$guid}}"
}
]
}
},
"response": []
},
{
"name": "02 Submit login form",
"event": [
{
"listen": "prerequest",
"script": {
"exec": [
""
],
"type": "text/javascript"
}
},
{
"listen": "test",
"script": {
"exec": [
"var url = 'https://www.linkedin.com'+ pm.response.headers.get(\"Location\");\r",
"pm.collectionVariables.set('first_redirect', url);\r",
"//console.log(pm.collectionVariables.get('first_redirect'));"
],
"type": "text/javascript"
}
}
],
"protocolProfileBehavior": {
"followRedirects": false
},
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/x-www-form-urlencoded",
"type": "text"
}
],
"body": {
"mode": "raw",
"raw": "{{form_data}}",
"options": {
"raw": {
"language": "text"
}
}
},
"url": {
"raw": "https://www.linkedin.com/checkpoint/lg/login-submit",
"protocol": "https",
"host": [
"www",
"linkedin",
"com"
],
"path": [
"checkpoint",
"lg",
"login-submit"
]
}
},
"response": []
},
{
"name": "03 handle login-success redirect",
"event": [
{
"listen": "test",
"script": {
"exec": [
"var sdk = require('postman-collection');\r",
"var redirect = new sdk.Url(pm.response.headers.get(\"Location\"));\r",
"pm.collectionVariables.set('code', redirect.query.filter(q => q.key === 'code').map(k => k.value)[0]);\r",
"//console.log(pm.collectionVariables.get('code'));"
],
"type": "text/javascript"
}
},
{
"listen": "prerequest",
"script": {
"exec": [
"console.log(pm.variables.get('first_redirect'));\r",
"pm.request.url.update(pm.variables.get('first_redirect'));"
],
"type": "text/javascript"
}
}
],
"protocolProfileBehavior": {
"followRedirects": false
},
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{first_redirect}}",
"host": [
"{{first_redirect}}"
]
}
},
"response": []
},
{
"name": "04 Get Auth Code",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&code={{code}}&redirect_uri={{redirect_uri}}&client_id={{client_id}}&client_secret={{client_secret}}",
"protocol": "https",
"host": [
"www",
"linkedin",
"com"
],
"path": [
"oauth",
"v2",
"accessToken"
],
"query": [
{
"key": "grant_type",
"value": "authorization_code"
},
{
"key": "code",
"value": "{{code}}"
},
{
"key": "redirect_uri",
"value": "{{redirect_uri}}"
},
{
"key": "client_id",
"value": "{{client_id}}"
},
{
"key": "client_secret",
"value": "{{client_secret}}"
}
]
}
},
"response": []
}
],
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
}
],
"variable": [
{
"key": "client_id",
"value": "your app id"
},
{
"key": "client_secret",
"value": "your app secret"
},
{
"key": "redirect_uri",
"value": "your urlencoded redirect uri such as https%3A%2F%2Flocalhost%3A8080"
},
{
"key": "username",
"value": "user login"
},
{
"key": "password",
"value": "user password"
}
]
}
redirect_uri
andcode
tohttps://www.linkedin.com/oauth/v2/accessToken
- i believe both are required – Rovergrant_type
is set to your email ID where as the documentation explicitly says that it should be set toclient_credentials
and nothing else. – Merrileemerriliclient_credentials
means? Should I putemail:password
oremail&password
or justemail
or justpassword
? 2) What aboutclient_id
? An example would be easier and will be less back and forward for everyone. I just want to have some code that I can paste and works – Paryavihttps://www.linkedin.com/oauth/v2/authorization
and access token URL should be set tohttps://www.linkedin.com/oauth/v2/accessToken
. Token name and state can be anything no issues with that. – Merrileemerrilir_liteprofile
andr_emailaddress
. Marketing APIs need approval from LinkedIn before they can be used by you. Request for theSign In with LinkedIn
for those scopes. – MerrileemerriliSign In With LinkedIn
andShare on LinkedIn
do not require approval and they have the basic scopes that you might want. For more info, check their docs. – MerrileemerriliSign in with LinkedIn
requires approval snipboard.io/SRoLEz.jpg . Anyway, I feel I'm getting there. I will let you know – Paryavi