require("dotenv").config(); const express = require("express"); const session = require("express-session"); const helmet = require("helmet"); const crypto = require("crypto"); const { createRemoteJWKSet, jwtVerify } = require("jose"); const app = express(); const PORT = process.env.PORT || 3000; const CLIENT_ID = process.env.CLIENT_ID; const CLIENT_SECRET = process.env.CLIENT_SECRET; const BASE_URL = process.env.BASE_URL; const CALLBACK_URL = `${BASE_URL}/auth/callback`; if (!CLIENT_ID || !CLIENT_SECRET || !BASE_URL || !process.env.SESSION_SECRET) { throw new Error("Missing environment variables"); } app.use( helmet({ contentSecurityPolicy: false, crossOriginOpenerPolicy: { policy: "same-origin-allow-popups" } }) ); app.use(express.urlencoded({ extended: false })); app.use( session({ name: "telegram_login_session", secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: BASE_URL.startsWith("https://"), sameSite: "lax", maxAge: 60 * 60 * 1000 } }) ); const JWKS = createRemoteJWKSet( new URL( "https://oauth.telegram.org/.well-known/jwks.json" ) ); function randomString() { return crypto.randomBytes(32).toString("base64url"); } function createChallenge(verifier) { return crypto .createHash("sha256") .update(verifier) .digest("base64url"); } // HOME PAGE app.get("/", (req, res) => { const user = req.session.user; if (user) { return res.send(` My Dashboard

Welcome!

${escapeHTML(user.name || "")}

Username: @${escapeHTML(user.username || "Not available")}

Telegram ID: ${escapeHTML(user.sub || "")}

`); } res.send(` Telegram Login

Welcome

Login securely with Telegram.

Login with Telegram
`); }); function escapeHTML(value) { return String(value).replace(/[&<>"']/g, char => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[char]); } // START TELEGRAM LOGIN app.get("/auth/telegram", (req, res) => { const state = randomString(); const nonce = randomString(); const verifier = randomString(); req.session.oauth = { state, nonce, verifier, created: Date.now() }; const challenge = createChallenge(verifier); const params = new URLSearchParams({ client_id: CLIENT_ID, redirect_uri: CALLBACK_URL, response_type: "code", scope: "openid profile", state, nonce, code_challenge: challenge, code_challenge_method: "S256" }); res.redirect( "https://oauth.telegram.org/auth?" + params.toString() ); }); // TELEGRAM CALLBACK app.get("/auth/callback", async (req, res) => { try { const { code, state, error } = req.query; if (error) { return res.status(400).send( "Telegram authorization was cancelled." ); } const oauth = req.session.oauth; if ( !oauth || !code || !state || state !== oauth.state || Date.now() - oauth.created > 5 * 60 * 1000 ) { return res.status(400).send( "Invalid or expired login request." ); } // Exchange authorization code const credentials = Buffer .from(`${CLIENT_ID}:${CLIENT_SECRET}`) .toString("base64"); const tokenResponse = await fetch( "https://oauth.telegram.org/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "Authorization": `Basic ${credentials}` }, body: new URLSearchParams({ grant_type: "authorization_code", code, redirect_uri: CALLBACK_URL, client_id: CLIENT_ID, code_verifier: oauth.verifier }) } ); if (!tokenResponse.ok) { throw new Error("Token exchange failed"); } const tokens = await tokenResponse.json(); if (!tokens.id_token) { throw new Error("Missing ID token"); } // Verify Telegram ID token const { payload } = await jwtVerify( tokens.id_token, JWKS, { issuer: "https://oauth.telegram.org", audience: CLIENT_ID } ); if ( !payload.nonce || payload.nonce !== oauth.nonce ) { throw new Error("Invalid nonce"); } // Create website session const user = { sub: payload.sub, name: payload.name || "", username: payload.preferred_username || "", picture: payload.picture || "" }; delete req.session.oauth; req.session.regenerate((err) => { if (err) { return res.status(500).send( "Session error." ); } req.session.user = user; req.session.save((err) => { if (err) { return res.status(500).send( "Could not save session." ); } res.redirect("/"); }); }); } catch (error) { console.error("Login error:", error.message); res.status(401).send( "Telegram login failed. Please try again." ); } }); // LOGOUT app.post("/logout", (req, res) => { req.session.destroy(() => { res.clearCookie("telegram_login_session"); res.redirect("/"); }); }); // START SERVER app.listen(PORT, () => { console.log( `Website running at ${BASE_URL}` ); });