In the previous article, you can access and update your Google Spreadsheet using Python, and you have created our Telegram Bot and stored it on our Python password vault – keyring. Securing your Telegram Bot app against unauthorized access is essential. A simple authentication method can ensure that only authorized users can access your Telegram Bot app preventing data breaches or other security incidents from compromising your user’s information. This article will teach you how to secure your Telegram Bot app with a simple authentication method.
Prerequisite: You have put your credential JSON file into your Python project directory, and you must install aiogram, keyring, gspread and oauth2client in your Python environment. You may install these libraries by
pip install aiogram
pip install oauth2client
pip install gspread
pip install keyring
Step 1: Initialize the program by
import logging
from aiogram import Bot, Dispatcher, executor, types
from aiogram.types import ReplyKeyboardMarkup
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import traceback
import keyring
# Configure logging, initialize the bot and the dispatcher
logging.basicConfig(level=logging.INFO)
API_TOKEN = keyring.get_password("api", "telegram")
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)
if __name__ == '__main__':
answers = [] # store the answers they have given
password = "silicon.blog"
scope = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]
credentials = ServiceAccountCredentials.from_json_keyfile_name('genuine-amulet-386508-e126616283cf.json', scope)
gs_client = gspread.authorize(credentials)
docid = "1BVg-WgsDEjembne02KQ7F7U3EQLq33BG7uuybmFAZXs"
userid_tsv_location = 'whitelisted_user.tsv'
executor.start_polling(dp, skip_updates=True)
The part between import keyring and if __name__ == ‘__main__’: will initialize your Telegram Bot. You may save your password into keyring if you want. XD The docid and userid_tsv_location come from the previous article.
Step 2: we need to add a message handler after the line dp = Dispatcher(bot) and if __name__ == ‘__main__’:. It will handle every message anyone sends to your discord bot by default.
@dp.message_handler()
async def default(message: types.Message):
Step 3: Inside the default message handler, you must first download your latest Google Spreadsheet authentication file from the cloud because it acts as your user database.
########################################
########################################
########################################
#
# sync whitelisted_user from Google cloud
#
########################################
########################################
########################################
try:
spreadsheet = gs_client.open_by_key(docid)
export_file = spreadsheet.export(format=gspread.utils.ExportFormat.TSV)
f = open(userid_tsv_location, 'wb')
f.write(export_file)
f.close()
except:
traceback.print_exc()
Step 4: Keep asking for the password of an unauthorized user. Append the user id to the whitelisted user list if the password is correct. This article does not include blocking users after 5 retries or a similar function to fail2ban. You may try to write it by yourself.
uid = []
########################################
########################################
########################################
#
# Auth
#
########################################
########################################
########################################
try:
with open(userid_tsv_location, 'r', encoding="utf8") as f:
for line in f:
filtered_data = line.replace("\n","").split('\t')
uid.append(filtered_data[0])
except Exception:
print("No data!")
if(str(message.from_user.id) not in uid and message.text not in password):
await message.answer("Your user id is not in the whitelist. Please enter the passcode.")
elif(str(message.from_user.id) not in uid and message.text in password): #add user to the whitelist
uid.append(message.from_user.id)
Step 5: The elif case has not ended yet. Write the latest whitelisted user list to a local file first.
########################################
########################################
########################################
#
# write lastest whitelist to local file
#
########################################
########################################
########################################
count = 0
with open(userid_tsv_location, 'w', encoding="utf8") as f:
while count < len(uid):
data = "".join([str(uid[count]),'\n'])
f.write(data)
count+=1
print("".join(["Added ",str(uid)," to the whitelist!"]))
Step 6: Continue the elif case. Synchronize the latest whitelisted user list to your Google Spreadsheet (user database). Send a message on Telegram telling your user you have registered them on your user database.
########################################
########################################
########################################
#
# sync whitelisted_user to Google Spreadsheet
#
########################################
########################################
########################################
content = open(userid_tsv_location, 'r', encoding="utf8").read()
gs_client.import_csv(docid, content)
print("Uploaded to cloud")
await message.answer('Added your user id to the whitelist.')
Execute the program. The output will be something like this:
Also, have a look at your Google Spreadsheet. Your Telegram user id should now be included.
Congratulation! You can now secure your Telegram Bot app with a simple authentication method. In the following article, we will ask some simple questions to our whitelisted users. You will also learn how to create a list of options.
The complete Python script
import logging
from aiogram import Bot, Dispatcher, executor, types
from aiogram.types import ReplyKeyboardMarkup
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import traceback
import keyring
# Configure logging, initialize the bot and the dispatcher
logging.basicConfig(level=logging.INFO)
API_TOKEN = keyring.get_password("api", "telegram")
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)
@dp.message_handler()
async def default(message: types.Message):
########################################
########################################
########################################
#
# sync whitelisted_user from Google cloud
#
########################################
########################################
########################################
try:
spreadsheet = gs_client.open_by_key(docid)
export_file = spreadsheet.export(format=gspread.utils.ExportFormat.TSV)
f = open(userid_tsv_location, 'wb')
f.write(export_file)
f.close()
except:
traceback.print_exc()
uid = []
########################################
########################################
########################################
#
# Auth
#
########################################
########################################
########################################
try:
with open(userid_tsv_location, 'r', encoding="utf8") as f:
for line in f:
filtered_data = line.replace("\n","").split('\t')
uid.append(filtered_data[0])
except Exception:
print("No data!")
if(str(message.from_user.id) not in uid and message.text not in password):
await message.answer("Your user id is not in the whitelist. Please enter the passcode.")
elif(str(message.from_user.id) not in uid and message.text in password): #add user to the whitelist
uid.append(message.from_user.id)
########################################
########################################
########################################
#
# write lastest whitelist to local file
#
########################################
########################################
########################################
count = 0
with open(userid_tsv_location, 'w', encoding="utf8") as f:
while count < len(uid):
data = "".join([str(uid[count]),'\n'])
f.write(data)
count+=1
print("".join(["Added ",str(uid)," to the whitelist!"]))
########################################
########################################
########################################
#
# sync whitelisted_user to Google Spreadsheet
#
########################################
########################################
########################################
content = open(userid_tsv_location, 'r', encoding="utf8").read()
gs_client.import_csv(docid, content)
print("Uploaded to cloud")
fruitOptions = ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
fruitOptions.add('@Apple')
fruitOptions.add('@Watermelon')
fruitOptions.add('@Mango')
await message.answer('Added your user id to the whitelist.)
if __name__ == '__main__':
answers = [] # store the answers they have given
password = "silicon.blog"
scope = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]
credentials = ServiceAccountCredentials.from_json_keyfile_name('genuine-amulet-386508-e126616283cf.json', scope)
gs_client = gspread.authorize(credentials)
docid = "1BVg-WgsDEjembne02KQ7F7U3EQLq33BG7uuybmFAZXs"
userid_tsv_location = 'whitelisted_user.tsv'
executor.start_polling(dp, skip_updates=True)