没有默认按钮的电报授权

IT技术 javascript reactjs oauth telegram telegram-bot
2021-05-14 03:36:56

使用 Telegram 3-rd 方授权的唯一记录方式是使用https://core.telegram.org/widgets/login提供的脚本

这个脚本(正如我挖掘的那样)以非常奇怪的方式工作

  1. 它在内部呈现“使用 Telegram 登录”按钮,并iframe带有另一个script加载一些 Telegram 实体的额外功能(如TWidgetLogin, TSticker (?) , TVideo (??) , TAudio (???)和其他一些)。
  2. 通过单击按钮,这iframe将打开正在执行授权的新窗口。
  3. 授权完成后,此窗口关闭,完成后,iframe再次检查授权。如果以正确的方式完成,则iframe检索所有共享用户信息并取决于授权结束调用的类型data-onauth或将请求发送到data-auth-url.

这种行为对我来说真的无法使用,因为我们也在附近使用 Google、Github 和 Facebook OAuths,并且所有这些都提供了正常可用的 API 来手动打开授权窗口并重定向到指定的 url。

我的意思是,这就是我们的,例如,谷歌授权的工作方式:

  1. 用户点击我们自己创建的按钮,自定义以匹配我们的应用程序风格。
  2. 单击时,我们的应用程序会使用 url 创建新窗口 https://hostname/some/path/to/auth?and_some_params=here
  3. 我们的服务器捕获此信息并重定向到 Google OAuth 同意屏幕。
  4. 谷歌授权完成后,将用户重定向到另一个 /some/path/to/completed_authorization
  5. 服务器检索所有必要的信息,并将窗口重定向到具有授权信息的父窗口的/some/path/to/success_authorization脚本window.postMessage
  6. 父窗口(应用程序窗口)捕获此消息,关闭窗口并使用给定的用户数据填充存储空间。

大功告成。由于打开的窗口是由应用程序打开的,因此它可以在不使用时被控制和关闭(例如,当另一个身份验证窗口正在打开时,或者当应用程序选项卡正在关闭时)。

电报中不合适的“使用电报登录”按钮是:

  1. 无法将按钮风格化以匹配应用程序风格
  2. 无法更改按钮的内容(在我们的例子中是必要的,因为我们的应用程序是多语言的)。
  3. 无法控制打开的窗口(即使主窗口关闭,它也会被打开)

现在我可以使用 Telegram OAuth 屏幕打开一个窗口

// some code above
this.popup = window.open("https://oauth.telegram.org/auth?bot_id=<my_bot_id>&origin=http%3A%2F%2F<mydevorigin>&request_access=write, "authWindow", <some window params>)
// some code below

但是由于授权正在完成,我无法设置任何内容让服务器知道它应该检索用户数据并重定向到我的页面 window.postMessage

有没有办法在没有“使用电报登录”按钮的情况下获得电报授权?任何帮助都受到高度赞赏。

2个回答

因此,有一种更简单的方法可以做到这一点,而无需直接收听 postMessages。

Telegram widget 脚本https://telegram.org/js/telegram-widget.js添加Telegram对象到窗口,这个对象有Login属性,有auth功能。

auth函数接受optionsand callback,像这样:

declare const auth: (options: Options, callback: Callback) => void;

interface Options {
  bot_id: string;
  request_access?: boolean;
  lang?: string;
}

interface Data {
  auth_date: number;
  first_name: string;
  hash: string;
  id: number;
  last_name: string;
  username: string;
  // I think there could be other properties too
}

type Callback = (dataOrFalse: Data | false) => void;

请注意,如果授权不成功callback将使用false布尔值调用

因此,您需要做的就是加载小部件脚本(没有数据属性,否则它将使用按钮初始化 iframe),然后在需要时调用此函数:

window.Telegram.Login.auth(
  { bot_id: 'YOUR_BOT_ID', request_access: true },
  (data) => {
    if (!data) {
      // authorization failed
    }

    // Here you would want to validate data like described there https://core.telegram.org/widgets/login#checking-authorization
    doWhateverYouWantWithData(data);
  }
);

auth将打开另一个具有 Telegram 授权界面的窗口,并将自行侦听此窗口发布消息。当窗口关闭时,您callback将被调用。

@Limbo 正如我所见——生成的小部件和代码只是根据我们的机器人名称和其他参数创建了一个包含内容的 iframe。它每次都一样。例如对于(https://oauth.telegram.org/embed/samplebot?origin=https%3A%2F%2Fcore.telegram.org&size=medium&userpic=false),响应中感兴趣的部分在这里:

<div class="tgme_widget_login medium nouserpic" id="widget_login"><button class="btn tgme_widget_login_button" onclick="return TWidgetLogin.auth();"><i class="tgme_widget_login_button_icon"></i>Log in with Telegram</button></div>

<script src="//telegram.org/js/widget-frame.js?27"></script>
<script>TWidgetLogin.init('widget_login', 547043436, {"origin":"https:\/\/core.telegram.org"}, false, "en");

而且每次都是一样的。因此,您只需将此代码添加到您可以自定义按钮样式的页面,并根据需要放置在页面的任何位置。只需注意 id 参数,不要忘记为 onClick 添加一个事件侦听器,当您想显示登录弹出窗口时,它将调用 TWidgetLogin.auth()。

TWidgetLogin.init 函数接受几个参数(target_login_btn_id、bot_id、params、init_auth、lang)。所有这些都是自我描述的。

有趣的部分 - 是关于获取身份验证信息。如果您检查该 widget-frame.js,您会发现在成功验证后,它window.parent.postMessage(JSON.stringify(data), origin || '*');使用数据参数中的用户数据调用在我们的例子中(我们在没有 iframe 的情况下运行) postMessage 将被传递到当前窗口,您将能够使用简单的代码捕获它

window.addEventListener("message", function(event) {console.log('get message, evetn)}, false);

您可以在其中获取所需的所有用户数据。

唯一的事情- 该消息的来源。但是这个参数脚本从电报服务器获取用户数据,所以我怀疑它会包含链接的站点来源,我们不会有任何问题。

祝进一步调查好运。