无法通过 API 更新电子邮件 - invalid_access 错误

Hi Guys,

Im getting an error when trying to use the API to update email.
I have looked at the logs and can see the following:

Started PUT “/discussion/users/davetest/preferences/email.json” for xx.xx.xx.xx at 2018-05-11 12:22:11 +0000

Processing by UsersEmailController#update as JSON

Parameters: {“api_key”=>;"[FILTERED]", “api_username”=>;“daveAdmin”, “email”=>;“[new.email@example.com](mailto:new.email@example.com)”, “username”=>;“davetest”}

Can’t verify CSRF token authenticity.

This is a PUT request, but looking at the scopes below, doesnt seem like PUT is supported for the WRITE scope? surely im misunderstanding, so could someone please assist?

I have re-generated the all-user api-key, also created specific user api-keys to use, but same result.

SCOPES = {
read: [:get],
write: [:get, :post, :patch],
message_bus: [[:post, ‘message_bus’]],
push: nil,
notifications: [[:post, ‘message_bus’], [:get, ‘notifications#index’], [:put, ‘notifications#mark_read’]],
session_info: [[:get, ‘session#current’], [:get, ‘users#topic_tracking_state’]]
}

Can you verify the content-type that you are making the API request as? It needs to be

"Content-Type: multipart/form-data;"

If it is not that content type you may see the CSRF token error.

Hi, thanks for the reply.
I actually had tried it both with ‘application/json’ and ‘application/x-www-form-urlencoded’ and neither worked. I have now tried it with what you suggested (via postman) and getting:

“You are not permitted to view the requested resource. The API username or key is invalid.”

I have regenerated the global api key that is used for “all users” and using it with my own username, which is an admin too…

shahid

Here is an example of my postman request maybe you can spot any differences with what you are doing? I’m also using the “all users” key with an admin username.

yes, its the same, im using the Postman API collection supplied by discourse. So using it as suggested. I will try again tonight and see if i get any different results. Will update when ive tried. Thanks for assisting, much appreciated. Do let me know if you have any other idea.

我也遇到了这个问题,我想知道这是否与使用 OAuth 提供商进行登录有关,从而导致此特定页面被阻止?

这很可能不是 OAuth 提供商的问题,因为 API 密钥会绕过它。

你能分享一下你的 API 请求代码吗?

在 Python 中:

import json
import requests
import time

my_token = ''

url_base = '<>'
update_email = url_base + "users/<my_username>/preferences/email.json"

headers = {
    "Content-Type": "multipart/form-data",
    'user-agent': 'my-app/0.0.1',
    'Api-Key': my_token,
    'Api-Username': '<my_username>'
}

data = {
  "email": "<new_email>"
}

response = requests.put(update_email, data=data, headers=headers)

print(response.text)

编辑:设置用户群组等功能的类似代码可以正常工作,因此密钥与用户名的组合(该用户具有管理员权限)是有效的。

编辑 2:根据我在论坛中的其他浏览经验,我猜测这必须直接在数据库中完成(或者更准确地说,通过控制台完成),而这对我们来说是不可能的。

对此还有什么想法吗?我的感觉是,拥有管理员权限的人应该能够设置某人的电子邮件地址。

怎么会呢?我认为现有的 Web UI(它定义了 API)无法实现这一点,因此这是做不到的。

你的意思是,UX/API 应当允许将用户的电子邮件地址设置为你想要的任何内容。(并非你认为当前已具备此功能。)

你可以通过编辑其档案并输入新地址来发起更改(通过 UX,我推测 API 也可),但只有当用户点击其电子邮件中的链接后,更改才会生效。这是否足够?如果不够,你需要通过控制台或插件来完成操作。

没错。

每当我在 UX 中输入内容以编辑电子邮件时(我仅能通过直接 URL 访问,即 https://<discourse>/u/<username>/preferences/email,用户个人资料中并无相关链接),点击“更改”后就会弹出提示,显示我无法执行此操作:

而且这是在我的管理员账户上进行的。我没有收到任何电子邮件。

现在也遇到了这个问题…

@pfaffman:你提到可以在个人资料中更改电子邮件地址,但这需要设置 email editable,对吧?

我了解到,除非允许用户自行更改电子邮件地址,否则管理员或管理 API 调用无法发起电子邮件地址的更改,是这样吗?我完全可以接受发送确认邮件,并且需要用户授权才能完成更改。

我的使用场景是:用户将通过某个其他应用程序的 API 进行管理。因此,我不希望他们仅在 Discourse 中自行更改电子邮件地址。

您能否实现单点登录,并将您的其他应用作为登录源?

有一个特定的 SSO 设置 sso overrides email 可以实现您想要达到的效果。如果您已设置好 SSO,就可以使用 sync_sso 端点并传入新的电子邮件地址。

谢谢你 @blake,这很有挑战性,但也很有趣 :wink:

我得把密码从 Discourse 导入到身份中心……天哪。

我用一个三步流程帮助了我的原始场景:启用可编辑邮箱、发起邮箱地址变更、禁用可编辑邮箱。这看起来有点过于复杂,但确实有效。

我会再考虑一下单点登录(SSO)的场景。