ygramoel
(Johan Cockx)
1
我有一个可用的 Discourse 论坛,用户可以在其中创建本地登录(用户名 + 密码)。
我想在另一个应用程序中重新使用他们的登录名和密码。换句话说:用户将在另一个应用程序中输入他们的用户名和密码,该应用程序应能够检查这是否是论坛的有效登录。
我已阅读 Discourse API 的文档。许多事情都是可能的,包括为给定用户设置用户名和密码,但我没有找到一个 API 端点来验证现有用户名和密码是否与论坛用户列表匹配。
我假设必须存在这样一个 API 端点,因为论坛必须能够通过 Web 界面执行此操作才能登录用户。
用于检查用户名和密码以登录论坛的 API 端点是什么?
3 个赞
更直接地说,您可以使用 DiscourseConnect 作为验证用户的机制,或者在应用程序前面使用 discourse-auth-proxy。
这些是用于验证用户的建议方法,而不是直接处理登录凭据。这也意味着您无需尝试处理双因素认证 (2FA) 的详细信息。
5 个赞
ygramoel
(Johan Cockx)
3
实际上,我的“其他应用程序”是一个桌面应用程序,而不是一个 Web 应用程序。我认为 discourse-auth-proxy 在这种情况下不起作用。
在 DiscourseConnect 页面上,开头的陈述之一是:
许多希望与 Discourse 站点集成的站点希望将所有用户注册保留在一个单独的站点中。在这种设置中,所有登录操作都应外包给该不同的站点。
这与我想要做的完全相反:我想将所有登录操作外包给 Discourse。是否有办法使用 DiscourseConnect 来做到这一点?
1 个赞
是的,绝对可以。
棘手之处在于提供商(Discourse)和使用者(您的应用程序)之间有一个共享的密钥。如果分发您的应用程序,用户将可以访问其中的所有密钥。
在自定义的最小 Web 服务前面放置一个 auth-proxy,该服务向您的应用程序提供一个签名的令牌,这可能会很好地起作用。
我确信还有其他我没想到的方法可以做到这一点。
ygramoel
(Johan Cockx)
5
你是指 API 密钥吗?似乎可以创建一个“细粒度”的 API 密钥,它只能访问特定的 API 端点。如果我采用这种方法,我仍然不清楚需要哪些端点。你知道吗?
是的,一个带有身份验证代理的最小化 Web 服务可能是一个不错的解决方案;我需要做一些实验才能弄清楚。
不完全是——这需要是应用程序的 discourse connect provider secrets 值,并且需要与 enable discourse connect provider 一起设置。
更多信息请参见:Use Discourse as an identity provider (SSO, DiscourseConnect)
1 个赞
renato
(Renato Atilio)
7
1 个赞
ygramoel
(Johan Cockx)
8
如果我理解正确的话,这种方法意味着用户通过浏览器登录。这可以奏效,尽管我希望找到一种方法,可以在不打开浏览器的情况下,在我们的桌面应用程序中输入用户名和密码。
我明白我设想的方法将不支持 TFA,除非我自己实现它,并且它将不支持通过第三方提供商(Google、Facebook、Discord 等)登录。
我不认为这是明确支持的,但我会以用户在网页浏览器中的方式创建会话:
curl 'https://try.discourse.org/session' \
-H 'sec-ch-ua: "Chromium";v="113", "Not-A.Brand";v="24"' \
-H 'Discourse-Present: true' \
-H 'DNT: 1' \
-H 'X-CSRF-Token: …' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'User-Agent: …' \
-H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
-H 'Accept: */*' \
-H 'Referer: https://try.discourse.org/' \
-H 'X-Requested-With: XMLHttpRequest' \
-H 'sec-ch-ua-platform: "Linux"' \
--data-raw 'login=demouser&password=demopassword&second_factor_method=1&timezone=America%2FToronto' \
--compressed
并在应用程序中复制此登录逻辑。
ygramoel
(Johan Cockx)
10
据我目前的理解,在 React Native 示例中使用的方法似乎可以移植到我们的桌面应用程序(该应用程序是用 Python 编写的)。
API 访问点似乎是 <site>/session,它需要用户名、密码和 csrf 令牌。csrf 令牌可以从 <site>/session/csrf 获取。
这非常接近我想要的。我想我会尝试一下,如果对我有效,我会回来报告。
<site>/session API 访问点在任何地方都有记录吗?
1 个赞
在桌面应用中获取所需内容的最佳方式是使用用户 API 密钥。
你确实需要一个 Web 界面(在应用内或通过打开浏览器),但如果你让你的应用成为移动应用所使用的协议的处理程序,你就可以轻松地以这种方式获取令牌,而只有在令牌过期或用户使用其他设备时才需要再次使用浏览器。
我个人的经验是,使用用户 API 密钥比尝试使用会话端点更安全、更简单。 
2 个赞
ygramoel
(Johan Cockx)
12
这是 20 行 Python 代码,其功能与 @renato 引用的 React Native 代码大致相同(除了不支持 Discourse 2.5 - 我不需要那个)。
它运行良好,前提是您使用的是基本的用户名-密码登录。我仍然会研究替代方法,使用 Discourse 实例中配置的 Discourse SSO 登录。
import requests
import json
def discourse_authenticate(url, name, password):
session = requests.Session()
session.headers.update({'X-Requested-With': 'XMLHttpRequest'})
r1 = session.get(url + '/session/csrf')
csrf_token = json.loads(r1.text).get('csrf')
r2 = session.post(url + '/session',
data={
'login': name,
'password': password,
'authenticity_token': csrf_token,
},
)
if r2.status_code != 200:
return None
return json.loads(r2.text)
ygramoel
(Johan Cockx)
13
我尝试应用此方法,但无法使其正常工作。下面是一些(简化的)Python 代码,用于生成指向 .../session/sso_provider 的 URL。当我尝试它时,我收到 Login Error。不知道那是什么意思。
import secrets
import base64
import urllib.parse
import hmac
import hashlib
forum_url = 'https://forum.embeetle.com'
target_url = 'https://embeetle.com/#account'
sso_secret = b'JCLSVcqbAnEPXz2p2xBY'
nonce = secrets.token_urlsafe()
payload = f'nonce={nonce}&return_sso_url={target_url}'
payload_base64 = base64.b64encode(payload.encode('utf-8')).decode()
payload_for_url = urllib.parse.quote(payload_base64)
payload_for_url = 'bm9uY2U9YklKeEU1WWw2OFhjSkJydGlwSU15UTRZeVlMeWd6ZzQyUU9mOFo0SWF5QSZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA%3D%3D'
signature = hmac.new(
sso_secret, payload_for_url.encode('utf-8'), hashlib.sha256
).hexdigest()
print(f'{forum_url}/session/sso_provider?sso={payload_for_url}&sig={signature}')
例如,一次运行可能会生成下面 curl 命令中的 URL:
johan@morla:~/sa> curl 'https://forum.embeetle.com/session/sso_provider?sso=bm9uY2U9YklKeEU1WWw2OFhjSkJydGlwSU15UTRZeVlMeWd6ZzQyUU9mOFo0SWF5QSZyZXR1cm5fc3NvX3VybD1odHRwczovL2VtYmVldGxlLmNvbS8jYWNjb3VudA%3D%3D&sig=a392ebb81b93ba7411290fbd00240921ae053bbb82998830dda994c8a71853da'
Login Errorjohan@morla:~/sa>
作为管理员,请启用“详细的 Discourse Connect 日志记录”,然后尝试一下,接着检查论坛上的 /logs 以查看更详细的错误,例如 https://forum.embeetle.com/logs
您会看到例如:
您需要对 payload 进行签名,而不是对引用的 payload 进行签名,例如:
signature = hmac.new(
sso_secret, payload_base64.encode('utf-8'), hashlib.sha256
).hexdigest()
然后它就能正常工作了!
顺便说一句,您需要立即撤销并更改此密钥,因为任何拥有它的人都可以登录您的应用程序,就像我刚才在测试时所做的那样。
3 个赞
ygramoel
(Johan Cockx)
16
别担心,我正在重定向到的页面是公共页面,只是为了测试。
无论如何我都更改了密钥。
2 个赞
对于这项特定任务,您在开源方面有哪些排名前三的建议?
我正在使用 Nginx,但也许可以使用像 Keycloak 这样更强大的开发工具来管理?
system
(system)
关闭
19
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.