Created
September 11, 2021 05:04
-
-
Save S-codes14/1d31ef6e27a48483206d09b1d8e301e6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const crypto = require('crypto') | |
const get = require('simple-get') | |
const OAuth = require('oauth-1.0a') | |
const querystring = require('querystring') | |
const TW_REQ_TOKEN_URL = 'https://api.twitter.com/oauth/request_token' | |
const TW_AUTH_URL = 'https://api.twitter.com/oauth/authenticate' | |
const TW_ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token' | |
class LoginWithTwitter { | |
constructor (opts) { | |
// Check that required options exist | |
if (!opts.consumerKey || typeof opts.consumerKey !== 'string') { | |
throw new Error('Invalid or missing `consumerKey` option') | |
} | |
if (!opts.consumerSecret || typeof opts.consumerSecret !== 'string') { | |
throw new Error('Invalid or missing `consumerSecret` option') | |
} | |
if (!opts.callbackUrl || typeof opts.callbackUrl !== 'string') { | |
throw new Error('Invalid or missing `callbackUrl` option') | |
} | |
this.consumerKey = opts.consumerKey | |
this.consumerSecret = opts.consumerSecret | |
this.callbackUrl = opts.callbackUrl | |
this._oauth = OAuth({ | |
consumer: { | |
key: this.consumerKey, | |
secret: this.consumerSecret | |
}, | |
signature_method: 'HMAC-SHA1', | |
hash_function: (baseString, key) => { | |
return crypto.createHmac('sha1', key).update(baseString).digest('base64') | |
} | |
}) | |
} | |
login (cb) { | |
// Check that required params exist | |
if (typeof cb !== 'function') { | |
throw new Error('Invalid or missing `cb` parameter for login method') | |
} | |
const requestData = { | |
url: TW_REQ_TOKEN_URL, | |
method: 'POST', | |
data: { | |
oauth_callback: this.callbackUrl | |
} | |
} | |
// Get a "request token" | |
get.concat({ | |
url: requestData.url, | |
method: requestData.method, | |
form: requestData.data, | |
headers: this._oauth.toHeader(this._oauth.authorize(requestData)) | |
}, (err, res, data) => { | |
if (err) return cb(err) | |
const { | |
oauth_token: token, | |
oauth_token_secret: tokenSecret, | |
oauth_callback_confirmed: callbackConfirmed | |
} = querystring.parse(data.toString()) | |
// Must validate that this param exists, according to Twitter docs | |
if (callbackConfirmed !== 'true') { | |
return cb(new Error('Missing `oauth_callback_confirmed` parameter in response (is the callback URL approved for this client application?)')) | |
} | |
// Redirect visitor to this URL to authorize the app | |
const url = `${TW_AUTH_URL}?${querystring.stringify({ oauth_token: token })}` | |
cb(null, tokenSecret, url) | |
}) | |
} | |
callback (params, tokenSecret, cb) { | |
const { | |
oauth_token: token, | |
oauth_verifier: verifier | |
} = params | |
// Check that required params exist | |
if (typeof cb !== 'function') { | |
throw new Error('Invalid or missing `cb` parameter for callback method') | |
} | |
if (typeof params.denied === 'string' && params.denied.length > 0) { | |
const err = new Error('User denied login permission') | |
err.code = 'USER_DENIED' | |
return cb(err) | |
} | |
if (typeof params.oauth_token !== 'string' || params.oauth_token.length === 0) { | |
return cb(new Error('Invalid or missing `oauth_token` parameter for login callback')) | |
} | |
if (typeof params.oauth_verifier !== 'string' || params.oauth_verifier.length === 0) { | |
return cb(new Error('Invalid or missing `oauth_verifier` parameter for login callback')) | |
} | |
if (typeof tokenSecret !== 'string' || tokenSecret.length === 0) { | |
return cb(new Error('Invalid or missing `tokenSecret` argument for login callback')) | |
} | |
const requestData = { | |
url: TW_ACCESS_TOKEN_URL, | |
method: 'POST', | |
data: { | |
oauth_token: token, | |
oauth_token_secret: tokenSecret, | |
oauth_verifier: verifier | |
} | |
} | |
// Get a user "access token" and "access token secret" | |
get.concat({ | |
url: requestData.url, | |
method: requestData.method, | |
form: requestData.data, | |
headers: this._oauth.toHeader(this._oauth.authorize(requestData)) | |
}, (err, res, data) => { | |
if (err) return cb(err) | |
// Ready to make signed requests on behalf of the user | |
const { | |
oauth_token: userToken, | |
oauth_token_secret: userTokenSecret, | |
screen_name: userName, | |
user_id: userId | |
} = querystring.parse(data.toString()) | |
cb(null, { | |
userName, | |
userId, | |
userToken, | |
userTokenSecret | |
}) | |
}) | |
} | |
} | |
module.exports = LoginWithTwitter |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment