没有默认按钮的电报授权

Lim*_*mbo 8 javascript oauth reactjs telegram telegram-bot

使用Telegram第三方授权的唯一记录方法是使用https://core.telegram.org/widgets/login提供的脚本

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

  1. 它将在其中呈现“使用电报登录”按钮,并iframe带有另一个附加功能script,该按钮可加载要使用的某些电报实体(例如TWidgetLoginTSticker (?)TVideo (??)TAudio (???)和其他一些)。
  2. 通过单击按钮,这iframe将打开正在执行授权的新窗口。
  3. 授权完成后,此窗口将关闭,既然完成了,请iframe再次检查授权。如果操作正确,则iframe检索所有共享的用户信息,并取决于授权结束调用的类型,data-onauth或将请求发送到data-auth-url

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

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

  1. 用户单击我们自己创建的按钮,该按钮经过定制以匹配我们的应用程序样式。
  2. 点击后,我们的应用程序会创建带有网址的新窗口 https://hostname/some/path/to/auth?and_some_params=here
  3. 我们的服务器将其捕获,并重定向到Google OAuth同意屏幕。
  4. 完成Google授权后,它将用户重定向到另一个 /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
Run Code Online (Sandbox Code Playgroud)

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

没有其“使用电报登录”按钮,是否有任何方法可以实现电报授权?非常感谢您的帮助。

Dan*_*ila 7

所以有一种更简单的方法来做到这一点,而无需直接监听 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;
Run Code Online (Sandbox Code Playgroud)

请注意,如果授权不成功,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);
  }
);
Run Code Online (Sandbox Code Playgroud)

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


小智 5

@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");
Run Code Online (Sandbox Code Playgroud)

而且每次都是一样的。因此,您只需将此代码添加到您可以自定义按钮样式的页面,并根据需要放置在页面的任何位置。只需注意 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);
Run Code Online (Sandbox Code Playgroud)

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

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

祝进一步调查好运。