parameter secret_token (#1173)

* Added secret token validation
This commit is contained in:
sheldy 2023-06-25 00:40:04 +03:00 committed by GitHub
parent 5b20f81654
commit a890622e40
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 1 deletions

1
CHANGES/1173.feature.rst Normal file
View file

@ -0,0 +1 @@
Added X-Telegram-Bot-Api-Secret-Token header check

View file

@ -131,6 +131,10 @@ class BaseRequestHandler(ABC):
""" """
pass pass
@abstractmethod
def verify_secret(self, telegram_secret_token: str, bot: Bot) -> bool:
pass
async def _background_feed_update(self, bot: Bot, update: Dict[str, Any]) -> None: async def _background_feed_update(self, bot: Bot, update: Dict[str, Any]) -> None:
result = await self.dispatcher.feed_raw_update(bot=bot, update=update, **self.data) result = await self.dispatcher.feed_raw_update(bot=bot, update=update, **self.data)
if isinstance(result, TelegramMethod): if isinstance(result, TelegramMethod):
@ -185,6 +189,8 @@ class BaseRequestHandler(ABC):
async def handle(self, request: web.Request) -> web.Response: async def handle(self, request: web.Request) -> web.Response:
bot = await self.resolve_bot(request) bot = await self.resolve_bot(request)
if not self.verify_secret(request.headers.get("X-Telegram-Bot-Api-Secret-Token", ""), bot):
return web.Response(body="Unauthorized", status=401)
if self.handle_in_background: if self.handle_in_background:
return await self._handle_request_background(bot=bot, request=request) return await self._handle_request_background(bot=bot, request=request)
return await self._handle_request(bot=bot, request=request) return await self._handle_request(bot=bot, request=request)
@ -198,7 +204,12 @@ class SimpleRequestHandler(BaseRequestHandler):
""" """
def __init__( def __init__(
self, dispatcher: Dispatcher, bot: Bot, handle_in_background: bool = True, **data: Any self,
dispatcher: Dispatcher,
bot: Bot,
handle_in_background: bool = True,
secret_token: Optional[str] = None,
**data: Any,
) -> None: ) -> None:
""" """
:param dispatcher: instance of :class:`aiogram.dispatcher.dispatcher.Dispatcher` :param dispatcher: instance of :class:`aiogram.dispatcher.dispatcher.Dispatcher`
@ -208,6 +219,12 @@ class SimpleRequestHandler(BaseRequestHandler):
""" """
super().__init__(dispatcher=dispatcher, handle_in_background=handle_in_background, **data) super().__init__(dispatcher=dispatcher, handle_in_background=handle_in_background, **data)
self.bot = bot self.bot = bot
self.secret_token = secret_token
def verify_secret(self, telegram_secret_token: str, bot: Bot) -> bool:
if self.secret_token:
return secrets.compare_digest(telegram_secret_token, self.secret_token)
return True
async def close(self) -> None: async def close(self) -> None:
""" """
@ -244,6 +261,9 @@ class TokenBasedRequestHandler(BaseRequestHandler):
self.bot_settings = bot_settings self.bot_settings = bot_settings
self.bots: Dict[str, Bot] = {} self.bots: Dict[str, Bot] = {}
def verify_secret(self, telegram_secret_token: str, bot: Bot) -> bool:
return True
async def close(self) -> None: async def close(self) -> None:
for bot in self.bots.values(): for bot in self.bots.values():
await bot.session.close() await bot.session.close()

View file

@ -189,8 +189,24 @@ class TestSimpleRequestHandler:
result = await resp.json() result = await resp.json()
assert not result assert not result
async def test_verify_secret(self, bot: MockedBot, aiohttp_client):
app = Application()
dp = Dispatcher()
handler = SimpleRequestHandler(
dispatcher=dp, bot=bot, handle_in_background=False, secret_token="vasya228"
)
handler.register(app, path="/webhook")
client: TestClient = await aiohttp_client(app)
resp = await self.make_reqest(client=client)
assert resp.status == 401
class TestTokenBasedRequestHandler: class TestTokenBasedRequestHandler:
async def test_verify_secret(self, bot: MockedBot):
dispatcher = Dispatcher()
handler = TokenBasedRequestHandler(dispatcher=dispatcher)
assert handler.verify_secret("petro328", bot)
async def test_register(self): async def test_register(self):
dispatcher = Dispatcher() dispatcher = Dispatcher()
app = Application() app = Application()