How to access Wordpress authentication token - node.js

We are trying to link our website to Wordpresses API using OAuth 2.0. Hoping that a client can authenticate and post to WordPress from our site. We need to receive an access token to do this.
We have successfully connected with Wordpress to receive our access code. We've followed the Wordpress api, and have it working for a single user (with secret key not with OAuth). Things we have tried are adding a headers, changing data to different names examples: params, body
This is a simplified version of the code we have been using
const axios = require('axios');
axios({
method: "POST",
data: {
grant_type: 'authorization_code',
client_id: '12345',
client_secret: 'ABCABC1235412345',
code: 'Abc123',
redirect_uri: 'https://localhost:5000/wordpress/callback_wordpress'
},
url: 'https://public-api.wordpress.com/oauth2/token'
}).then( (response) => {
console.log(response);
}).catch( (error) => {
console.log(error);
});
We expect to receive a jwt access token, but instead are getting this 400 error:
data:
{ error: ‘invalid_client’,
error_description: ‘The required “client_id” parameter is missing.’ } } }
It seems clear that we are missing the client_id, however we have it included in our request. Is there somewhere else we need to include it?

var authOptions = {
url: 'https://public-api.wordpress.com/oauth2/token',
form:
{
grant_type: 'authorization_code',
code: code,
client_id: client_id,
client_secret: client_secret,
redirect_uri: redirect_uri,
},
headers: {
'Authorization': 'Basic ' + (Buffer.from(client_id + ':' + client_secret).toString('base64'))
},
json: true
};
We needed to include a header with that information, and we needed to use the variable 'form' instead of 'data'.

Related

When I use Discord OAuth2 I am getting error 400. How can I make this return the access_token correctly?

I am unable to get the clients identiy through discords oauth2. First we do this:
https://discord.com/api/oauth2/authorize?client_id=9999999999999&redirect_uri=http%3A%2F%2Fxxxx.xyz%2F&response_type=code&scope=identify
to get their code. Which seems to work fine.
let options = {
url: 'https://discord.com/api/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'client_id': '9999999999999',
'client_secret': 'MYSECRETHERE',
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'https://xxxx.xyz/callback',
'scope': 'identify'
}).toString()
};
await fetch("https://discord.com/api/oauth2/token", options)
.then(handleErrors)
.then(response => response.json())
.then(response => {
access_token = response.access_token;
}).catch(function(error) {
console.log(error);
});
What happens here is I get a error 400 instead of the access token. Originally the 'grant_type' was set as client_credientals but I realized that this only grabs the identity of the application owner itself, not others. This worked however. Changing it to authorization_code however does not.
Any suggestions?
Compared to the token exchange example, you are passing scope in the request – that shouldn't be there. Scope is passed only in the initial authorization URL.

401 failed request when trying to exchange authorization code for tokens w/ google

I'm struggling with this specific step in the Google OAuth process: "Exchange authorization code for tokens" (As called in Google Developers' "OAuth 2.0 Playground", Step 2).
function getGoogleAuthURL() {
const rootUrl = "https://accounts.google.com/o/oauth2/v2/auth";
const options = {
redirect_uri: `http://${HOST}:${PORT}/auth/google`,
client_id: `${googleConfig.clientId}`,
access_type: "offline",
response_type: "code",
prompt: "consent",
scope: defaultScope.join(" "), // A list of scopes declared in the file scope
};
return `${rootUrl}?${querystring.stringify(options)}`;
}
app.get("/auth/google/url", (req, res) => {
res.redirect(getGoogleAuthURL());
});
After redircting the user to the consent prompt, the code above redirect the user to: http://${HOST}:${PORT}/auth/google, giving the 'Authorization code' necessary to get the refresh and access tokens.
app.get(`/auth/google`, async (req, res) => {
const code = req.query.code
const tokens = await getTokens({code})
});
My problem is coming from the getToken() function that is used to POST and return the tokens.
function getTokens({code}) {
const url = 'https://accounts.google.com/o/oauth2/token';
const values = {
code,
client_id: googleConfig.clientId,
client_secret: googleConfig.clientSecret,
redirect_uri: googleConfig.redirect,
grant_type: 'authorization_code',
};
console.log(`${url}${querystring.stringify(values)}`)
return axios
.post(url, querystring.stringify(values), {
headers: {
'Content-Type': 'application/x-www-form-url-encoded',
},
})
.then((res) => res.data)
.catch((error) => {
throw new Error(error.message);
});
}
I get Error: Request failed with status code 401 from the .catch((error) ...
The console.log(${url}${querystring.stringify(values)}) gives the full built link, which is:
https://accounts.google.com/o/oauth2/tokencode=X&client_id=X.apps.googleusercontent.com&client_secret=X&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fdashboard%3B&grant_type=authorization_code
What I troubleshooted:
I've compared many times my 'request' and 'url' with the ones on Google Developers' "OAuth 2.0 Playground", and the syntax doesn't seem to be the problem with the fields, though I have doubt about the punctuation between /token and code=... that I changed to /token and ?code=..., but still resulting in a failed request (401).
I've also been using two different ${url}:
https://oauth2.googleapis.com/token
https://accounts.google.com/o/oauth2/v2/auth
But I can tell which one I should be using.
The second param of axios post is the body, not query params.
You can set params in the third argument.
axios.post(url, {}, {
headers: { 'Content-Type': 'application/x-www-form-url-encoded' },
params: {
tokencode: values.code,
// etc
}
}
You are also missing key for code in your values object.
You can also just append the querystring in the first argument:
axios.post(url + querystring.stringify(values),{}, {
headers: {
'Content-Type': 'application/x-www-form-url-encoded'
},
})

Instagram API: Invalid Platform App when fetching access token

I'm trying to log in using Instagram Basic Display API.
I'm trying to get the access_token, and I'm using axios:
const { code } = queryParams;
const url = `https://instagram.com/oauth/access_token`;
const result = await axios.request({
url,
method: 'POST',
data: {
'client_id': INSTAGRAM_CLIENT_ID,
'client_secret': INSTAGRAM_CLIENT_SECRET,
'grant_type': 'authorization_code',
'redirect_uri': 'https://localhost:3000/auth/instagram/token',
code,
},
});
I'm getting a 400 error, with the message invalid platform app. All the values sent exist and are correct.
My redirect_uri doesn't exist though, but it's added to the authorized URL list. It doesn't exist because I don't have https in my local server.
I had this same issue. The official example given by Instagram using curl uses the -F tag, which means that they are posting the data as the application/x-www-form-urlencoded content-type.
Every other post format I tried is ignored. Changing your code to post as a form and it should work.
There is a very good answer on this post
const querystring = require('querystring');
//Make Object with params const data = {
client_id: 'xxxxxxx',
client_secret: 'xxxxxxxxxxx',
grant_type: 'authorization_code',
redirect_uri: 'https://example.com/auth',
code: 'xxxx' }
//Make the Call
axios.post("https://api.instagram.com/oauth/access_token",
querystring.stringify(data)) .then(function (response) {
console.log("OK", response.data); }) .catch(function (error) {
console.log(error); });

error returned in postman to get access token but works in console for NodeJS

I am trying to access the token using authorization code after passing the authentication, it works in my console for nodejs using request-promise module however it doesnt work on postman it says
{
"error": "invalid_grant",
"error_description": "invalid authorization code"
}
however it works in the console for nodeJS
{"access_token":"eyJhbGciOiJIUzI1NiJ9.7DkDzFz89Y-W-HLlwnqA0YmA_mMrR8nZV44eC1gAJjEp2Zmq8SE9q0UmzXuU-hHuXseMNvpqQeRMhHeVTbn8J_ZCQmkkAgZ359CnKvnXe3mZoYAWM4oQbtJFefoa7mwsAEFKScyEaIqi1DqHTItVqZfbCYdzrbee88E2-pWteiE.CHAvVIanJrUlTZZ25LMUTzW7IO4qRGZ_B_wN7c5Kfkk","token_type":"Bearer","refresh_token":"uDhPe4dRJkUYB1rC9VuV","expires_in":2592000,"scope":"openid profile","id_token":"eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FjY2Vzcy5saW5lLm1lIiwic3ViIjoiVWU4NTUzNTBiNDIzYzI5ZjExYjIwZTgwZTJiZmE4MmQ1IiwiYXVkIjoiMTU1Njc5NDgxOCIsImV4cCI6MTUxNzkzMDc3MCwiaWF0IjoxNTE3OTI3MTcwLCJuYW1lIjoiSm9obiBCb3JqZSIsInBpY3R1cmUiOiJodHRwczovL3Byb2ZpbGUubGluZS1zY2RuLm5ldC8waG1URGV0bUpWTW50NUhCem5YUnhOTEVWWlBCWU9NalF6QVhJcVNBNGVQaDVSSzNRcFRINHVGQXdiUEI5V0pYTW9RWGgxR1Y5UGIwMVQifQ.mYUWJQ-YLrz4zEer5n1J-R3S1W37mDLx6g_mVmmWDTk"}
this is the code using nodeJS
var data = {
grant_type: "authorization_code",
code: qC,
redirect_uri: "https://sample.com/profile", //edited for security
client_id: 1, // edited for security
client_secret: "9" //edited for security
}
var options = {
method: 'POST',
url: 'https://api.line.me/oauth2/v2.1/token',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
// payload: 'grant_type=authorization_code&code="'+queryCode+'"&redirect_uri=https://line-poc-demo.herokuapp.com/profile&client_id=1556794818&client_secret=98760fb0cea2aebdf7848ecf93c19cf4',
form: data
}
//
rp(options)
.then(function (parsedBody) {
// POST succeeded...
console.log('bick dig' + parsedBody);
})
.catch(function (err) {
// POST failed...
console.log('err ' + err);
});
Is there something wrong with my code? Thank you, any help will be appreciated.

Google OAuth2: Required parameter is missing: grant_type

I have tried just about everything, read every StackOverflow post on this issue but I still can't get it to work. Interestingly enough, I am able to get 200 OK response when sending a POST request via DHC REST API Client (Google Chrome app).
var url = 'https://accounts.google.com/o/oauth2/token';
var params = querystring.stringify({
grant_type: 'authorization_code',
code: req.body.code,
client_id: req.body.clientId,
client_secret: 'HIDDEN',
redirect_uri: req.body.redirectUri
});
params = querystring.unescape(params); // doesn't work with or without string escaping
request.post(url + '?' + params, function(error, response, body) {
console.log(body);
});
As #BenFortune has already mentioned, I was sending GET parameters as a POST request. It's amazing such a trivial thing has gone unnoticed after trying to figure it out for over an hour.
Now, I blame inconsistencies across OAuth providers for this. In the same application I am doing a GET request to Facebook to obtain access_token: https://graph.facebook.com/oauth/access_token. But Google expects a POST request to obtain access_token: https://accounts.google.com/o/oauth2/token
Correct version:
var url = 'https://accounts.google.com/o/oauth2/token';
var payload = {
grant_type: 'authorization_code',
code: req.body.code,
client_id: req.body.clientId,
client_secret: 'HIDDEN',
redirect_uri: req.body.redirectUri
};
request.post(url, { form: payload }, function(error, response, body) {
console.log(body);
});
Check the request Encoding.
in my case i was sending .json and was .url
Using Alamofire 3.0

Resources