Browse Source

implemented telegram login

feature/telegramLogin
Nareshkumar Rao 3 years ago
parent
commit
4bac4ffe15
  1. 125
      app.js
  2. 41
      package-lock.json
  3. 1
      package.json

125
app.js

@ -5,7 +5,9 @@ const bcrypt = require('bcrypt');
const QRCode = require('qrcode'); const QRCode = require('qrcode');
const cors = require('cors'); const cors = require('cors');
const { createSecureServer } = require('http2'); const { createSecureServer } = require('http2');
const { default: axios } = require('axios');
require("dotenv-flow").config(); require("dotenv-flow").config();
const crypto = require('crypto');
var SequelizeStore = require("connect-session-sequelize")(session.Store); var SequelizeStore = require("connect-session-sequelize")(session.Store);
@ -82,17 +84,36 @@ User.sync().then(() => {
}); });
function authUser(telegram, password, done) {
function authUser(telegramResponse, done) {
let dataCheckArray = [];
for (const [key, value] of Object.entries(telegramResponse)) {
if (key == "hash") continue;
dataCheckArray.push(`${key}=${value}`);
}
dataCheckArray.sort();
const dataCheckString = dataCheckArray.join("\n");
secretKey = crypto.createHash("sha256").update(process.env.TELEGRAM_TOKEN).digest();
confirmationHash = crypto.createHmac("sha256", secretKey).update(dataCheckString).digest("hex");
const authorized = confirmationHash == telegramResponse.hash;
if (!authorized) {
done({ authorized: false });
}
User.findOne({ User.findOne({
where: { where: {
telegram: telegram
telegram: telegramResponse.id,
} }
}).then(user => { }).then(user => {
if (!user) { if (!user) {
done(false, "User not found")
createUser(telegramResponse.id, (success) => {
done({ authorized: success });
})
} else { } else {
const auth = bcrypt.compareSync(password, user.hash);
done(auth, auth ? "Authorized" : "Wrong password");
done({ authorized: true });
} }
}); });
} }
@ -109,10 +130,10 @@ function refreshVerification(user, done) {
function createQRCode(telegram, done) { function createQRCode(telegram, done) {
User.findOne({ User.findOne({
where: {
telegram: telegram
}
})
where: {
telegram: telegram
}
})
.then(user => { .then(user => {
refreshVerification(user, result => { refreshVerification(user, result => {
const verifyURL = `${process.env.WEBSITE_URL}/#/verify/${encodeURIComponent(result.verification)}`; const verifyURL = `${process.env.WEBSITE_URL}/#/verify/${encodeURIComponent(result.verification)}`;
@ -140,11 +161,9 @@ function checkVerification(id, done) {
}); });
} }
function createUser(telegram, password, done) {
hash = bcrypt.hashSync(password, 10);
function createUser(telegram, done) {
User.create({ User.create({
telegram: telegram,
hash: hash,
telegram: telegram
}).then(user => { }).then(user => {
if (!user) { if (!user) {
done(false, "Could not create user"); done(false, "Could not create user");
@ -162,13 +181,18 @@ function createUser(telegram, password, done) {
function addContact(telegram, withUserID, done) { function addContact(telegram, withUserID, done) {
User.findOne({ where: { telegram: telegram } }).then(user => { User.findOne({ where: { telegram: telegram } }).then(user => {
Contact.create({ user: user.id, with: withUserID })
.then(res => {
done(true, "Successfully added contact");
})
.catch(e => {
done(false, e);
});
User.findOne({ where: { id: withUserID } }).then(withUser => {
Contact.create({ user: user.id, with: withUserID })
.then(res => {
console.log(`Registering contact between ${user.id} and ${withUserID}`);
sendTelegramMessage(withUser.telegram, "Someone scanned your QR code. You will be notified if they are tested positive with Covid. If you are tested positive, please tell this bot /COVIDPOSITIVE");
done(true, "Successfully added contact");
})
.catch(e => {
done(false, e);
});
})
}) })
} }
@ -176,6 +200,32 @@ function getCookieExpiry() {
return new Date(Date.now() + COOKIE_EXPIRY_DURATION); return new Date(Date.now() + COOKIE_EXPIRY_DURATION);
} }
function setTelegramWebHook(done) {
const url = `https://api.telegram.org/bot${process.env.TELEGRAM_TOKEN}/setWebhook`;
axios.post(url, {
url: `${process.env.SERVER_API_URL}/${process.env.TELEGRAM_SECRET}`,
allowed_updates: [],
drop_pending_updates: true,
})
.then(res => { done(res) })
.catch(err => { done(err) });
}
function sendTelegramMessage(telegramID, message, done) {
const url = `https://api.telegram.org/bot${process.env.TELEGRAM_TOKEN}/sendMessage`;
axios.post(url, {
chat_id: telegramID,
text: message,
})
.then((res) => {
done(res)
})
.catch(err => {
console.error("Problem sending Telegram message.");
done(err)
});
}
const app = express(); const app = express();
app.set('trust proxy', 1) app.set('trust proxy', 1)
app.use(session({ app.use(session({
@ -191,17 +241,25 @@ app.use(session({
app.use(cors({ credentials: true, origin: true, secure: true })); app.use(cors({ credentials: true, origin: true, secure: true }));
app.use(express.json()) app.use(express.json())
setTelegramWebHook(() => { });
app.post(`/${process.env.TELEGRAM_SECRET}`, (req, res) => {
if (req.body.message) {
sendTelegramMessage(req.body.message.chat.id, `${req.body.message.text.toUpperCase()}`, (res) => { console.log(res) });
}
res.send();
});
app.post('/login', (req, res) => { app.post('/login', (req, res) => {
reqTelegram = req.body.telegram.toLowerCase();
const auth = authUser(reqTelegram, req.body.password, (success, msg) => {
telegramResponse = req.body.telegramResponse;
const auth = authUser(telegramResponse, (success, msg) => {
if (success) { if (success) {
const verified = req.session.verified; const verified = req.session.verified;
const verifiedBy = req.session.verifiedBy; const verifiedBy = req.session.verifiedBy;
req.session.regenerate(() => { req.session.regenerate(() => {
cookieExpiry = getCookieExpiry(); cookieExpiry = getCookieExpiry();
req.session.user = reqTelegram;
req.session.user = telegramResponse.id;
if (verified) { if (verified) {
addContact(reqTelegram, verifiedBy, (contactSuccess) => {
addContact(telegramResponse.id, verifiedBy, (contactSuccess) => {
res.send({ authorized: success, message: msg, contactSuccess: contactSuccess }); res.send({ authorized: success, message: msg, contactSuccess: contactSuccess });
}); });
} else { } else {
@ -214,25 +272,6 @@ app.post('/login', (req, res) => {
}); });
}); });
app.post('/create', (req, res) => {
reqTelegram = req.body.telegram.toLowerCase();
if (req.session.verified) {
createUser(reqTelegram, req.body.password, (success, msg) => {
cookieExpiry = getCookieExpiry();
req.session.user = reqTelegram;
if (success) {
addContact(req.session.user, req.session.verifiedBy, (sucesss, msg) => {
res.send({ success: success, message: msg });
});
} else {
res.send({ success: success, message: msg });
}
});
} else {
res.status(401).send("Not verified");
}
})
app.get('/code', (req, res) => { app.get('/code', (req, res) => {
if (!req.session.user) { if (!req.session.user) {
res.status(401).send("Not logged in"); res.status(401).send("Not logged in");

41
package-lock.json

@ -8,6 +8,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"axios": "^0.21.1",
"bcrypt": "^5.0.1", "bcrypt": "^5.0.1",
"connect-session-sequelize": "^7.1.1", "connect-session-sequelize": "^7.1.1",
"cors": "^2.8.5", "cors": "^2.8.5",
@ -202,6 +203,14 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
"optional": true "optional": true
}, },
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -965,6 +974,25 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/foreach": { "node_modules/foreach": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
@ -3431,6 +3459,14 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
"optional": true "optional": true
}, },
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"balanced-match": { "balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -4020,6 +4056,11 @@
"locate-path": "^3.0.0" "locate-path": "^3.0.0"
} }
}, },
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
},
"foreach": { "foreach": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",

1
package.json

@ -10,6 +10,7 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"axios": "^0.21.1",
"bcrypt": "^5.0.1", "bcrypt": "^5.0.1",
"connect-session-sequelize": "^7.1.1", "connect-session-sequelize": "^7.1.1",
"cors": "^2.8.5", "cors": "^2.8.5",

Loading…
Cancel
Save