@MrOnatsky

Работает ли telegram oauth в России?

Сам проверить не могу, но может кто знает? Заранее спасибо!
  • Вопрос задан
  • 200 просмотров
Решения вопроса 1
  • neatsoft
    @neatsoft
    Life is too short for bad software
    Telegram login widget в России не работает, но авторизация через Telegram элементарно реализуется с помощью бота. При отправке команды бот вызывает веб-хук, передавая имя пользователя, в ответ отправляется одноразовая ссылка для входа на сайт. Бота нужно запускать на зарубежном хостинге, т.к. с него должен быть доступен api.telegram.org, пользователь может находиться где угодно.

    Вот пример на Django 2.0 (максимально упрощённый):
    1. Через @BotFather нужно создать нового бота, записать полученный token - <bot_token>
    2. Добавить команду /login с помощью /setcommands
    3. В консоли сгенерировать случайный uuid (uuidgen -r) - <webhook_token>
    4. Настроить веб-хук (вместо httpie можно использовать curl, wget, или любую другую подобную утилиту):
      http "https://api.telegram.org/bot<bot_token>/setWebhook?url=https://<domain_name>/bot/<webhook_token>/"

    5. Внести необходимые изменения в проект
    6. Если используется DatabaseCache, инициализировать таблицу в базе данных:
      ./manage.py createcachetable

    .

    settings.py
    ...
    TELEGRAM_BOT_ACCESS_TOKEN = <bot_token>
    TELEGRAM_BOT_WEBHOOK_TOKEN = <webhook_token>
    TELEGRAM_BOT_OTP_TIMEOUT = 120
    
    USE_X_FORWARDED_HOST = True
    
    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
            'LOCATION': 'django_cache',
        }
    }
    ...


    urls.py
    ...
    from .views import BotView, LoginView
    
    
    urlpatterns = [
        ...
        path('bot/<uuid:token>/', BotView.as_view()),
        path('login/<uuid:otp>/', LoginView.as_view(), name='login'),
    ]


    views.py
    import json
    import requests
    import uuid
    
    from django.conf import settings
    from django.contrib.auth import login
    from django.contrib.auth.models import User
    from django.core.cache import cache
    from django.http import HttpResponse, HttpResponseNotFound, HttpResponseRedirect
    from django.urls import reverse
    from django.utils.decorators import method_decorator
    from django.views import View
    from django.views.decorators.csrf import csrf_exempt
    from django.views.generic import TemplateView
    
    ...
    
    @method_decorator(csrf_exempt, name='dispatch')
    class BotView(View):
        def post(self, request, token):
            if str(token) != settings.TELEGRAM_BOT_WEBHOOK_TOKEN:
                return HttpResponseNotFound()
    
            params = json.loads(request.body)
            message = params['message']
    
            if message.get('text') == '/login':
                user = message['from']
                chat_id = user['id']
                data = {
                    'username': user['username'],
                    'first_name': user.get('first_name', ''),
                    'last_name': user.get('last_name', ''),
                }
    
                otp = uuid.uuid4()
                cache.set(otp, data, settings.TELEGRAM_BOT_OTP_TIMEOUT)
                path = reverse('login', args=[otp])
                login_url = request.build_absolute_uri(path)
    
                url = 'https://api.telegram.org/bot{}/sendMessage?chat_id={}&text={}'.format(
                    settings.TELEGRAM_BOT_ACCESS_TOKEN,
                    chat_id,
                    login_url,
                )
    
                requests.get(url, timeout=10)
    
            return HttpResponse('')
    
    
    class LoginView(TemplateView):
        template_name = 'login.html'
    
        def dispatch(self, request, otp):
            self.data = cache.get(otp, {})
            return super().dispatch(request, otp)
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['data'] = self.data
            return context
    
        def post(self, request, otp):
            cache.delete(otp)
    
            username = self.data.get('username')
            if not username:
                return HttpResponseRedirect(request.path)
    
            user, created = User.objects.update_or_create(
                username=username,
                defaults={
                    'first_name': self.data.get('first_name', ''),
                    'last_name': self.data.get('last_name', ''),
                },
            )
            login(request, user)
    
            path = reverse('home')
            return HttpResponseRedirect(path)


    templates/login.html
    {% extends 'bootstrap4/bootstrap4.html' %}
    
    {% block bootstrap4_content %}
    
    <div class="container">
    
      <div style="padding:5rem; text-align:center;">
        {% if not data %}
          <h1>This url invalid or expired.</h1>
        {% else %}
          <h1>Login as {{ data.username }}</h1>
          <form action="" method="post">
            {% csrf_token %}
            <button type="submit" class="btn btn-primary btn-lg btn-block">
              Login
            </button>
          </form>
        {% endif %}
      </div>
    
    </div>
    
    {% endblock %}
    Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы