Skip to content

Instantly share code, notes, and snippets.

@rhussmann
Created September 6, 2010 06:05
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save rhussmann/566699 to your computer and use it in GitHub Desktop.
Save rhussmann/566699 to your computer and use it in GitHub Desktop.
Simple 'sign in with Twitter' implementation in node.js
var http = require('http'),
sys = require('sys'),
URL = require('url'),
querystring = require('querystring'),
OAuth = require('oauth').OAuth;
var oa = new OAuth('https://api.twitter.com/oauth/request_token',
'https://api.twitter.com/oauth/access_token',
'YOUR APP CONSUMER KEY HERE',
'YOUR APP CONSUMER SECRET HERE',
'1.0',
null,
'HMAC-SHA1');
var callbackUrl = '/YOUR TWITTER CALLBACK ENDPOINT HERE';
var global_secret_lookup = {};
http.createServer(function (req, res) {
var reqURL = URL.parse(req.url);
switch (reqURL['pathname']) {
case '/': // Default case, redirect to Twitter signin
console.log('Default URL');
oa.getOAuthRequestToken(function(error, oauth_token, oauth_token_secret, results){
if(error) {
console.log('error :' + sys.inspect(error));
var errResponse = 'Unable to retrieve request token';
res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': errResponse.length});
res.end(errResponse);
}
else {
console.log('oauth_token: ' + oauth_token);
console.log('oauth_token_secret: ' + oauth_token_secret);
console.log('requestoken results: ' + sys.inspect(results));
// I'm sure there's a better way than storing in a single
// global variable (it's not threadsafe, but works for illustrations)
global_secret_lookup[oauth_token] = oauth_token_secret;
// NOTE: we use the AUTHENTICATE, not the AUTHORIZE URL here
var twitterAuthEndpoint = 'https://api.twitter.com/oauth/authenticate?oauth_token=' + oauth_token;
console.log('Redirecting to ' + twitterAuthEndpoint);
res.writeHead(301, {'Content-Type': 'text/plain', 'Location': twitterAuthEndpoint});
res.end('Redirecting...\n');
}
});
break;
case callbackUrl: // Callback URL case
console.log('Callback URL');
var parsedURL = URL.parse(req.url);
var parsedQuery = querystring.parse(parsedURL.query);
// If there's no oauth_token parameter then the user must have
// denied access. Bail.
if(typeof(parsedQuery['oauth_token']) === 'undefined') {
console.log('User failed to authorize access');
var accessDenied = 'Please grant access to continue...'
res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': accessDenied.length});
res.end(accessDenied);
return;
}
var oauth_token = parsedQuery['oauth_token'];
// !IMPORTANT!
// Grab an access token. Twitter won't remember that the user authorized
// the application for authentication unless we grab an access token
oa.getOAuthAccessToken(oauth_token, global_secret_lookup[oauth_token], function(error, oauth_access_token, oauth_access_token_secret, results) {
console.log('Requested access token');
console.log('oauth_access_token: ' + oauth_access_token);
console.log('oauth_token_secret: ' + oauth_access_token_secret);
console.log('accesstoken results: ' + sys.inspect(results));
var stringifiedResults = JSON.stringify(results);
res.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': stringifiedResults.length});
res.end(stringifiedResults);
});
delete global_secret_lookup[oauth_token];
break;
}
}).listen(8888, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8888/');
@jonathanong
Copy link

thanks for this. some notes:

  • sys no longer exists. you want to use require('util').inspect
  • you want to redirect with a 303 status code, not 301.

@shaharsol
Copy link

Thanks, it was a good start.

You missed the oauth_verifier part in the callback. you should take it from the parsed query and use as param #3 to getOAuthAccessToken, the callback function comes as #4.

instead of globals you can use req.session.

Cheers!

@odykyi
Copy link

odykyi commented Oct 6, 2017

69 code line incorrect
see here
|
V
oa.getOAuthAccessToken(oauth_token, global_secret_lookup[oauth_token], oauth_verifier, (error, oauth_access_token, oauth_access_token_secret, results) => {

oauth_verifier shoud come from request query

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment