본문 바로가기
텔레그램 한글 가이드
채널·봇 STEP 75 / 98

텔레그램 미니 앱 사용자 확인 — initData 서명 검사

텔레그램 미니 앱이 받은 사용자 정보를 서버에서 믿을 수 있게 확인하는 방법입니다. initData 와 initDataUnsafe 의 차이, 봇 토큰으로 hash 를 검사하는 순서와 파이썬 예시, auth_date 확인, 토큰 없이 쓰는 Ed25519 서명을 정리했습니다.

  • 난이도L4
  • 읽는 시간5분
  • 최종 검증

결론부터

  1. 1화면에서 받은 사용자 정보는 서명 검사 전엔 믿지 않는다.
  2. 2initData 를 서버로 — 키 순 정렬, WebAppData 비밀 키로 hash 비교.
  3. 3auth_date 가 오래됐거나 initData 가 비면 거절한다.
이 글의 목차
  1. 왜 검사해야 하나
  2. 봇 토큰으로 검사하기
  3. 토큰 없이 검사하기 — 남이 확인할 때
  4. 열린 방법에 따라 initData 가 없을 수 있다
  5. 자주 묻는 질문
  6. 한눈에 정리

왜 검사해야 하나

미니 앱이 열리면 텔레그램은 웹페이지에 '지금 이 앱을 연 사용자' 정보를 넘겨 줍니다. 그런데 이 값은 결국 사용자 기기의 브라우저 안에 있는 데이터라, 마음먹으면 누구나 바꿔서 내 서버로 보낼 수 있습니다. 그래서 서버는 텔레그램의 서명을 확인한 뒤에만 그 사용자를 믿습니다. 포인트 지급·주문·로그인처럼 돈이나 계정이 걸린 일은 특히 그렇습니다.

값무엇쓰는 곳
initData원래 모양 그대로의 문자열(서명 포함)서버로 보내 검사한다
initDataUnsafe그 문자열을 풀어 놓은 객체화면에 이름을 띄우는 정도만 — 믿지 않는다

봇 토큰으로 검사하기

  1. 미니 앱 화면이 Telegram.WebApp.initData 문자열을 그대로 내 서버에 보냅니다.
  2. 서버는 문자열을 키=값 쌍으로 나누고, hash 를 따로 빼 둡니다.
  3. 나머지 쌍을 키 이름 순으로 정렬해 줄바꿈 문자로 이어 붙입니다(검사용 문자열).
  4. 비밀 키 = 봇 토큰을 WebAppData 라는 고정 키로 HMAC-SHA256 한 값.
  5. 검사용 문자열을 그 비밀 키로 HMAC-SHA256 한 결과(16진수)가 빼 둔 hash 와 같으면 텔레그램이 만든 값입니다.
  6. auth_date(만든 시각)가 너무 오래됐으면 거절합니다 — 예전에 훔친 값을 다시 쓰는 것을 막습니다.
import hmac, hashlib, time
from urllib.parse import parse_qsl

def check(init_data, bot_token, max_age=3600):
    pairs = dict(parse_qsl(init_data))
    received = pairs.pop("hash", "")
    text = chr(10).join(f"{k}={v}" for k, v in sorted(pairs.items()))  # 줄바꿈으로 잇기
    secret = hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest()
    ok = hmac.compare_digest(
        hmac.new(secret, text.encode(), hashlib.sha256).hexdigest(), received)
    return ok and time.time() - int(pairs.get("auth_date", 0)) < max_age

예시 코드는 이해를 돕는 최소 형태입니다(파이썬 표준 라이브러리만). 허용할 시간(max_age)은 내 서비스에 맞게 정합니다.

토큰 없이 검사하기 — 남이 확인할 때

봇 토큰을 가진 내 서버가 아닌 다른 서비스가 사용자를 확인해야 할 때를 위해, initData 에는 signature(Ed25519 서명)도 들어 있습니다. 이 서명은 텔레그램이 공개한 공개 키로 확인하므로 봇 토큰을 넘길 필요가 없습니다. 검사용 문자열 만드는 법이 조금 다르니(봇 ID 를 앞에 붙임) 이 방식을 쓸 때는 원문 절차를 그대로 따릅니다.

열린 방법에 따라 initData 가 없을 수 있다

미니 앱을 연 곳initData
인라인 버튼 · 메뉴 버튼 · 메인 미니 앱 · 직접 링크 · 첨부 메뉴있다
답장 키보드 버튼 · 인라인 모드없다 — 답장 키보드로 연 앱은 sendData 로 봇에게 최대 4096바이트를 돌려보내는 방식

initData 가 비어 있으면 '사용자를 모른다'로 처리합니다. 빈 값을 통과시키는 실수가 가장 흔합니다.

미니 앱을 띄우는 버튼은 봇 메뉴 버튼, 사이트 밖에서의 텔레그램 로그인은 로그인 위젯, 미니 앱 만들기 처음은 미니 앱 만들기 입문에 있습니다.

자주 묻는 질문

텔레그램 미니 앱 initDataUnsafe 를 써도 되나요?

화면에 이름을 보여 주는 정도만 씁니다. 돈이나 계정이 걸린 처리는 서버에서 initData 의 hash 를 검사한 뒤에 합니다.

initData 검사에 봇 토큰이 필요한가요?

hash 검사에는 필요하므로 서버에서 합니다. 토큰 없이 확인해야 하면 signature 를 텔레그램 공개 키로 검사합니다.

initData 가 비어 있어요.

답장 키보드 버튼이나 인라인 모드로 연 미니 앱에는 initData 가 없습니다. 이때는 사용자를 모르는 것으로 처리합니다.

auth_date 는 왜 보나요?

예전에 빼낸 initData 를 다시 쓰는 것을 막기 위해, 만든 지 오래된 값은 거절합니다.

참고한 공식 문서

요약

한눈에 정리

  1. 1서버로

    initData 원문 그대로.

  2. 2검사

    정렬 · HMAC · hash 비교.

  3. 3거절

    오래된 값 · 빈 값.

이 글 공유하기

같은 문제를 겪는 친구에게 보내 주세요.

텔레그램
더보기

휴대폰으로 열기휴대폰 카메라로 비추면 이 글이 열려요.

최종 수정 2026-10-06

함께 보면 좋은 글

전체 보기 ›