Created
August 18, 2022 08:32
-
-
Save hypernova7/34d90bd7faefbc9ce8d00279ddb01ddc to your computer and use it in GitHub Desktop.
Telegram bot login example using Telegraf v4 and Express
This file contains 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
import 'dotenv/config'; | |
import crypto from 'node:crypto'; | |
import express from 'express'; | |
import cookieSession from 'cookie-session'; | |
import { Markup, session, Telegraf } from 'telegraf'; | |
import consola from 'consola'; | |
const logger = consola.withTag('tg-check-auth'); | |
const bot = new Telegraf(process.env.BOT_TOKEN); | |
const app = express(); | |
bot.use(session()); | |
bot.use((ctx, next) => { | |
ctx.session = ctx.session || {}; | |
return next(); | |
}); | |
bot.start(ctx => { | |
const { startPayload } = ctx; | |
if (startPayload.startsWith('login-')) { | |
if (startPayload === 'login-fail') { | |
ctx.session.loginFail = true; | |
return login(ctx); | |
} | |
if (startPayload === `login-${ctx.from.id}`) ctx.reply('You have already logging in'); | |
if (startPayload === 'login-success') ctx.reply('You are logged in'); | |
ctx.session.loggedIn = true; | |
return; | |
} | |
ctx.reply(`Hi ${[ctx.from.first_name, ctx.from.last_name].filter(Boolean).join(' ')}`); | |
}); | |
bot.command('login', login); | |
// To use the login button, you need to setup a domain for your bot with @BotFather | |
async function login (ctx) { | |
if (ctx.session.loggedIn) return ctx.reply('You have already logging in'); | |
await ctx.replyWithHTML( | |
!ctx.session.loginFail | |
? 'Sign In with <b>Telegram</b>' | |
: 'Something went wrong, please try again or try again later', | |
{ | |
...Markup.inlineKeyboard([ | |
Markup.button.login('Sign In', 'https://yourdomain.com/auth') | |
]) | |
} | |
); | |
} | |
// Setup cookie-session | |
app.use( | |
cookieSession({ | |
name: 'session', | |
keys: [process.env.BOT_TOKEN], | |
maxAge: 24 * 60 * 60 * 1000 // 24 hours | |
}) | |
); | |
app.get('/auth', auth); | |
function auth (req, res) { | |
let loggedIn = true; | |
const url = 'https://t.me/yourbotusername?start=login-'; | |
// Use the start parameter to send proof that the user is already logged in | |
if (req.session.user) // Prevent re-authentication and redirect to the bot | |
return res.redirect(`${url}${req.session.user}`); | |
// Authentication | |
const { auth_date, hash, id } = req.query; | |
if (auth_date && hash && id) { | |
const time = Date.now() / 1000; | |
const authTime = Number.parseInt(auth_date, 10); | |
const key = crypto.createHash('sha256').update(process.env.BOT_TOKEN).digest(); | |
const data = Object.keys(req.query) | |
.sort() | |
.filter(key => key !== 'hash') | |
.map(key => `${key}=${req.query[key]}`) | |
.join('\n'); | |
const secret = crypto.createHmac('sha256', key).update(data).digest('hex'); | |
if (hash.localeCompare(secret) === 0 && time - authTime <= 86_400) { | |
// Set session | |
req.session.user = id; | |
logger.success('Successful login'); | |
} else { | |
loggedIn = false; | |
} | |
} else { | |
loggedIn = false; | |
} | |
// Use the start parameter to inform the user if the login was successful or failed | |
res.redirect(`${url}${loggedIn ? 'success' : 'fail'}`); | |
} | |
bot.launch({ | |
// Setup a webhook to use login button. required | |
webhook: { | |
domain: 'yourdomain.com', | |
port: +process.env.PORT, | |
cb: app // Integrate Express with Telegraf | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment