Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] login to server via signing a message #11

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Lint fixes
  • Loading branch information
tibetsprague committed Oct 15, 2019
commit 3f62caba6bb0d4197957f41d44cef88f0dcc72fa
6 changes: 5 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
@@ -3,6 +3,10 @@
"rules": {
"max-len": "off",
"object-curly-spacing": ["error", "always"],
"padded-blocks": "off"
"padded-blocks": "off",
"one-var": "off"
},
"parserOptions": {
"ecmaVersion": 2017
}
}
84 changes: 43 additions & 41 deletions providers.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,60 @@
'use strict';

const providers = {};

const base_url = process.env.BASE_URL || "";
const baseURL = process.env.BASE_URL || '';

if (process.env.FACEBOOK_APP_ID) {
providers['facebook-link'] = {
"provider": "facebook",
"module": "passport-facebook",
"clientID": process.env.FACEBOOK_APP_ID,
"clientSecret": process.env.FACEBOOK_APP_SECRET,
"callbackURL": base_url + "/link/facebook/callback",
"authPath": "/link/facebook",
"callbackPath": "/link/facebook/callback",
"successRedirect": "/link/account",
"scope": ["email", "user_link"],
"profileFields": ["link", "locale", "name", "timezone", "verified", "email", "updated_time"],
"link": true
'provider': 'facebook',
'module': 'passport-facebook',
'clientID': process.env.FACEBOOK_APP_ID,
'clientSecret': process.env.FACEBOOK_APP_SECRET,
'callbackURL': baseURL + '/link/facebook/callback',
'authPath': '/link/facebook',
'callbackPath': '/link/facebook/callback',
'successRedirect': '/link/account',
'scope': ['email', 'user_link'],
'profileFields': ['link', 'locale', 'name', 'timezone', 'verified', 'email', 'updated_time'],
'link': true,
};
}

if (process.env.TWITTER_CONSUMER_KEY) {
providers['twitter-link'] = {
"provider": "twitter",
"authScheme": "oauth",
"module": "passport-twitter",
"callbackURL": base_url + "/link/twitter/callback",
"authPath": "/link/twitter",
"callbackPath": "/link/twitter/callback",
"successRedirect": "/",
"failureRedirect": "/",
"consumerKey": process.env.TWITTER_CONSUMER_KEY,
"consumerSecret": process.env.TWITTER_CONSUMER_SECRET,
"failureFlash": false,
"callbackHTTPMethod": "get",
"link": true
'provider': 'twitter',
'authScheme': 'oauth',
'module': 'passport-twitter',
'callbackURL': baseURL + '/link/twitter/callback',
'authPath': '/link/twitter',
'callbackPath': '/link/twitter/callback',
'successRedirect': '/',
'failureRedirect': '/',
'consumerKey': process.env.TWITTER_CONSUMER_KEY,
'consumerSecret': process.env.TWITTER_CONSUMER_SECRET,
'failureFlash': false,
'callbackHTTPMethod': 'get',
'link': true,
};
}

if (process.env.GITHUB_CLIENT_ID) {
providers["github-link"] = {
"provider": "github",
"authScheme": "oauth",
"module": "passport-github",
"callbackURL": base_url + "/link/github/callback",
"authPath": "/link/github",
"callbackPath": "/link/github/callback",
"successRedirect": "/",
"failureRedirect": "/",
"clientID": process.env.GITHUB_CLIENT_ID,
"clientSecret": process.env.GITHUB_CLIENT_SECRET,
"failureFlash": false,
"callbackHTTPMethod": "get",
"scope": ["email", "profile"],
"link": true
providers['github-link'] = {
'provider': 'github',
'authScheme': 'oauth',
'module': 'passport-github',
'callbackURL': baseURL + '/link/github/callback',
'authPath': '/link/github',
'callbackPath': '/link/github/callback',
'successRedirect': '/',
'failureRedirect': '/',
'clientID': process.env.GITHUB_CLIENT_ID,
'clientSecret': process.env.GITHUB_CLIENT_SECRET,
'failureFlash': false,
'callbackHTTPMethod': 'get',
'scope': ['email', 'profile'],
'link': true,
};
}

module.exports = providers;
module.exports = providers;
6 changes: 4 additions & 2 deletions server/config.local.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

module.exports = {
"cookieSecret": process.env.COOKIE_SECRET
}
'cookieSecret': process.env.COOKIE_SECRET,
};
2 changes: 2 additions & 0 deletions server/create-lb-tables.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var server = require('./server');
var ds = server.dataSources.postgresql;
var lbTables = ['User', 'AccessToken', 'ACL', 'RoleMapping', 'Role'];
8 changes: 5 additions & 3 deletions server/datasources.production.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';

module.exports = {
postgresql: {
connector: 'postgresql',
url: process.env.DATABASE_URL
}
};
url: process.env.DATABASE_URL,
},
};
10 changes: 6 additions & 4 deletions server/migrate.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
'use strict';

var app = require('./server');
var ds = app.dataSources.postgresql;
var appModels = ['Account', 'Proposal', 'ApplicationCredential', 'UserCredential', 'UserIdentity'];

ds.isActual(appModels, function(err, actual) {
if (actual) {
console.log('No migration needed')
console.log('No migration needed');
ds.disconnect();
process.exit(0);
} else {
ds.autoupdate(appModels, function(err) {
if (err){
if (err) {
throw (err);
}
console.log('autoupdate done!')
console.log('autoupdate done!');
ds.disconnect();
process.exit(0);
});
}
});
});
2 changes: 1 addition & 1 deletion server/passport-ethereum.js
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ function Strategy(options, postVerifyGetInfo) {
postVerifyGetInfo = options;
options = {};
}
//if (!postVerifyInfo) { throw new TypeError('LocalStrategy requires a verify callback'); }
// if (!postVerifyInfo) { throw new TypeError('LocalStrategy requires a verify callback'); }

if (options == null) {
options = {};
47 changes: 24 additions & 23 deletions server/server.js
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@ require('dotenv').config();
var bodyParser = require('body-parser');
var boot = require('loopback-boot');
var cookieParser = require('cookie-parser');
var cors = require("cors");
var fs = require("fs");
var cors = require('cors');
var fs = require('fs');
var http = require('http');
var https = require('https');
var loopback = require('loopback');
@@ -26,7 +26,7 @@ var corsOption = {
origin: true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
exposedHeaders: ['x-auth-token']
exposedHeaders: ['x-auth-token'],
};
app.use(cors(corsOption));

@@ -43,11 +43,11 @@ app.middleware('auth', loopback.token({
}));

var RedisStore = require('connect-redis')(session);
app.middleware("session", session({
store: new RedisStore({ url: process.env.REDIS_URL || "redis://127.0.0.1:6379" }),
app.middleware('session', session({
store: new RedisStore({ url: process.env.REDIS_URL || 'redis://127.0.0.1:6379' }),
secret: process.env.SESSION_SECRET,
saveUninitialized: true,
resave: true
resave: true,
}));

app.middleware('session:before', cookieParser(app.get('cookieSecret')));
@@ -85,7 +85,7 @@ passportConfigurator.init();
passportConfigurator.setupModels({
userModel: app.models.User,
userIdentityModel: app.models.UserIdentity,
userCredentialModel: app.models.UserCredential
userCredentialModel: app.models.UserCredential,
});
for (var s in config) {
var c = config[s];
@@ -101,19 +101,20 @@ for (var s in config) {
if (token) {
authInfo.accessToken = token;
}
const profile = identity.profile, provider = identity.provider;
const profile = identity.profile;
const provider = identity.provider;
const profileUrl = provider == 'github' || provider == 'facebook' ? profile.profileUrl :
(provider == 'twitter' ? "https://twitter.com/" + profile.username : "");
(provider == 'twitter' ? 'https://twitter.com/' + profile.username : '');
const name = provider == 'github' || provider == 'twitter' ? profile.displayName :
provider == 'facebook' ? profile._json.first_name + " " + profile._json.last_name : " ";
var account = await app.models.Account.findOne({ where: { ethereumAccountAddress: req.session.ethereumAccountAddress }});
provider == 'facebook' ? profile._json.first_name + ' ' + profile._json.last_name : ' ';
var account = await app.models.Account.findOne({ where: { ethereumAccountAddress: req.session.ethereumAccountAddress } });
if (!account) {
account = new app.models.Account();
account.ethereumAccountAddress = req.session.ethereumAccountAddress;
account.name = name;
}
account.userId = user.id;
account[provider + "URL"] = profileUrl;
account[provider + 'URL'] = profileUrl;
// Skip signature check because this all happening on the server with no client interaction so we dont have or need a signature
account.save({ skipSignatureCheck: true });

@@ -129,15 +130,15 @@ for (var s in config) {

// Add our Ethereum strategy for authenticating by signing a message on the client
const ethStrategy = new EthereumStrategy(
{ passReqToCallback: true},
function (req, address, done) {
{ passReqToCallback: true },
function(req, address, done) {
const password = utils.generateKey('password');
app.models.User.findOrCreate({ username: address }, { username: address, emailVerified: true, password, email: address + "@daostack.loopback" }, async function (err, user) {
app.models.User.findOrCreate({ username: address }, { username: address, emailVerified: true, password, email: address + '@daostack.loopback' }, async function(err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }

// Connect user to account
var account = await app.models.Account.findOne({ where: { ethereumAccountAddress: address }});
var account = await app.models.Account.findOne({ where: { ethereumAccountAddress: address } });
// TODO: what if can't find?? That would be weird
account.userId = user.id;
account.save();
@@ -152,7 +153,7 @@ const ethStrategy = new EthereumStrategy(
},
function(err, token) {
if (err) {
console.error("Login error", err);
console.error('Login error', err);
return err.code === 'LOGIN_FAILED' ?
done(null, false, { message: 'Failed to create token.' }) :
done(err);
@@ -176,16 +177,16 @@ app.get('/nonce',
app.post('/loginByEthSign',
passport.authenticate('ethereum'),
function(req, res) {
console.log("Successful login");
console.log('Successful login');
res.json({ token: req.authInfo.accessToken });
}
);

app.start = function() {
if (process.env.NODE_ENV == 'production') {
app.use(function (req, res, next) {
app.use(function(req, res, next) {
res.setHeader('Strict-Transport-Security', 'max-age=8640000; includeSubDomains');
if (req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'] === "http") {
if (req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'] === 'http') {
return res.redirect(301, 'https://' + req.host + req.url);
} else {
return next();
@@ -206,12 +207,12 @@ app.start = function() {
privateKey = fs.readFileSync(path.join(__dirname, './private/privatekey.pem')).toString();
certificate = fs.readFileSync(path.join(__dirname, './private/certificate.pem')).toString();
useHTTPS = true;
} catch(e) {}
} catch (e) {}

if (useHTTPS) {
var options = {
key: privateKey,
cert: certificate
cert: certificate,
};
server = https.createServer(options, app);
} else {
@@ -237,4 +238,4 @@ if (require.main === module) {

const io = socketio(app.start());
app.set('io', io);
}
}
2 changes: 1 addition & 1 deletion server/utils.js
Original file line number Diff line number Diff line change
@@ -32,4 +32,4 @@ function generateKey(hmacKey, algorithm, encoding) {
return key;
}

exports.generateKey = generateKey;
exports.generateKey = generateKey;