diff --git a/.env.example b/.env.example index ec6a347..d66a7e6 100644 --- a/.env.example +++ b/.env.example @@ -3,14 +3,18 @@ AWS_SECRET_ACCESS_KEY= AWS_S3_BUCKET= DISABLE_S3=false -MYSQL_USER=root -MYSQL_PASSWORD=webmailpasswd +MYSQL_USER= +MYSQL_PASSWORD= MYSQL_DATABASE=phase2 TWITTER_CONSUMER_KEY= TWITTER_CONSUMER_SECRET= -TWITTER_CALLBACK_URL=http://localhost:3000/api/twitter_callback +TWITTER_CALLBACK_URL=https://ceremony.tornado.cash/api/oauth_callback/twitter + +GITHUB_CLIEND_ID= +GITHUB_CLIENT_SECRET= +GITHUB_CALLBACK_URL=https://ceremony.tornado.cash/api/oauth_callback/github + SESSION_SECRET= NUXT_HOST=0.0.0.0 -NUXT_PORT=3000 diff --git a/.gitignore b/.gitignore index c6dda1b..7576c55 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,5 @@ sw.* *.swp .env.local db.development.sqlite +.env.development +.env.production diff --git a/components/Form.vue b/components/Form.vue index 148f1aa..e4856e9 100644 --- a/components/Form.vue +++ b/components/Form.vue @@ -13,10 +13,10 @@
@@ -52,7 +52,7 @@ export default { } }, methods: { - ...mapActions('user', ['makeTweet', 'twitterLogIn']) + ...mapActions('user', ['makeTweet', 'logInVia']) } } diff --git a/docker-compose.yml b/docker-compose.yml index 090663f..afddcd4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,14 +9,14 @@ services: nginx_client_max_body_size: 50m nginx_proxy_read_timeout: 600s MYSQL_HOST: mysql - env_file: .env + env_file: .env.production depends_on: - mysql mysql: image: mysql:5.7 restart: always - env_file: .env + env_file: .env.production environment: MYSQL_RANDOM_ROOT_PASSWORD: 'true' volumes: diff --git a/pages/make-contribution.vue b/pages/make-contribution.vue index 3a13986..396af07 100644 --- a/pages/make-contribution.vue +++ b/pages/make-contribution.vue @@ -132,7 +132,7 @@ export default { }, async mounted() { this.loading = true - this.status.msg = 'Loading...' + this.status.msg = 'Loading' this.status.type = '' await this.getUserData() this.loading = false diff --git a/server/controllers/authorize.js b/server/controllers/authorize.js index f53481e..823ae6d 100644 --- a/server/controllers/authorize.js +++ b/server/controllers/authorize.js @@ -3,64 +3,137 @@ const router = express.Router() const oauth = require('oauth') const logger = require('morgan') -const consumer = new oauth.OAuth( +const { + TWITTER_CONSUMER_KEY, + TWITTER_CONSUMER_SECRET, + TWITTER_CALLBACK_URL, + GITHUB_CLIEND_ID, + GITHUB_CLIENT_SECRET, + GITHUB_CALLBACK_URL +} = process.env +const providers = ['github', 'twitter'] + +// twitter uses OAuth1 +const twitter = new oauth.OAuth( 'https://twitter.com/oauth/request_token', 'https://twitter.com/oauth/access_token', - process.env.TWITTER_CONSUMER_KEY, - process.env.TWITTER_CONSUMER_SECRET, + TWITTER_CONSUMER_KEY, + TWITTER_CONSUMER_SECRET, '1.0A', - process.env.TWITTER_CALLBACK_URL || 'http://localhost:3000/api/twitter_callback', + TWITTER_CALLBACK_URL, 'HMAC-SHA1' ) -router.get('/user_data', (req, res) => { - let userData = { name: 'Anonymous' } - consumer.get( - 'https://api.twitter.com/1.1/account/verify_credentials.json', - req.session.oauthAccessToken, - req.session.oauthAccessTokenSecret, - function(error, data) { - if (!error) { - userData = JSON.parse(data) - userData.handle = userData.screen_name - req.session.handle = userData.screen_name - req.session.socialType = 'twitter' - } - res.json(userData) - } - ) -}) +// github uses OAuth2 +const github = new oauth.OAuth2( + GITHUB_CLIEND_ID, + GITHUB_CLIENT_SECRET, + 'https://github.com/', + 'login/oauth/authorize', + 'login/oauth/access_token' +) -router.get('/connect', (req, res) => { - consumer.getOAuthRequestToken(function(error, oauthToken, oauthTokenSecret) { - if (error) { - res.status(500).send(error) - } else { - req.session.oauthRequestToken = oauthToken - req.session.oauthRequestTokenSecret = oauthTokenSecret - res.redirect( - 'https://twitter.com/oauth/authorize?oauth_token=' + req.session.oauthRequestToken - ) - } - }) -}) +router.get('/connect/:provider', (req, res) => { + const { provider } = req.params + if (!providers.includes(provider)) { + res.status(404).send('Wrong provider') + } -router.get('/twitter_callback', (req, res) => { - consumer.getOAuthAccessToken( - req.query.oauth_token, - req.session.oauthRequestTokenSecret, - req.query.oauth_verifier, - (error, oauthAccessToken, oauthAccessTokenSecret) => { + if (provider === 'github') { + const authorizeUrl = github.getAuthorizeUrl({ + redirect_uri: GITHUB_CALLBACK_URL, + scope: [], // 'gist' - https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/ + state: 'some random string to protect against cross-site request forgery attacks' + }) + res.redirect(authorizeUrl) + } else if (provider === 'twitter') { + twitter.getOAuthRequestToken(function(error, oauthToken, oauthTokenSecret) { if (error) { - logger.error(error) res.status(500).send(error) } else { - req.session.oauthAccessToken = oauthAccessToken - req.session.oauthAccessTokenSecret = oauthAccessTokenSecret + req.session.oauthRequestToken = oauthToken + req.session.oauthRequestTokenSecret = oauthTokenSecret + res.redirect( + 'https://twitter.com/oauth/authorize?oauth_token=' + req.session.oauthRequestToken + ) + } + }) + } +}) + +router.get('/oauth_callback/:provider', (req, res) => { + const { provider } = req.params + if (!providers.includes(provider)) { + res.status(404).send('Wrong provider') + } + + if (provider === 'github') { + github.getOAuthAccessToken(req.query.code, {}, function( + error, + accessToken, + refreshToken, + results + ) { + if (error || results.error) { + logger.error('getOAuthAccessToken error', error || results.error) + res.status(500).send(error || results.error) + } else { + req.session.refreshToken = refreshToken + req.session.accessToken = accessToken res.redirect('/make-contribution') } - } - ) + }) + } else if (provider === 'twitter') { + twitter.getOAuthAccessToken( + req.query.oauth_token, + req.session.oauthRequestTokenSecret, + req.query.oauth_verifier, + (error, oauthAccessToken, oauthAccessTokenSecret) => { + if (error) { + logger.error(error) + res.status(500).send(error) + } else { + req.session.oauthAccessToken = oauthAccessToken + req.session.oauthAccessTokenSecret = oauthAccessTokenSecret + res.redirect('/make-contribution') + } + } + ) + } +}) + +router.get('/user_data/', (req, res) => { + let userData = { name: 'Anonymous' } + if (req.session.accessToken) { + github.get('https://api.github.com/user', req.session.accessToken, function(error, data) { + if (!error) { + userData = JSON.parse(data) + userData.handle = userData.login + userData.socialType = 'github' + req.session.handle = userData.login + req.session.socialType = 'github' + } + res.json(userData) + }) + } else if (req.session.oauthAccessToken && req.session.oauthAccessTokenSecret) { + twitter.get( + 'https://api.twitter.com/1.1/account/verify_credentials.json', + req.session.oauthAccessToken, + req.session.oauthAccessTokenSecret, + function(error, data) { + if (!error) { + userData = JSON.parse(data) + userData.handle = userData.screen_name + userData.socialType = 'twitter' + req.session.handle = userData.screen_name + req.session.socialType = 'twitter' + } + res.json(userData) + } + ) + } else { + res.json(userData) + } }) router.get('/logout', (req, res) => { diff --git a/server/index.js b/server/index.js index 83de525..caaa9c5 100644 --- a/server/index.js +++ b/server/index.js @@ -1,6 +1,7 @@ -require('dotenv').config() -const fs = require('fs') const path = require('path') +const { NODE_ENV } = process.env +require('dotenv').config({ path: path.join(__dirname, `../.env.${NODE_ENV}`) }) +const fs = require('fs') const express = require('express') const bodyParser = require('body-parser') const morgan = require('morgan') @@ -14,7 +15,7 @@ const models = require('./models') const app = express() async function start() { - config.dev = process.env.NODE_ENV !== 'production' + config.dev = NODE_ENV !== 'production' await models.sequelize.sync() const nuxt = new Nuxt(config) diff --git a/server/snark_files/current.params b/server/snark_files/current.params index 4939bad..7e200b3 100644 Binary files a/server/snark_files/current.params and b/server/snark_files/current.params differ diff --git a/store/user.js b/store/user.js index 0d0881b..0d36da3 100644 --- a/store/user.js +++ b/store/user.js @@ -49,8 +49,8 @@ const getters = { } const actions = { - twitterLogIn() { - window.location.replace('/api/connect') + logInVia({ state }, provider) { + window.location.replace(`/api/connect/${provider}`) }, makeTweet({ state }) { const tweetText = `Just made the contribution %23${state.contributionIndex} to Tornado.cash Trusted Setup Ceremony! 🚀` @@ -90,8 +90,7 @@ const actions = { if (data.name !== 'Anonymous') { commit('SET_HANDLE', data.handle) commit('SET_NAME', data.name) - // TODO check whether it's github or twitter - commit('SET_CONTRIBUTION_TYPE', 'twitter') + commit('SET_CONTRIBUTION_TYPE', data.socialType) } } catch (e) { console.error('user_data fail', e)