Reputation: 12352
It's not easy to use the official LinkedIn API and I cannot find a valid documentation.
Following the official documentation I created a new application in order to obtain the Client ID and Client Secret
When I now make a POST call through Postman to https://www.linkedin.com/oauth/v2/accessToken this is what I obtain:
{
"error": "invalid_grant_type",
"error_description": "The passed in grant_type is invalid"
}
Where am I wrong?
EDIT AFTER HELP FROM @Amit Singh
Thanks to @AmitSingh I was able to create 2 different applications, the test with the Client Credentials flow gave me as a result an error retrieving the token:
{
"error": "access_denied",
"error_description": "This application is not allowed to create application tokens"
}
When I try to use the LinkedIn 3-legged workflow I receive Unauthorized
EDIT 3: GETTING THERE THROUGH POSTMAN
I now see that I can ask Postman to do the job, however when I press on Get New Access Token
it opens an error page. I believe the error might be in these 4 elements:
Token name
: maybe I have to give a special token name?Auth URL
: I set https://www.getpostman.com/oauth2/callback
as explained here but maybe I have to set something else?Access Token URL
: I left it blank, maybe I have to put something here?State
: I set a random string like Hello123Boy
but maybe I have to put something else. Maybe is too long. Maybe is too short. Maybe it has to contain symbols, etc... ?...Also, in the guide you linked it says that the applicatoin needs to have:
mine has nothing:
Being recently created is still under review. It says it can take up to 90 days. Is that true?
4th EDIT: I WANT TO BELIEVE!
Here we are, at least now I'm getting the error: Bummer, something went wrong. The redirect_uri does not match the registered value
. This is amazing: finally an error that says where the problem is!
On the app the, on the Products tab, I choose Sign In with LinkedIn
. As
Authorized redirect URLs for your app I set https://www.getpostman.com/oauth2/callback
In Postman I setup Auth URL
and Access Token URL
as you said:
Upvotes: 6
Views: 14437
Reputation: 12352
Thanks to @timur and @AmitSingh I finally arrived to authenticate to LinkedIn API.
A brief step by step solution in pictures:
Authorized redirect URLs for your app = https://oauth.pstmn.io/v1/callback
OAuth 2.0 scopes = must have r_emailaddress
and r_liteprofile
In the Products Tab set Sign In with LinkedIn
Now open Postman > Collections > New Collection > Authorization and set the parameters as in picture:
OAUTH 2.0
https://oauth.pstmn.io/v1/callback
(should be greyed out once you tick Authorize using browser
)Authorize using browser
https://www.linkedin.com/oauth/v2/authorization
https://www.linkedin.com/oauth/v2/accessToken
r_liteprofile
r_emailaddress
Now click on Get New Access Token
, a page will open on your browser and you will be able to login using your LinkedIn account. Once done you are authenticated.
Now use the code provided by @timur and on Postman go to Import > Upload File and import that .JSON file. You will now have the 4 queries and you can drag and drop them in your collection.
Upvotes: 2
Reputation: 3063
LinkedIn offers 2 different credential workflows.
"Grant type" refers to how you have acquired an access token in an OAuth workflow.
Several grant types are supported. Some of them are:
Client Credentials - Used when you want to access your own resources and not any other users
Authorization Code - Used when an app wants to access a client's data
Refresh token - Exchange an expired access token for a valid access token, used to avoid repeated user involvement
Password - Used when there is high trust between the app and the user e.g. LinkedIn mobile app, you provide your username and password
client_credentials
.Content-Type
to application/x-www-form-urlencoded
for all POST requests in OAuth.Create an App and get your Client ID and Client Secret. Steps are shown in the respective docs linked above. Let's say they have values - <client_id>
and <client_secret>
.
Send a POST required to https://www.linkedin.com/oauth/v2/accessToken
with following information.
Parameters
grant_type : client_credentials
client_id : <client_id>
client_secret : <client_secret>
NOTE : client_credentials
is the literal text to be entered for grant_type
.
Response will return a JSON Object containing your access token and its expiry duration in seconds.
Response
{
"access_token" : <access_token>,
"expires_in" : "1800"
}
Use the <access_token>
obtained in Step 2 make API requests.
Example
Request URL: https://www.linkedin.com/v2/jobs
Request type: GET
Parameters
Authorization: Bearer <access_token>
Grant type will be Authorization code - code
, since you want to access a user's data.
Your Content-Type
should be application/x-www-form-urlencoded
for all POST requests in OAuth.
Redirect URLs are URLs where you OAuth server will redirect the user after successful authorization.
#
.Create app and provide the Redirect URLs, if not already provided. Check docs for information regarding how to do this.
Get your Client ID and Client Secret. Let's say the values are <client_id>
and <client_secret>
.
Generate a random, hard to guess string. Let's say it's <random-string>
.
Choose one of the redirect URLs provided in Step 1, where you want user to be redirected after authorization. Let's say it is <redirect_uri>
.
Let's suppose you want to:
r_emailaddress
- Get his email addressw_member_social
- Post, comment and like posts on behalf of the user.These are referred as "permission scopes", as in what permissions is the user authenticating you for. When sending these scopes in your request, they should be URL-encoded and space-delimited. In this particular instance, our scope will be scope: r_emailaddress%20w_member_social
. We have URL-encoded the scopes mentioned above.
Adding more information regarding scopes from the Microsoft docs:
The scopes available to your app depend on which Products or Partner Programs your app has access to. Your app's Auth tab will show current scopes available. You can apply for new Products under the Products tab. If approved, your app will have access to new scopes.
Send a POST request to https://www.linkedin.com/oauth/v2/authorization
with following information.
Parameters
response_type : code
client_id : <client_id>
redirect_uri : <redirect_uri>
state : <random_string>
scope : r_emailaddress%20w_member_social
After the request, the user will be presented with LinkedIn's Auth screen and asked to approve the request.
After user approves the request and the <redirect_uri>
has been verified, user will be redirected to provided <redirect_uri>
along with the access code <access_code>
and a value in state
argument. Let's say in the state argument is <state_value>
.
Verify that the <state_value>
is equal to the <random_string>
before working with the <access_code>
to get access token, for security purposes. Also, use the <access_code>
within 30 minutes of being issued, for security reasons.
Next, send a POST request to https://www.linkedin.com/oauth/v2/accessToken
with following information to get the access token.
Parameters
grant_type : authorization_code
client_id : <client_id>
client_secret : <client_secret>
redirect_uri : <redirect_uri>
code : <access_code>
NOTE : authorization_code
is the literal text to be passed in grant_type
.
You should get a similar response as in the Client Credentials workflow containing your access token and expiry duration.
Response
{
"access_token" : <access_token>,
"expires_in" : "1800"
}
Use the <access_token>
obtained in Step 9 make API requests.
Example
Request URL: `https://www.linkedin.com/v2/me`
Request type: GET
Parameters:
Authorization: Bearer <access_token>
Postman has been designed to make such operations easier, but you have to know how to do it. For more details, you can read their official docs.
Upvotes: 14
Reputation: 14577
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.
https://www.linkedin.com/oauth/v2/authorization
(you seem to have done that)x-www-form-urlencoded
datahttps://www.linkedin.com/oauth/v2/accessToken
and get access_token in responseFrom 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"
}
]
}
Upvotes: 0