How to force users link phone number when they using Discourse?

I’m the admin of a Discourse forum which mainly for China Mainland users, so our the governing law(网络安全法, 互联网跟帖评论服务管理规定 and 互联网论坛社区服务管理规定) required we must use real-name system. That means we must force users link phone number.
I tried to use Alipay’s API to get user’s phone number, but only their Mini Apps / Programs’ developers can get users’ phone number.
The main problem is we must verify users filed phone number is their real phone number.


Can you use QQ’s implementation of OAuth2.0?简介


OAuth 2.0 just can allow users Sign In with their QQ account, it can’t get user’s real phone number.

You can create a custom user field asking for a registering user’s phone number and make the field required.

1 Like

The emphasis is on verify.


I think the Facebook Account Kit is a good option for this. I don’t think there’s a discourse plugin for it tough.

1 Like

Thanks, I’ll try it later.

  1. Is there any good video tutorial for this? Can you guide me to one?
  2. For this to use, do I need to install oAuth 2 plugin?

I haven’t implemented it for discourse, so I don’t know exactly how to create a plugin for that, but in my implementation:

1) I already had an application in the Facebook for developers site (if you don’t have, just create one) and then just added the Account Kit product there.

2) Then I loaded the Account Kit script in the front-end:

<script src=""></script>

	AccountKit_OnInteractive = function() {
			appId: '{{ FACEBOOK_APP_ID }}', 
			state: '{{ CSRF_TOKEN }}', 
			version: 'v1.1',
			fbAppEventsEnabled: true,

(in a first moment, when developing, you can put anything in the csrf token to make the flow work first, then you may return here and handle the csrf token)

3) In a button press event from the user I call the javascript SDK:

      {countryCode: countryCode, phoneNumber: phoneNumber}, // will use default values if not specified

4) The loginCallback function calls my backend api in case of success, or shows an error otherwise:

function loginCallback(response) {
	if (response.status === "PARTIALLY_AUTHENTICATED") {
		var code = response.code;
		var csrf = response.state;
		callbackSuccess(code, csrf);
	else if (response.status === "NOT_AUTHENTICATED") {
	else if (response.status === "BAD_PARAMS") {

5) Then in the backend I call the Account Kit endpoint passing the code to retrieve the access token, and then I call passing the access token to retrieve the phone number (phone.number), but first I make sure that it was called using my application Id (created in the 1st step).

Click to see the java code that I use (for reference)
public static String retrievePhoneData(String code) throws HTTPException, NotAllowedException {
	String appAccessToken = Arrays.asList(
	Map<String, String> params = new HashMap<>();
	params.put("grant_type", "authorization_code");
	params.put("code", code);
	params.put("access_token", appAccessToken);
	SimpleHttpClientRequest requestToken = new SimpleHttpClientRequest();
	SimpleHttpClientResponse responseToken = URIUtils.getResponseObjectFromRequest(requestToken);
	int statusCodeToken = responseToken.getStatusCode();
	if ((statusCodeToken < 200) || (statusCodeToken > 299)) {
		throw new HTTPException(requestToken, responseToken);
	String responseStrToken = responseToken.getResponse();
	Mapper mapperToken = StringUtil.getMapperFromJSON(responseStrToken);
	String accessToken = mapperToken.getAsString("access_token");
	SimpleHttpClientRequest requestMain = new SimpleHttpClientRequest();
	requestMain.setUrl(ME_ENDPOINT_BASE_URL + "?access_token=" + accessToken);
	SimpleHttpClientResponse responseMain = URIUtils.getResponseObjectFromRequest(requestMain);
	int statusCodeMain = responseMain.getStatusCode();
	if ((statusCodeMain < 200) || (statusCodeMain > 299)) {
		throw new HTTPException(requestMain, responseMain);
	String responseStrMain = responseMain.getResponse();
	Mapper mapperMain = StringUtil.getMapperFromJSON(responseStrMain);
	String appId = mapperMain.getAsString("");
	if (!FACEBOOK_APP_ID.equals(appId)) {
		throw new NotAllowedException();
	String phoneNumber = mapperMain.getAsString("phone.number");
	return phoneNumber;

I haven’t seen any videos, just followed the steps that is explained here:

(the main change was that it’s in nodejs, and I used java, but it was pretty straightforward, after all it’s just api calls in the backend)

If you use the javascript flow (including the script that loads the sdk and so on), I don’t think so. But like I said, I haven’t implemented it in a Discourse site, so I don’t know the exact requirements to create a plugin that supports Account Kit.

1 Like

Problem is in the very first step.
When, after creating our app in the FB developer console, we have to choose components/functions for our app, where we are supposed to find FB Account Kit, there FB Account Kit is no longer there to be found.

Even clicking on + button besides ‘products’ link, takes us to ‘Dashboard’ screen (as shown in the SS).

I entered my app now and saw that behaviour. To me it seems like a bug on their end. Or you can add the products in another, well hidden place :S

1 Like

I can’t find any (option/place/work around)

That was just a joke (because I tried to find in every place and also couldn’t find, so if there is such a place, it must be very well hidden).

I advise to create a question in the Facebook Developers group:

To make it easier for you, I already created a post there (just waiting now).

1 Like

While they don’t reply, try to see if you can access:


It seems that people created an issue yesterday about it, and it is really a bug:

1 Like


Love you.
(not that problems are not there further ahead. But this was a grand step)