79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
import base64
|
|
import hashlib
|
|
import hmac
|
|
import json
|
|
import time
|
|
|
|
from django.http import HttpResponseRedirect
|
|
from django.shortcuts import render
|
|
from django.urls import reverse
|
|
from django.utils.decorators import method_decorator
|
|
from django.utils.http import urlencode
|
|
from django.views import View
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
|
|
from allauth.socialaccount.adapter import get_adapter
|
|
from allauth.socialaccount.helpers import (
|
|
complete_social_login,
|
|
render_authentication_error,
|
|
)
|
|
|
|
from .provider import TelegramProvider
|
|
|
|
|
|
class LoginView(View):
|
|
def dispatch(self, request):
|
|
provider = get_adapter().get_provider(request, TelegramProvider.id)
|
|
return_to = request.build_absolute_uri(
|
|
reverse("telegram_callback") + "?" + request.GET.urlencode()
|
|
)
|
|
|
|
url = "https://oauth.telegram.org/auth?" + urlencode(
|
|
{
|
|
"origin": request.build_absolute_uri("/"),
|
|
"bot_id": provider.app.client_id,
|
|
"request_access": "write",
|
|
"embed": "0",
|
|
"return_to": return_to,
|
|
}
|
|
)
|
|
return HttpResponseRedirect(url)
|
|
|
|
|
|
login = LoginView.as_view()
|
|
|
|
|
|
@method_decorator(csrf_exempt, name="dispatch")
|
|
class CallbackView(View):
|
|
def get(self, request):
|
|
return render(request, "telegram/callback.html")
|
|
|
|
def post(self, request):
|
|
result = request.POST.get("tgAuthResult")
|
|
padding = "=" * (4 - (len(result) % 4))
|
|
data = json.loads(base64.b64decode(result + padding))
|
|
adapter = get_adapter()
|
|
provider = adapter.get_provider(request, TelegramProvider.id)
|
|
hash = data.pop("hash")
|
|
payload = "\n".join(sorted(["{}={}".format(k, v) for k, v in data.items()]))
|
|
token = provider.app.secret
|
|
token_sha256 = hashlib.sha256(token.encode()).digest()
|
|
expected_hash = hmac.new(
|
|
token_sha256, payload.encode(), hashlib.sha256
|
|
).hexdigest()
|
|
auth_date = int(data.pop("auth_date"))
|
|
auth_date_validity = provider.get_auth_date_validity()
|
|
if hash != expected_hash or time.time() - auth_date > auth_date_validity:
|
|
return render_authentication_error(
|
|
request, provider_id=provider.id, extra_context={"response": data}
|
|
)
|
|
|
|
login = provider.sociallogin_from_response(request, data)
|
|
process = request.GET.get("process")
|
|
if process:
|
|
login.state["process"] = process
|
|
return complete_social_login(request, login)
|
|
|
|
|
|
callback = CallbackView.as_view()
|