I am trying to get access token following the steps described in Linkedin Oauth. I am trying to perform step 2 in the process to get an access token. I am using Axios for the POST request. Here is the code I am using (The client secret and id is not real for security reasons):
const axios = require('axios');
const qs = require('qs');
axios({
method: 'post',
url: 'https://www.linkedin.com/oauth/v2/accessToken',
data: qs.stringify({
grant_type: 'authorization_code',
code: 'AQSow7V6s2F2koWzIsnVKcQGt_cHtsM1F3FHZOrEV0UY1KIFkWiFJpi8dt1NtjuZMOO6-NStoCjTf58awk6GBcH2XQRctt7IBtel4Oeop5yVIBqiedk8qxlIlbkMxlfGg1gCVoupXL6xUc3-jegKYDPSe0rl4mygdpIzGdej2_hhJ827vJcojtvaMXCCGw',
redirect_uri: 'https%3A%2F%2Fwww.linkedin.com%2Fcompany%2Ftttrrr878',
client_id: '99blt2z20qlm3d',
client_secret: 'fGGgdqqcx5t3cRfw'
}),
headers: {
content-type: 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then(result => {
console.log(result.data);
}).catch(error => {
console.log(error);
});
I get the following error when I run the code even after making sure that the code is not expired (before the 30 min expiration time):
data: {
error: 'invalid_redirect_uri',
error_description: 'Unable to retrieve access token: appid/redirect uri/code verifier does not match authorization code. Or authorization code expired. Or external member binding exists'
}
However when I do the same thing using curl in the command line as follows, I am able to get the access code:
curl -ik -X POST https://www.linkedin.com/oauth/v2/accessToken \
-d grant_type=authorization_code \
-d code=AQSow7V6s2F2koWzIsnVKcQGt_cHtsM1F3FHZOrEV0UY1KIFkWiFJpi8dt1NtjuZMOO6-NStoCjTf58awk6GBcH2XQRctt7IBtel4Oeop5yVIBqiedk8qxlIlbkMxlfGg1gCVoupXL6xUc3-jegKYDPSe0rl4mygdpIzGdej2_hhJ827vJcojtvaMXCCGw \
-d redirect_uri=https%3A%2F%2Fwww.linkedin.com%2Fcompany%2Ftttrrr878 \
-d client_id=99blt2z20qlm3d \
-d client_secret=fGGgdqqcx5t3cRfw
Any idea why this is happening? Is it somehow related to this
issue ?
Your code looks correct. The issue is because you are url encoding the redirect_uri parameter, remove that and it should work.
You only need to url encode the redirect_uri parameter when doing the initial request for the access code from the browser.
Related
I'm attempting to convert this CURL command
curl -X POST "https://serverless-upload.twilio.com/v1/Services/ZS5798711f7bee1284df67427071418d0b/Assets/ZH4912f44da25f4b1a1c042a16a17f2eac/Versions" \
-F Content=#./mapping/mapping.json; type=application/json \
-F Path=mapping.json \
-F Visibility=private \
-u username:password
into a post request using the package axios,
I've tried
url = `https://serverless-upload.twilio.com/v1/Services/${service_uid}/Assets/${asset_uid}/Versions`
data = {
'Path': 'mapping.json',
'Visibility': 'private',
'Content': JSON.stringify(mapping),
'filename': 'mapping.json',
'contentType': 'application/json'
}
await axios.post(url, data, {
auth : {
user: `${accountSid}:${authToken}`
},
headers: {
'Content-Type': 'multipart/form-data',
}
}).then((r) => console.log(r));
but I'm unsure if this is malformed or not
Twilio developer evangelist here.
The Twilio Node library actually uses axios under the hood, you can see it in action in the RequestClient. We also have a stand-alone Serverless API client which is part of the Twilio Serverless Toolkit you can use, but it is written with got instead.
You can use the Serverless API module to save yourself the work of recreating this request.
If you decide to continue with axios, here are the changes you should make.
Auth
Authorization is done via the Authorization header, passing a base 64 encoded string made up of the account Sid and auth token.
headers: {
Authorization: 'Basic ' + Buffer.from(`${accountSid}:${authToken}`).toString('base64')
}
Data
When uploading an asset, it is done as multipart form data. To build up multipart data in Node.js you can use the form-data module. Something like this should work:
const FormData = require("form-data");
const form = new FormData();
form.append("Path", "mapping.json");
form.append("Visibility", "private");
form.append("Content", JSON.stringify(mapping));
form.append("filename", "mapping.json");
form.append("contentType", "application/json");
await axios.post(url, form, {
headers: {
Authorization: 'Basic ' + Buffer.from(`${accountSid}:${authToken}`).toString('base64'),
...form.getHeaders(),
},
}).then((r) => console.log(r));
Let me know how you get on with that.
I am trying to get recipe nutritional information from Edamam API. In the API docs, the cURL command is:
curl -d #recipe.json -H "Content-Type: application/json" "https://api.edamam.com/api/nutrition-details?app_id=${YOUR_APP_ID}&app_key=${YOUR_APP_KEY}"
I am using Axios and Javascript to try to access the API with a Post command:
import axios from "axios";
var postData = './recipe.json'
let axiosConfig = {
headers: {
'Content-Type': 'application/json;charset=UTF-8',}
};
axios.post('https://api.edamam.com/api/nutrition-details?app_id=XXXXXXXX&app_key=XXXXXXXXXXXXXXXXXXXXX', postData, axiosConfig)
.then((res) => {
console.log("RESPONSE RECEIVED: ", res);
})
.catch((err) => {
console.log("AXIOS ERROR: ", err);
})
I receive a 400 error back. Any thoughts on what I need to do to make this work would be appreciated.
postData needs to be a string of JSON.
You appear to be passing it a string containing a filename.
You might want to read './recipe.json' with axios.get() to fetch the data from it.
In your cURL the option -d #recipe.json is sending the content of the file recipe.json
But, In your Code postData = './recipe.json', You are just passing the name instead of reading it.
First you need to read the data from recipe.json,Then you need to send it through request.
I'm sort of new to REST..
For full disclosure, I'm running this code inside of a Netlify Lambda function and testing via netlify-lambda.
My curl command works:
curl -u "<username>:<password>" https://api.github.com/repos/<username>/<reponame>
But when I attempt a get request via axios I'm getting a 404 (which according to github docs implies an auth issue). This is what I'm doing (also doesn't work without the custom headers, I've just been trying random things).
axios({
method: "get",
url: `https://api.github.com/repos/${user}/<reponame>/`,
headers: {
Authorization: `Bearer ${githubToken}`,
"Content-Type": "application/json"
},
auth: {
username: user,
password: pass
}
})
.then(res => {
callback(null, {
statusCode: 200,
body: JSON.stringify(res.data)
});
})
.catch(err => {
callback(err);
});
One thing I noticed was that it seems axios was taking my username and password and prepending them to the url i.g. https://<username>:<password>#api.github.com/repos/<username>/<reponame>
Is this how auth should be sent over?
I shouldn't have had a trailing forward slash at the end of my URL.
If you already have a token you don’t need user/pass, just add the token to the header.
Is it possible to make a curl request by using axios?
the curl string is:
curl -v 'https://developer.api.autodesk.com/authentication/v1/authenticate' --data 'client_id=1234&client_secret=1234&grant_type=client_credentials&scope=bucket:create bucket:read data:write data:read viewables:read' --header 'Content-Type: application/x-www-form-urlencoded' -k | jq '.'
I tried to do this:
getToken() {
axios.get({
url: 'https://developer.api.autodesk.com/authentication/v1/authenticate',
data: {
client_id: '1234',
client_secret: '1234',
grant_type : 'client_credentials',
scope: 'data:read data:viewables'
},
beforeSend: function(xhr) {
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
}, success: function(data){
console.log(data)
}
})
}
But with no luck - e.g. nothing happens.
I previously used the cygwin-terminal to make the curl-request and I succesfully got the response
{
"token_type": "Bearer",
"expires_in": 1799,
"access_token": "eyJhbGciOiJIUzI1NiIsImtpZCI6Imp3dF9zeW1tZXRyaWNfa2V5X2RldiJ9.eyJjbGllbnRfaWQiOiJjWTFqcm1rQXhPSVptbnNsOVhYN0puVURtVEVETGNGeCIsImV4cCI6MTQ4NzU2NzgwMSwic2NvcGUiOlsiZGF0YTpyZWFkIl0sImF1ZCI6Imh0dHBzOi8vYXV0b2Rlc2suY29tL2F1ZC9qd3RleHAzMCIsImp0aSI6InJZcEZZTURyemtMOWZ1ZFdKSVVlVkxucGNWT29BTDg0dFpKbXlmZ29ORW1MakF0YVVtWktRWU1lYUR2UGlnNGsifQ.uzNexXCeu4efGPKGGhHdKxoJDXHAzLb28B2nSjrq_ys"
}
So, is this possible with React/axios?
In addition to the question, can I pass the received token to another curl request?
Well it's not really "a curl request". It's an HTTP request. Curl is just the tool you use to do HTTP (and other) actions via the command line.
In your HTTP request, I can see you're using axios.get(), however you're trying to do a post request (you've got a data object you're trying to send). So you should be using axios.post(). It'd be best to check out the axios page to see the syntax for HTTP posts, including how to include the data and header objects in the post.
In answer to your second question, yes you can. In the .then() section of your first axios post, you can do another axios post using the response, e.g.
axios.post(
...
).then(response => {
// do another post with response.token or whatever as the data
})
...
I am trying to implement a google oauth 2.0 login without using any libraries in my Node.js application.
I have created an app on the Google API console with the redirect url as http://localhost:3000. During login my response_type is code which returns a one-time use code that needs to be exchanged with the token_endpoint as described here.
The exchange is done on my node.js server with the following snippet.
axios({
url: 'https://www.googleapis.com/oauth2/v4/token',
method: 'post',
data: {
code: code,
client_id: sso.clientId,
client_secret: sso.clientSecret,
redirect_uri: sso.redirect_uri,
grant_type: 'authorization_code',
}
})
.then((response) => {
console.log(response.data);
})
.catch(function(err) {
console.log(err.response.data);
});
But this is is sending me back an error response of
{
"error": "unsupported_grant_type",
"error_description": "Invalid grant_type: "
}
instead of the user token.
Please help me identify the issue.
I tried doing a POSTMAN query as well with the same payload in the raw with content-type set to application/json, and it gave me the same error.
You need to use params in place of your data while making your exchange call through axios, revised block will be like
params: {
code: code,
client_id: sso.clientId,
client_secret: sso.clientSecret,
redirect_uri: sso.redirect_uri,
grant_type: 'authorization_code',
}
Hope this helps!
NEVER include things like a clientSecret in GET parameters. This can lead to serious security issues !
The google doc is very clear about how to send the data ;
As a POST body - as always in OAuth2 :
https://developers.google.com/identity/protocols/OAuth2WebServer - Step 5, REST code sample
They must be sent as a string but in the POST body / data :
The string is the urlencoded parameters like
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https://yourOauth2redirectUrl.example.com/code&
grant_type=authorization_code