电报机器人 - OAuth 授权

Posted

技术标签:

【中文标题】电报机器人 - OAuth 授权【英文标题】:Telegram bot - OAuth authorization 【发布时间】:2016-09-12 21:17:06 【问题描述】:

我想在我的机器人上通过 Twitch API 实现 OAuth 授权,当我在寻找更好的解决方案时,我发现了这个 @GitHubBot。在这个以integrations.telegram.org/github 开始的机器人重定向URL 中,我想知道如何实现这样的身份验证。如果你愿意,你能告诉在电报机器人中实施 OAuth 的最佳实践吗?哪种情况更好:授权码还是隐式授权? 提前谢谢!

【问题讨论】:

刚刚意识到它是如何完成的,希望在我有时间的几个小时内详细回答您的问题。 (在 6 个字中:使用 /start 代码重定向到 telegram.me) 【参考方案1】:

我有通过 Telegram 授权访问 3rd 方服务的相同想法,我有两个主要想法。 灵感来自解释deep linking usage:

第一个想法是创建具有唯一重定向 URI 的唯一授权 URL。 不幸的是,我在 Google 控制台中设置凭据时错过了有关重定向 URI 的解释。它说

"授权的重定向 URI 用于来自 Web 服务器的请求。 这是您的应用程序中用户被重定向到的路径 在他们通过 Google 进行身份验证后。路径将被附加 使用授权码进行访问。必须有协议。不能 包含 URL 片段或相对路径。不能是公网IP 地址。 "

所以,这种方法动态唯一重定向 URI 是一个失败的请求。

第二个是获取资源的访问权限,然后将散列的授权结果直接发送给机器人。 预计看起来像这样: ttps://telegram.me/bot?hashed_code=code 但是,不幸的是,我发现这也无法按计划进行。 我对这个事实感到非常失望,但经过一番偷偷摸摸后,我发现通过直接 URL 将参数传递给机器人的唯一方法是 /start 命令!

@BotSupport 证实了我的假设:

JV,[17.09.16 22:16] 我需要在 3rd 方服务中授权用户。 例如,谷歌日历。所以,我决定创建一个简单的 URI 重定向到服务登录并将 URL 重定向到我的服务器 令牌\身份验证码。至于 oauth 不验证用户,我仍然 需要以某种方式确定谁确切授予了访问他的资源的权限。所以 我的下一个合乎逻辑的步骤是散列收到的令牌并将其发送回 用户通过 ttps://telegram.me/BOT?code=xxx 我确信如果 /code 有 commandHandler 并且 /code 在 bot 命令中 列表我将能够与我的机器人打开对话并发送此 通过 webhook 将哈希代码返回到我的服务器以检测谁 正是在访问授权步骤。当我发现时我很震惊 我的计划在最后一步被毁了:据我所知,只有 /start 命令可能会被触发。我的问题是:你能确认 只有 /start 命令可以通过 URL 查询参数?如果是这样,可以 你给我一些关于正确授权方式的建议和 认证用户?

机器人支持,[20.09.16 01:50] 您好,抱歉让您久等了。你在讲话 关于深度链接 (https://core.telegram.org/bots#deep-linking) 和, 实际上,那里只能使用 /start 和 /startgroup。

最后我能够成功执行用户授权\识别,但是在对话中间看到开始按钮看起来很奇怪。

简历:您不能像在 ttps://telegram.me/youtube 或 ttps://telegram.me/GitHubBot 中那样执行静默授权,但您可以执行“关闭足够”版本的静默oauth授权

注意:目前我很难说出这些机器人是如何实现的(youtube、GitHubBot),但它应该是这些机器人的一些独特后门,因为它们重定向到 ttps ://integrations.telegram.org/youtube/oauth_redirect 具有相同的方案(至少,来自 oauth 服务的重定向 URI 不包含唯一信息来识别用户,就像我在这篇文章中描述的那样) 也许,有一种方法可以使用某些参数使 auth URL 唯一,但据我所知,这是不允许的。

方案实施步骤:

    设置 webhook 添加 oauth_cb 端点 在例如 Google Console 中为您的应用获取凭据 等待回调到 oauth_cb end_point 为第 4 步中的授权代码生成哈希 将 hash 和 auth_code 保存为键值对 使用来自 5 的哈希创建重定向到您的机器人的 URL 生成包含来自 7 的重定向 URL 的 html 使用参数将 8 实际重定向到您的机器人 为需要内联参数的 /start 命令编写解析器 使用 /start 命令等待 webhook 使用来自 6 的键值对识别用户 移除键值对 你太棒了!现在您可以访问一些用户数据了

抱歉,没有图片或链接,就我没有声誉而言

【讨论】:

好的,我发现使用个性化链接的方法是可能的:OAuth RFC 允许您添加自定义唯一参数“状态”,该参数将从授权请求传递到最后。顺便说一句,它是一个强烈推荐的参数,因为它应该是唯一的签名哈希,旨在防止身份验证代码伪造。因此,我使用相同的缓存机制,除了根据用户请求为一个用户个人生成的身份验证 URL。我设法使静默 OAuth 就像使用 YouTube 或 GitHub 机器人完成的一样。希望,我在我的研究中帮助了某人 您好,您能否将您对该流程的实现发布到 github,或者如果您已经完成,请给我一个链接?非常感谢!【参考方案2】:

我通过Telegram deep linking 和AWS API Gateway 服务解决了这个问题。

认证场景是这样的:

    机器人告诉用户打开服务链接并登录 服务重定向到您设置的 URL:即向该 URL 发送请求,其中包含 OAuth 代码作为 code 参数

您需要在您的机器人中接收该代码,但您不能只重定向到您的机器人的 URL,因为它接受的唯一参数是 start。这在@evasyuk 的回答中有很好的描述。

我的解决方案是设置一个 AWS API Gateway 终端节点,该终端节点将使用来自服务的身份验证代码接收回调,并使用 start 参数将其重定向到您的机器人链接。以下是执行此操作的基本步骤。

我假设您有一个 AWS 账户,但如果没有,它很容易创建,您可以完全免费使用该解决方案一年:

API Gateway 免费套餐包括每月 100 万次 API 调用,最长可达 12 个月。

    前往控制台create a new API Gateway。您可以新建一个并按照步骤操作,也可以导入 Swagger 定义(不要忘记更改机器人 URL!)

    ---
    swagger: "2.0"
    info:
      version: "2017-02-25T14:22:32Z"
      title: "BotAuthRedirect"
    schemes:
    - "https"
    paths:
      /:
        x-amazon-apigateway-any-method:
          produces:
          - "text/html"
          parameters:
          - name: "code"
            in: "query"
            required: false
            type: "string"
          responses:
            200:
              description: "200 response"
              schema:
                $ref: "#/definitions/Empty"
          x-amazon-apigateway-integration:
            type: "http"
            httpMethod: "GET"
            passthroughBehavior: "when_no_match"
            responses:
              default:
                statusCode: "200"
            requestParameters:
              # This is where we map `code` query parameter to `start`
              integration.request.querystring.start: "method.request.querystring.code"
            # Don't forget to change your bot's username:
            uri: "https://telegram.me/my_bot"
    definitions:
      Empty:
        type: "object"
        title: "Empty Schema"
    

    Actions > 部署API,打个艺名,没关系

    您将获得新创建的端点的链接,例如

    https://<some_id>.execute-api.<region>.amazonaws.com/<stage>
    

    例如

    https://abcdefghij.execute-api.eu-central-1.amazonaws.com/auth
    

你准备好了。现在您可以对您的机器人进行编程,为用户提供服务授权的链接,例如

https://some.service.com/auth?response_type=code&client_id=<your_client_id>&redirect_uri=https://abcdefghij.execute-api.eu-central-1.amazonaws.com

一旦用户关注并登录,他将被发送到

https://abcdefghij.execute-api.eu-central-1.amazonaws.com/auth?code=<auth_code>

将被重定向到

https://telegram.me/my_bot?start=<auth_code>

通常用户会回到他的电报应用程序,在那里他可以按开始按钮。一旦他这样做了,机器人将收到一条消息/start &lt;auth_code&gt;(但代码不会出现在聊天记录中)。您的机器人可以保存此代码并将其用于用户身份验证(获取令牌)。

【讨论】:

以上是关于电报机器人 - OAuth 授权的主要内容,如果未能解决你的问题,请参考以下文章

如何获取不和谐 oauth2 隐式授权的范围值?

电报机器人 - 电报与电报机器人

电报机器人的客户端,有可能吗?

删除电报机器人发送的传出消息(电报,python)

电报机器人可以访问有关用户的哪些信息?

电报机器人可以读取频道消息吗