Twitter API Email not getting - node.js

I am using the following code to get email after twitter login
var requestTokenUrl = 'https://api.twitter.com/oauth/request_token';
var accessTokenUrl = 'https://api.twitter.com/oauth/access_token';
var profileUrl = 'https://api.twitter.com/1.1/account/verify_credentials.json?include_email=true';
var accessTokenOauth = {
consumer_key: authConf.TWITTER_KEY,
consumer_secret: authConf.TWITTER_SECRET,
token: req.body.oauth_token,
verifier: req.body.oauth_verifier
};
// Step 3. Exchange oauth token and oauth verifier for access token.
request.post({ url: accessTokenUrl, oauth: accessTokenOauth }, function(err, response, accessToken) {
if (err) {
return res.status(500).json(err);
}
accessToken = qs.parse(accessToken);
var profileOauth = {
consumer_key: authConf.TWITTER_KEY,
consumer_secret: authConf.TWITTER_SECRET,
oauth_token: accessToken.oauth_token
};
// Step 4. Retrieve profile information about the current user.
request.get({
url: profileUrl,
oauth: profileOauth,
json: true
}, function(err, response, profile) {
if (err) {
console.log("..........." + err)
return res.status(500).json(err);
}
if (profile) {
//Succes : Do something
}
I am getting the access token. But in the step 4, I am getting an error as follows
{"errors":[{"message":"Your credentials do not allow access to this
resource","code":220}]}
I have tried refreshing the access tokens but of no use.

When you open your app setting # apps.twitter.com, under the Permisions tab, make sure that the Request email addresses from users checkbox is ticked as shown in the image, then update setting. You will need to regenerate access token for this new permission update to work.
Twitter Dev

Related

How to connect and find a user from Azure AD using Nodejs

I am trying to find a user from the azure active directory using nodejs. I am using Node-ActiveDirectory for this task. First I tried to connect to the Azure active directory as the given example in the above link. example code as below that I have used.
var ActiveDirectory = require('activedirectory');
var config = { url: 'ldap://myhotmail.onmicrosoft.com',
baseDN: 'dc=myhotmail,dc=onmicrosoft,dc=com',
username: 'roledene#myhotmail.onmicrosoft.com',
password: 'myPassword'
}
var ad = new ActiveDirectory(config);
var username = 'roledene#myhotmail.onmicrosoft.com';
var password = 'myPassword';
ad.authenticate(username, password, function(err, auth) {
if (err) {
console.log('ERROR: '+JSON.stringify(err));
return;
}
if (auth) {
console.log('Authenticated!');
}
else {
console.log('Authentication failed!');
}
});
but it gives the following error. what is wrong with this code ?
ERROR: {"code":"ENOTFOUND","errno":"ENOTFOUND","syscall":"getaddrinfo","hostname":"myhotmail.onmicrosoft.com","host":"myhotmail.onmicrosoft.com","port":389}
as #juunas comment, I tried with the Microsoft Graph client.
I will quote the initial step for setup the ms graph client which is exactly mentioned in here for more details
Installing ms graph client
npm install #microsoft/microsoft-graph-client
connect and query from MS graph api
const MicrosoftGraph = require("#microsoft/microsoft-graph-client");
var client = MicrosoftGraph.Client.init({
authProvider: (iss, sub, profile, accessToken, refreshToken, done) => {
done(null, {
profile,
accessToken,
refreshToken
}); //first parameter takes an error if you can't get an access token
}
});
// Example calling /me with no parameters
client
.api('/me')
.get((err, res) => {
console.log(res); // prints info about authenticated user
});

Node AWS Lambda POST to Twitter with User context Auth

I am attempting to create a Node lambda on AWS which will authenticate with the Twitter API, via the twit npm module, in User Context. So that the lambda can then upload a GIF and then once uploaded, tweet on the user's timeline using the returned media_id.
I have created a twitter app etc. It works, however it is posting the tweet to the account associated with the app, instead of the user's timeline. Here is my entire lambda code:
const fs = require('fs');
const Twit = require('twit');
var T = new Twit({
consumer_key: '...',
consumer_secret: '...',
access_token: '...',
access_token_secret: '...'
});
module.exports.oauth = (event, context, callback) => {
var b64content = fs.readFileSync('./testGIF.gif', { encoding: 'base64' })
// POST the media to Twitter
T.post('media/upload', { media_data: b64content }, function (err, data, response) {
// assign alt text to the media, for use by screen readers etc
var mediaIdStr = data.media_id_string
var altText = "Alt text"
var meta_params = { media_id: mediaIdStr, alt_text: { text: altText } }
T.post('media/metadata/create', meta_params, function (err, data, response) {
if (!err) {
// reference the media and post a tweet (media will attach to the tweet)
var params = { status: 'Testing, GIF Sharing', media_ids: [mediaIdStr] }
T.post('statuses/update', params, function (err, data, response) {
console.log(data)
})
}
})
})
const response = {
statusCode: 200,
};
callback(null, response);
};
Any help would be much appreciated!
You are currently using tokens for the user account associated with the app.
You'll need to obtain an OAuth token on the user's behalf and use that to make authorized calls to Twitter's APIs.
You need to first create a webpage for your twitter app, then do any of the following:
implement a twitter signin to directly capture an OAUTH token
implement a three legged authorization to directly capture an OAUTH token
use a PIN-based authorization
Once you have captured OAUTH token for the user, you can passed it on to your lambda to be used to initialize the Twit client.
https://dev.twitter.com/oauth/overview

Get an access token to Linkedin API using email and password

Is it possible to get an access token in order to use node-linkedin package by providing credentials - user email and password? What I'm trying to do is an command line app, that can make an api calls to linkedin and write results in a text file. Thus, I'm not sending any api call results to the client.
I've been trying to do the same thing.
the simple-oauth2 module has a method for logging in via password, but I cannot seem to get it to work.
https://www.npmjs.com/package/simple-oauth2
// Set the configuration settings
const credentials = {
client: {
id: '<client-id>',
secret: '<client-secret>'
},
auth: {
tokenHost: 'https://api.linkedin.com',
authorizePath: 'https://api.linkedin.com/uas/oauth/requestToken',
tokenPath: 'https://api.linkedin.com/uas/oauth/accessToken'
}
};
// Initialize the OAuth2 Library
const oauth2 = require('simple-oauth2').create(credentials);
// Get the access token object.
const tokenConfig = {
username: 'username',
password: 'password'
};
// Callbacks
// Save the access token
oauth2.ownerPassword.getToken(tokenConfig, (error, result) => {
if (error) {
return console.log('Access Token Error', error.message);
}
const token = oauth2.accessToken.create(result);
});
I am not sure these endpoints are correct:
auth: {
tokenHost: 'https://api.linkedin.com',
authorizePath: 'https://api.linkedin.com/uas/oauth/requestToken',
tokenPath: 'https://api.linkedin.com/uas/oauth/accessToken'
}
I get a 400 bad request.

Check Oauth2 token exists and valid in Node.js Rest Client With Bluebird

I am writing a Node.js client for a REST API that uses OAuth2. I am using Bluebird and promises (and sending the access token in the header) and I was wondering when would be a good time to check if the access token is already granted (exists) or still valid (not expired).
So far, I have come up with this:
'use strict';
var Bluebird = require('bluebird');
var request = Bluebird.promisifyAll(require('request'), { multiArgs: true });
var Oauth = require('oauth');
var OAuth2 = OAuth.OAuth2;
var _ = require('lodash');
function Client(options) {
this.options = _.assign({
url: '<API URL>',
oauth2Url: 'oauth2/token',
apiVersion: process.env.apiVersion,
consumerKey: process.env.consumerKey,
consumerSecret: process.env.consumerSecret
}, options);
if (!this.options.url) {
throw new Error('Missing client url.');
}
...
if (!this.options.consumerSecret) {
throw new Error('Missing consumer secret.');
}
if(!this.access_token){
var oauth2 = new OAuth2(
this.options.consumerKey,
this.options.consumerSecret,
this.options.url + this.options.version,
null,
this.options.oauth2Url,
null);
oauth2.getOAuthAccessToken(
'',
{'grant_type':'client_credentials'},
function (e, access_token, refresh_token, results){
this.access_token = access_token;
this.refresh_token = refresh_token;
done();
});
}
}
Client.prototype.queryApi = function (options, callback) {
return request.postAsync({
headers: {
Authorization: 'Bearer ' + access_token
},
url: this.options.url + this.options.apiVersion,
body: JSON.stringify(options)}).
then(function (result) {
var json = JSON.parse(result[1]);
if (_.isFunction(callback)) {
callback(null, json);
}
return json;
}).
catch(function (err) {
if (_.isFunction(callback)) {
callback(err);
return;
}
throw err;
});
};
module.exports = Client;
I am new to both Oauth/Oauth2 and Node.js and I was just wondering if I am checking for the access token in the right place and how/where can I also check if it expired or not. Thanks!
First of all there is two way to check whether access token is expired or not
By knowing token_expiration value from your oauth app.In this case you need to keep task running on your app that will determine wheter access_token is expired or not.(Not recommended way of handling access token)
Handle the response from Authorization server stating that your acces token has been expired.In this case you need to get new access token by presenting refresh token.
You can write 'tokenPersistanceFunction' that will be called when your oauth values(access_token,refresh_token) are updated.
I have modified your code to reflect these changes
function tokenPersistanceFunction(updatedOauth){
// Here you will get Updated Oauth values
// Save these to DB
return saveAccessToken(updatedOauth.access_token, updatedOauth.refresh_token);
}
Client.prototype.queryApi = function (options, tokenPersistanceFunction, callback) {
return request.postAsync({
headers: {
Authorization: 'Bearer ' + access_token
},
url: this.options.url + this.options.apiVersion,
body: JSON.stringify(options)}).
then(function (result) {
// You have some indication from your oauth server, that your access_token is expired.
// You can check your response here to know whether access_token is expired or not.
// If access_token is expired, Make request to refresh access token.
// In your case
if(AccessTokenIsExpired){
// Function that will make request to refresh access_token by presenting refresh_token
return <functionThatRefreshesAccessToken>( refreshAccessTokenOptions,tokenPersistanceFunction)
.then(function(result){
//Extract access_token, refresh_token from response
// call 'tokenPersistanceFunction' to store these token in your DB.
return tokenPersistanceFunction(updatedOauth);
})
.then(function(savedOauthTokensSuccess){
// Now you have the updated Oauth tokens, you can make request to get resource
// this call will return you the actual response.
return queryApi(options, tokenPersistanceFunction, callback);
})
}else{
var json = JSON.parse(result[1]);
if (_.isFunction(callback)) {
callback(null, json);
}
return json;
}
}).
catch(function (err) {
if (_.isFunction(callback)) {
callback(err);
return;
}
throw err;
});
};

How to retrieve user's additional information from Azure Mobile/App Services?

I need to get the user's extra information from social accounts like Facebook and Google+. When I first read about Azure Mobile Services I thought it to be the holy grail of social authentication. Well, after a full week of hair pulling I'm starting to reconsider my first impression. It does authenticate as easily as it could possibly do. I configured Google+ and FB to work with Azure, configured Azure to use the key/secret from each provider and it all just worked. I was able to login perfectly. The problem started when I tried to get information from the logged user, which I honestly think is basic!
Azure Mobile Services returns the UserId and a Token that you can not use to request the extra info on the selected provider. So even if I were to create a second request using FB's graph API for instance, that wouldn't work (I've tried!). That token is Azure's own token. So I found out from several Carlos Figueira (SE at Azure) posts that I should customize my Azure script, make a request to Azure and then I'd be able to get it working.
I've also read several posts from Carlos Figueira on how to implement that extra functionality and even though that was not what I was looking for (customizing the server) I decided to work with that. But my return type is a MobileServiceUser and that type only has 2 properties: UserId and MobileServiceAuthenticationToken. So even after adding the server script from Carlos I couldn't retrieve the extra information from my Xamarin App.
I've read a lot of things, researched a lot and couldn't find an answer =/ By the way this is not the answer:
How to get user name, email, etc. from MobileServiceUser?
Did anyone manage to make it work?
PS: I'm not posting any code here because it's working. If you think checking some part of my code would help decipher the problem just let me know.
Thanks in advance!
EDIT:
Script
function insert(item, user, request) {
item.UserName = "<unknown>"; // default
user.getIdentities({
success: function (identities) {
var url = null;
var oauth = null;
if (identities.google) {
var googleAccessToken = identities.google.accessToken;
url = 'https://www.googleapis.com/oauth2/v3/userinfo?access_token=' + googleAccessToken;
} else if (identities.facebook) {
var fbAccessToken = identities.facebook.accessToken;
url = 'https://graph.facebook.com/me?access_token=' + fbAccessToken;
} else if (identities.microsoft) {
var liveAccessToken = identities.microsoft.accessToken;
url = 'https://apis.live.net/v5.0/me/?method=GET&access_token=' + liveAccessToken;
} else if (identities.twitter) {
var userId = user.userId;
var twitterId = userId.substring(userId.indexOf(':') + 1);
url = 'https://api.twitter.com/1.1/users/show.json?user_id=' + twitterId;
var consumerKey = process.env.MS_TwitterConsumerKey;
var consumerSecret = process.env.MS_TwitterConsumerSecret;
oauth = {
consumer_key: consumerKey,
consumer_secret: consumerSecret,
token: identities.twitter.accessToken,
token_secret: identities.twitter.accessTokenSecret
};
}
if (url) {
var requestCallback = function (err, resp, body) {
if (err || resp.statusCode !== 200) {
console.error('Error sending data to the provider: ', err);
request.respond(statusCodes.INTERNAL_SERVER_ERROR, body);
} else {
try {
var userData = JSON.parse(body);
item.UserName = userData.name;
request.execute();
} catch (ex) {
console.error('Error parsing response from the provider API: ', ex);
request.respond(statusCodes.INTERNAL_SERVER_ERROR, ex);
}
}
}
var req = require('request');
var reqOptions = {
uri: url,
headers: { Accept: "application/json" }
};
if (oauth) {
reqOptions.oauth = oauth;
}
req(reqOptions, requestCallback);
} else {
// Insert with default user name
request.execute();
}
}
});
}
You're talking about the token on the client side correct? That token is specific only to the client. If you're using Server Side flow, the server is the only one with that token. If you want to send that to the client, you need to do that via a custom API you create.
This class you're talking about does only contain those two properties. But on your server side, your ServiceUser can access the different identity provider tokens in order to speak to those servers APIs. Your linked post is correct in how you access the token, you're mistaken on where you can access that token, it's only on the server side (if you use the server directed login flow).
Here is the custom API Script I had working in Mobile Services to return the profile of the logged in user. I am working on updating to Mobile Apps as some environment variables appear to have changed. Would love to know if anyone has gotten it to work with Mobile Apps.
exports.get = function (request, response) {
var user = request.user;
user.getIdentities({
success: function (identities) {
var req = require('request');
var url = null;
var oauth = null;
var userId = user.userId.split(':')[1];
console.log('Identities: ', identities);
if (identities.facebook) {
url = 'https://graph.facebook.com/me?access_token=' +
identities.facebook.accessToken;
} else if (identities.google) {
url = 'https://www.googleapis.com/oauth2/v3/userinfo' +
'?access_token=' + identities.google.accessToken;
} else if (identities.microsoft) {
url = 'https://apis.live.net/v5.0/me?access_token=' +
identities.microsoft.accessToken;
} else if (identities.twitter) {
var consumerKey = process.env.MS_TwitterConsumerKey;
var consumerSecret = process.env.MS_TwitterConsumerSecret;
oauth = {
consumer_key: consumerKey,
consumer_secret: consumerSecret,
token: identities.twitter.accessToken,
token_secret: identities.twitter.accessTokenSecret
};
url = 'https://api.twitter.com/1.1/users/show.json?' +
'user_id=' + userId + '&include_entities=false';
} else {
response.send(500, { error: 'No known identities' });
return;
}
if (url) {
var reqParams = { uri: url, headers: { Accept: 'application/json' } };
if (oauth) {
reqParams.oauth = oauth;
}
req.get(reqParams, function (err, resp, body) {
if (err) {
console.error('Error calling provider: ', err);
response.send(500, { error: 'Error calling provider' });
return;
}
if (resp.statusCode !== 200) {
console.error('Provider call did not return success: ', resp.statusCode);
response.send(500, { error: 'Provider call did not return success: ' + resp.statusCode });
return;
}
try {
var userData = JSON.parse(body);
response.send(200, userData);
} catch (ex) {
console.error('Error parsing response: ', ex);
response.send(500, { error: ex });
}
});
} else {
response.send(500, { error: 'Not implemented yet', env: process.env });
}
}
});
};

Resources