Api for fetching github repos not working in Node.js - node.js

I have registered my app in Oauth in github
//#router GET api/profile/github/:githubUsername
//#desc get github profile
//#access public
router.get('/github/:githubUsername', (req,res)=>{
try {
const options = {
uri:`https://api.github.com/users/${req.params.githubUsername}
/repos?per_page=5&sort=created:asc&client_id=${config.get('githubClientId')}
&client_secret=${config.get('githubSecretKey')}`,
method: 'GET',
headers: { 'user-agent':'node.js' }
};
request(options, (err, response, body)=>{
if(err) console.error(err)
if(response.statusCode!==200) return res.status(404).json({msg : 'Github user not found'})
res.status(200).json(JSON.parse(body));
})
} catch (error) {
console.log(error);
res.status(500).send('Server Error');
}
})
This URL is working when used directly in browser.
It is giving status 404. I have checked with clientId and secret key they are working fine. I am also not sure about what URL to be pasted in Callback URL in github OAuth apps.
Thanks in advance.

The url line break was the problem. Thanks!

Related

Reactjs + Express Twitter API "Could not authenticate you."

I am trying to create a very simple app that allows me to post a tweet. I am currently using React running on port 3000 and express server.js running on port 5000
my server.js has the following:
app.post("/twitter/message", async(req, res) => {
const tweet = req.body.tweet;
try {
const response = await postToTwitter(tweet);
res.json({
message: 'Tweet successfully posted to twitter'
});
} catch (error) {
res.status(500).json({
message: 'Not able to post'
});
}
});
function postToTwitter(tweet) {
client.post(
"statuses/update",
{ status: tweet },
function (error, tweet, response) {
if (error) log(error);
/* log(tweet); // Tweet body. */
}
);
}
I am then using a script on the index.html page to post the input tweet:
<script>
$('button').on('click', (event) => {
event.preventDefault();
const tweet = $('#tweet').val();
// Post Tweet
$.ajax({
url: '/twitter/message',
method: 'POST',
data: {
tweet
}
})
.then(() => {
alert('Data successfully posted');
console.log('Data successfully posted');
})
.catch((error) => {
alert('Error: ', error);
console.log('Error: ', error);
});
})
</script>
This however is giving me the bellow error when I hit the post button:
[ { code: 32, message: 'Could not authenticate you.' } ]
If I use this exact same setup with just express it works perfectly fine, the issue occurs when trying to use react. Any help would be amazing.
It is possibly a CORS issue (which would show up in the frontend but not in Node/Backend).
If you're using some sort of API key to make the API request you're not showing it in this sample (don't show people your API key). By similar logic, do not have your API key on the client side, as anyone downloading your website would then have your Twitter API key. Instead, for multiple reasons it is better to have the backend be the one to make the API requests with your API key.
On the other hand if users are supposed to authenticate via O-Auth and you're supposed to pass a cookie with your authentication make sure you useCredentials on the request. axios.post(BASE_URL + '/api', { withCredentials: true }); . Looks like you're using jquery so add the same withCredentials:
Try adding this to your options:
crossDomain: true,
xhrFields: {
withCredentials: true
},
If you don't see a cookie when you type document.cookie in the browser that's probably a sign you're not authenticated in your computer.

CORS Error in a working setup while trying to authenticate using Google+ API in React/Node setup

I was implementing the Oauth2.0 authentication using Google. I used react-google-login npm on the frontend to authenticate the user using Google Oauth2.0. I successfully created the CLient-id and secret under google cloud platform for my project, along with the URI as needed.
The frontend is running on default localhost:3000 and backend (node/express) running on localhost:9001 with proxy enabled on frontend to redirect the request to backend.
I was able to authenticate using Google more than 2 dozen times last night as i was working on the backend siginIn contoller. I was also able to add the user to my Mongodb after successful authentication from Google.
All of a sudden, i was getting CORS error which is a bit strange as none of the code or Google configs were changed.
My Google config looks as follows.
My code on the frontend is still successfully redirecting the user to Google for authentication. Its also generating the right google credentials.
SignIn Component Code snippet passing the info to responseGoogle which resides in withLogin HOC Parent Component.
<GoogleLogin
clientId={GOOGLE_CLIENT_ID}
buttonText="Google"
render={(renderProps) => (
<button onClick={renderProps.onClick} style={customStyle}>
<img className="googleBtn" src={googleIcon} alt="GMAIL ICON" />
</button>
)}
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy={"single_host_origin"}
/>
withLogin HOC Parent Component dispatching the info to Redux thunk.
const responseGoogle = (res) => setGoogleResp(res);
useEffect(() => {
googleResp?.error &&
setValues({ ...values, serverError: "GOOGLE LOGIN FAILED" });
googleResp?.tokenId && dispatchGoogleSignInDataToBackend()
}, [googleResp]);
const dispatchGoogleSignInDataToBackend=async ()=>{
const data=await dispatch(allActions.googleSignInAction(googleResp,whoLoggedIn));
if (data.error) {
setValues({ ...values, serverError: data.error, success: false });
} else {
const {
email,
name,
_id,
role,
listOfEmailOfAllClientsForLawyerLogin,
} = data.userCred;
saveJwtToLocalStorage(
data.token,
{ name, email, _id, role, listOfEmailOfAllClientsForLawyerLogin },
() => {
setValues({
email,
serverError: false,
success: true,
});
}
);
}
}
I am sending the appropriate CORS header in the request to the backend.
export const dataHeaders = {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
"Access-Control-Allow-Headers" :"*"
};
Redux thunk code:-
export const googleSignInAction=(googleResp,whoLoggedIn)=>{
console.log("Login Success: currentUser:", googleResp);
return async (dispatch) => {
dispatch({ type: SIGNIN_LOADING });
try {
const response = await axios.post(
`${API_URL}/googlesignin`,
{
googleResp,
whoLoggedIn
},
{
headers: dataHeaders,
}
);
console.log("response inside googleSignInAction", response);
// CHANGED COZ OF ESLINT WARNING.
if (
response.status === 201 &&
Object.keys(response.data).includes("token") &&
Object.keys(response.data).includes("userCred")
) {
dispatch({ type: SIGNIN_SUCCESS, data: response.data });
return response.data;
} else {
dispatch({ type: SIGNIN_FAILED });
}
} catch (error) {
dispatch({ type: SIGNIN_FAILED });
return error.response.data;
}
};
}
API URL Points to following:-
export const API_URL="http://localhost:9001/api";
No request is reaching the backend because of CORS error.
Frontend receiving the Correct Response from Google Post authentication.
Errors on the Frontend.
Browsers will first send a pre-flight request to check CORS. In your backend code, you have to allow the front-end host and port. In this case localhost:3000.
The reason you are getting the cors error is bacause its on two different ports.
But if proper cors response is given by backend (port 9000), it will resolve.
Clearing the browser cookies and cache made everything work again. googlesignin is working without cors error. I have added following line of code to serve all static files from backend to frontend.
app.use(express.static(path.join(__dirname, '../frontend/public')));

'Login Required' error. How to login after getting oauth2 token with Google API

I'm building a small Node/React app where I'm trying to implement OAuth2 Google to request the Google Analytics API. I'm using Passport.js to handle the authentification.
I'm able to get the Token correctly:
router.get(
"/auth/google/callback",
passport.authenticate("google", { failureRedirect: "/error", session: false }),
function(req, res) {
var token = req.user.token;
res.redirect("http://localhost:5000/?token=" + token);
}
);
However, when trying to call the Google Analytics management API I have the following error Error: Login Required.
router.get('/getData', function(req, res) {
googleAccounts.management.profiles.list(
{
accountId: '~all',
webPropertyId: '~all'
},
(err, data) => {
if (err) {
console.error('Error: ' + err)
res.send('An error occurred')
} else if (data) {
Console.log(data)
}
}
)
})
How do I login? What step I'm missing?
You aren’t sending the access token, unless you’re using the gapi’s inbuilt auth, you have to send the access token manually in a HTTP authorization header.
Please use the following snippet to achieve the same.
function listViews() {
gapi.client.setToken{
access_token: <access-token>
})
... rest of the function

NodeJS SOAP client request with certificate

I'm trying to connect to a SOAP service which requires a certificate on my NodeJS project.
I'm using soap and this is how I'm trying to access to it:
const soap = require('soap');
(...)
let sslOptions = {
key: fs.readFileSync(keyPath),
cert: fs.readFileSync(certPath)
};
let sslHeaders = {
Authorization: {
user: 'Z100079',
pass: password
}
};
Service.GetLossRatio = function (contractID, start, end, asOf, cb) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
let args = {
contractID: contractID,
start: start,
end: end,
asOf: asOf
};
soap.createClientAsync(url,
{
//request : specialRequest,
wsdl_options: sslOptions,
wsdl_headers: sslHeaders
})
.then((client) => {
client.setSecurity(
new soap.ClientSSLSecurityPFX(
certCerPath
)
);
client.LossratioService.LossratioPort.calculate(args, (err, res) => {
if (err) {
console.log(err);
return cb(err);
}
console.log(res);
return cb(null, res);
});
})
.catch((e) => {
console.log(e);
cb(e);
});
};
And I'm getting a "Wrong Tag" Error when the LossratioPort.calculate() occurs.
I've no idea what that error means, I can't find much documentation about this specific situation, the "soap" documentation only show a brief explenation on how to make a request with certificates but there's not much more
I know the certificates are valid and I've tried with all the generated certificates from the .pem file (.p12, and .cer). I just want to be sure I'm getting something from the service. Either what I really want, or an error from the server, not from the api.
Any help?
Thanks in advance.
UPDATE:
I'm able to get the service description thorugh client.describe() though:
{"LossratioService":{"LossratioPort":{"calculate":{"input":"tns:calculate","output":"tns:calculateResponse"},"ping":{"input":"tns:ping","output":"tns:pingResponse"},"shakedownTest":{"input":"tns:shakedownTest","output":"tns:shakedownTestResponse"}}}}
I've also confirmed the inputs, and I'm sending as the service requires.

Making an 'Authorized Request' to a Google API using node.js (with everyauth authentication)

I have an app on node.js using everyauth authentication returning tokens of the form
{ access_token: 'ya29.AHES6ZTlm9qdoFuY9sdpdmFTJISGaQ_69LnW8fszSzPjSCs',
token_secret:
{ token_type: 'Bearer',
expires_in: 3600,
id_token: 'eyJhbGciOisdUzI1NiJ9.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiaWQ
iOiIxMTQ0MDU3NTM5MTg1NTk1Mzc3NzciLCJhdWQiOiI0NDcwOTkyNjgzMjAuYXBwcy5nb29nbGV1c2V
yY29udGVudC5jb20iLCJjaWQiOiI0NDcwOTkyNjgzMjAuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20
iLCJ0b2tlbl9oYXNoIjoicEFXMDBIaUdaSWNRaWMtM09TLU9vQSIsImlhdCI6MTM0NjMyMzQwMiwiZXh
wIjoxMzQ2MzI3MzAyfQ.HUAhg2hdBUB2n1oUFW_9MOxAyr2O7u8GFkShxggTL2o2tBpwIi0_jLIuD1ri
mGkZwdlR5DwjODe4w2w2rLzPpb3YPCeh19zWg7pxP0huqvuVl3cPLXOkWxke46WIH9KNSQbV3oX34GA4
jTvzEV2-HCR_-GhDeG245FTSpxYpTnE',
refresh_token: '1/Ns-89zzHPbIJlFYXAOCn4dKqxklN4Wc0Og-Gga5XSJA' } }
At this point how do I make an 'authorized request' (get a list of files)?
I've tried using node-auth in this form:
googleOAuth = new OAuth("https://accounts.google.com/o/oauth2/auth",
"https://accounts.google.com/o/oauth2/token",
config.clientID, config.secret,
"1.0A", undefined, "HMAC-SHA1");
googleOAuth.get('https://www.googleapis.com/drive/v2/files/list', token.access_token, token.token_secret.id_token, function (error, data) {
if(error){
console.log(error)
}else{
console.log(data)
}
});
After I've clicked 'Allow access' on the google prompt, the googleOAuth.get logs the error
{"error":{"statusCode":401,"data":"{\n \"error\": {\n \"errors\": [\n {\n \"domain\": \"global\",\n \"reason\": \"authError\",\n \"message\": \"Invalid Credentials\",\n \"locationType\": \"header\",\n \"location\": \"Authorization\"\n }\n ],\n \"code\": 401,\n \"message\": \"Invalid Credentials\"\n }\n}\n"}}
What authentication should I be passing with my get request to get a valid file listing?
It seems odd using two authentication libraries. I'm not sure how I can make a signed request with everyauth, though. It seems to be for 'logging in with' a service only.
1) In my everyauth register users function I updated the scope to include google drive.
exports.register = function register (everyauth, conf, users) {
everyauth['google']
.appId(conf.google.clientID)
.appSecret(conf.google.secret)
.scope('https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/userinfo.profile') // ADDED ADDITIONAL SCOPE VALUE HERE
.findOrCreateUser(function (sess, token, accessTokenExtra, googleUserData) {
var user = users.find('google', token);
if (user) {
return user;
} else {
return users.add('google', sess.id, token, accessTokenExtra, googleUserData);
}
})
.redirectPath('/');
};
2) In my request I abandoned node-oauth and use request, with the access token as a parameter.
// was googleOAuth.get('http.... etc
request('https://www.googleapis.com/drive/v2/files?access_token= + token.access_token, function (error, response, body) {
if(error){
callback(error, null);
}else{
callback(null, data);
}
});
3) At this point I'm now getting 403 errors returned, instead of 401 errors.
The missing action was to set Google Drive API as well as Google Drive SDK on in my control panel as per the answer to this question https://stackoverflow.com/a/10370391/1408316

Resources