Page MenuHomePhabricator

"Error contacting the Parsoid/RESTBase server (HTTP 403)" when trying to edit an existing page with VisualEditor
Closed, InvalidPublic

Description

Whenever I try to edit an exitsing page with VisualEditor I get the error mentioned in the title: "Error contacting the Parsoid/RESTBase server (HTTP 403)".
The wiki has editing restricted for unregistered users, but pages' content is public. MediaWiki's version is 1.35.

The 403 error arose after solving a 404 error by modifying the .htaccess file for the wiki.

I tried the 2 following versions of code for the .htaccess and they both lead to a 403 error:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ %{DOCUMENT_ROOT}/index.php
RewriteRule rest.php/ /rest.php?%{QUERY_STRING} [L]

and

RewriteEngine On
RewriteCond %{REQUEST_URI} !^(static)
RewriteCond %{HTTP_USER_AGENT} !^(VisualEditor)
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteRule ^(.*)$ %{DOCUMENT_ROOT}/index.php [L]

Event Timeline

I'm just gonna mention this here for reference: T263928#6518831

OK. I found it.

I had set

$wgRevokePermissions['*']['writeapi'] = true;

for security reasons.

Is there a way to enable it only for registered users?

$wgGroupPermissions['*']['writeapi'] = true;

Is there a group I can use instead of " * "?

AFAIK, VisualEditor is not part of any group, so you need to find a way to enable edit and writeapi for * - but only if the requests come from VisualEditor. The solution described in T263928#6518831 does this, but since you are using Cloudflare and every request comes from a different IP, even if it is sent by the server itself, this doesn't work for you.

You could try comparing for the User Agent instead of the IP - VisualEditor uses the user agent VisualEditor-MediaWiki/1.35.0, afaik. However, keep in mind that this would open a security risk - everyone with that user agent could edit your wiki, and user agents can be easily changed/falsified.

Another thing that might work: set $wgVisualEditorFullRestbaseURL = https://DOMAIN_THAT_LEADS_TO_YOUR_WIKI_BUT_DOESNT_USE_CLOUDFLARE.com/rest.php

That way VisualEditor would bypass Cloudflare and you could use the IP solution with your servers IP address.

AFAIK, VisualEditor is not part of any group, so you need to find a way to enable edit and writeapi for * - but only if the requests come from VisualEditor. The solution described in T263928#6518831 does this, but since you are using Cloudflare and every request comes from a different IP, even if it is sent by the server itself, this doesn't work for you.

You could try comparing for the User Agent instead of the IP - VisualEditor uses the user agent VisualEditor-MediaWiki/1.35.0, afaik. However, keep in mind that this would open a security risk - everyone with that user agent could edit your wiki, and user agents can be easily changed/falsified.

If edit is disabled in order to prevent unregistered users from editing the wiki, but at the same time unregistered users can use the writeapi to make modifications, there is already a "security risk", right?

I could call this a bug. VisualEditor can not work if a CDN is used and the wiki is set to semi-private mode.

Another thing that might work: set $wgVisualEditorFullRestbaseURL = https://DOMAIN_THAT_LEADS_TO_YOUR_WIKI_BUT_DOESNT_USE_CLOUDFLARE.com/rest.php

That way VisualEditor would bypass Cloudflare and you could use the IP solution with your servers IP address.

DNS is handled by Cloudflare, so I'm not sure if such a domain even exists.

Well, you could have www.mywiki.com use Cloudflare DNS and www.mywikiwithoutcloudflare.com use your hosting providers DNS.

Well, you could have www.mywiki.com use Cloudflare DNS and www.mywikiwithoutcloudflare.com use your hosting providers DNS.

Basically, having a second domain name...

Could a user group get created to serve this purpose?

OK. I found it.

I had set

$wgRevokePermissions['*']['writeapi'] = true;

for security reasons.

Is there a way to enable it only for registered users?

$wgGroupPermissions['*']['writeapi'] = true;

Is there a group I can use instead of " * "?

You can use the 'user' group to assign permissions to logged in users.

AFAIK, VisualEditor is not part of any group, so you need to find a way to enable edit and writeapi for * - but only if the requests come from VisualEditor. The solution described in T263928#6518831 does this, but since you are using Cloudflare and every request comes from a different IP, even if it is sent by the server itself, this doesn't work for you.

You could try comparing for the User Agent instead of the IP - VisualEditor uses the user agent VisualEditor-MediaWiki/1.35.0, afaik. However, keep in mind that this would open a security risk - everyone with that user agent could edit your wiki, and user agents can be easily changed/falsified.

If edit is disabled in order to prevent unregistered users from editing the wiki, but at the same time unregistered users can use the writeapi to make modifications, there is already a "security risk", right?

No, all of the the APIs performs all of the same permissions checks as the normal interface. You don't need to do anything with the 'writeapi' right (unless you have some custom extensions that don't check permissions correctly in their APIs).

I understand that it's a defense-in-depth thing, but IMO removing the 'writeapi' right is more likely to cause weird issues than to save you from a security problem.

You can use the 'user' group to assign permissions to logged in users.

I have already tried giving the appropriate permissions to the "user" group:

$wgRevokePermissions['*']['writeapi'] = true;
$wgGroupPermissions['user']['writeapi'] = true;

I also tried:

$wgRevokePermissions['*']['writeapi'] = true;
$wgGroupPermissions['*']['writeapi'] = true;

Both versions give a 403 error... I guess this approach does not work and it turns out that it's not the selected group of $wgGroupPermissions that doesn't solve the problem in the first version of the code.

No, all of the the APIs performs all of the same permissions checks as the normal interface. You don't need to do anything with the 'writeapi' right (unless you have some custom extensions that don't check permissions correctly in their APIs).

I understand that it's a defense-in-depth thing, but IMO removing the 'writeapi' right is more likely to cause weird issues than to save you from a security problem.

What does this mean? Does setting $wgGroupPermissions['*']['edit'] = false; except of preventing unregistered users to edit articles, also revokes the ability for them to use the writeapi?

You can use the 'user' group to assign permissions to logged in users.

I have already tried giving the appropriate permissions to the "user" group:

$wgRevokePermissions['*']['writeapi'] = true;
$wgGroupPermissions['user']['writeapi'] = true;

I also tried:

$wgRevokePermissions['*']['writeapi'] = true;
$wgGroupPermissions['*']['writeapi'] = true;

Both versions give a 403 error... I guess this approach does not work and it turns out that it's not the selected group of $wgGroupPermissions that doesn't solve the problem in the first version of the code.

Sorry, I didn't read your comment closely enough.

I don't think you want to use $wgRevokePermissions here. Per the docs: https://www.mediawiki.org/wiki/Manual:$wgRevokePermissions "Revoking a right with $wgRevokePermissions takes precedence over granting it with $wgGroupPermissions. If the right is revoked for even one of the user's groups, they will not have it, regardless of whether it's explicitly permitted by other groups."

(As I understand it, the purpose of $wgRevokePermissions is to allow "soft-banning" users, by adding them to a group that has all or most permissions revoked.)

Assuming you want to allow editing for logged in users, but not logged out users, I think you want this instead:

$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['user']['edit'] = true;

And maybe also this, but as I wrote earlier, I wouldn't recommend it:

$wgGroupPermissions['*']['writeapi'] = false;
$wgGroupPermissions['user']['writeapi'] = true;

No, all of the the APIs performs all of the same permissions checks as the normal interface. You don't need to do anything with the 'writeapi' right (unless you have some custom extensions that don't check permissions correctly in their APIs).

I understand that it's a defense-in-depth thing, but IMO removing the 'writeapi' right is more likely to cause weird issues than to save you from a security problem.

What does this mean? Does setting $wgGroupPermissions['*']['edit'] = false; except of preventing unregistered users to edit articles, also revokes the ability for them to use the writeapi?

Setting that will prevent unregistered users from using any APIs that can be used to edit articles, including action=edit API and action=visualeditoredit. It doesn't affect 'writeapi', so they can still use other write APIs, for example action=purge or action=createaccount.

Sorry, I didn't read your comment closely enough.

I don't think you want to use $wgRevokePermissions here. Per the docs: https://www.mediawiki.org/wiki/Manual:$wgRevokePermissions "Revoking a right with $wgRevokePermissions takes precedence over granting it with $wgGroupPermissions. If the right is revoked for even one of the user's groups, they will not have it, regardless of whether it's explicitly permitted by other groups."

(As I understand it, the purpose of $wgRevokePermissions is to allow "soft-banning" users, by adding them to a group that has all or most permissions revoked.)

Assuming you want to allow editing for logged in users, but not logged out users, I think you want this instead:

$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['user']['edit'] = true;

Well, during MediaWiki's installation if the choice to allow only registered users to edit pages is made, then automatically the installer sets:

$wgGroupPermissions['*']['edit'] = false;

That's the only line of code used by the installer and it achieves the desired result, without using the second line you suggested. That raises the question to which groups ' * ' actually corresponds to.

And maybe also this, but as I wrote earlier, I wouldn't recommend it:

$wgGroupPermissions['*']['writeapi'] = false;
$wgGroupPermissions['user']['writeapi'] = true;

If I use these lines instead of setting the $wgRevokePermissions variable to true for the writeapi, I still get the 403 error. I guess the explanation is the one suggested by @TheConen here: T265043#6530807
Probably VisualEditor is not part of any groups and that's why I asked if there is a way to assign a group to VisualEditor. If that's possible then I can create a new group that will be specific to VisualEditor and use it in order to set permissions according to my wishes.

Setting that will prevent unregistered users from using any APIs that can be used to edit articles, including action=edit API and action=visualeditoredit. It doesn't affect 'writeapi', so they can still use other write APIs, for example action=purge or action=createaccount.

If I'm not mistaken keeping the writeapi enabled for everyone, gives the ability to unregistered users to perform actions like deleting, moving or rolling back pages and also it makes possible for them to upload files etc. I'm not so sure that setting only $wgGroupPermissions['*']['edit'] = false; is an adequate security measure against unregistered malicious users.

Well, during MediaWiki's installation if the choice to allow only registered users to edit pages is made, then automatically the installer sets:

$wgGroupPermissions['*']['edit'] = false;

That's the only line of code used by the installer and it achieves the desired result, without using the second line you suggested. That raises the question to which groups ' * ' actually corresponds to.

I don't think that raises any such questions. '*' corresponds to all users, logged in or logged out.

I suggested the second line for clarity, assuming you had some crazy permissions settings already. If it was confusing, then please forget I ever wrote it there.

If I use these lines instead of setting the $wgRevokePermissions variable to true for the writeapi, I still get the 403 error. I guess the explanation is the one suggested by @TheConen here: T265043#6530807
Probably VisualEditor is not part of any groups and that's why I asked if there is a way to assign a group to VisualEditor. If that's possible then I can create a new group that will be specific to VisualEditor and use it in order to set permissions according to my wishes.

VisualEditor effectively makes requests as a logged out user, unless you enable "cookie forwarding" as described here: https://www.mediawiki.org/wiki/Extension:VisualEditor#Linking_with_Parsoid_in_private_wikis – in which case it will make requests as the user you are logged in as.

I'm sorry I didn't mention that first, I forgot that it's needed, or maybe I assumed you had already done it.

You can't and don't need to assign a group to VisualEditor, as far as I know.

Setting that will prevent unregistered users from using any APIs that can be used to edit articles, including action=edit API and action=visualeditoredit. It doesn't affect 'writeapi', so they can still use other write APIs, for example action=purge or action=createaccount.

If I'm not mistaken keeping the writeapi enabled for everyone, gives the ability to unregistered users to perform actions like deleting, moving or rolling back pages and also it makes possible for them to upload files etc. I'm not so sure that setting only $wgGroupPermissions['*']['edit'] = false; is an adequate security measure against unregistered malicious users.

No, like I have already said, it does not give them the ability to do anything they can't do via the web interface. If you configured $wgGroupPermissions to allow unregistered users to delete pages or whatever, then they can delete pages either via the interface or via the API; otherwise, they can not delete pages, neither via the interface nor via the API. If you're not sure how it works, then try visiting Special:ApiSandbox on your wiki (while logged out) and performing a deletion or whatever using the API, you'll get an appropriate error.

I don't think that raises any such questions. '*' corresponds to all users, logged in or logged out.

I suggested the second line for clarity, assuming you had some crazy permissions settings already. If it was confusing, then please forget I ever wrote it there.

Well, I had the impression that '*' referred to all user groups, which probably isn't the case. In other words, I thought that all the other groups were inheriting the '*' setting.

Probably, that's not true. In combination with $wgGroupPermissions behavior:
Those permissions, which are granted with $wgGroupPermissions, are always cumulative. If a user is member of different groups, then the user will get a right if it is granted to at least one of these groups even if it is not granted to their other groups. In other words, If one of the user's groups has a right, then it is not possible to take the right away using $wgGroupPermissions. Instead use $wgRevokePermissions to revoke permissions.

I think I see why using only that single line:

$wgGroupPermissions['*']['edit'] = false;

registered users still have the edit permission.

VisualEditor effectively makes requests as a logged out user, unless you enable "cookie forwarding" as described here: https://www.mediawiki.org/wiki/Extension:VisualEditor#Linking_with_Parsoid_in_private_wikis – in which case it will make requests as the user you are logged in as.

I'm sorry I didn't mention that first, I forgot that it's needed, or maybe I assumed you had already done it.

You can't and don't need to assign a group to VisualEditor, as far as I know.

I have already tried what you suggested:

$wgVirtualRestConfig['modules']['parsoid']['forwardCookies'] = true;

With that line of code instead of the 403 error I get a 404 error.

I see 3 problems with it:

  1. I use HTTPS with Cloudflare while there is a warning that this setting should be used only over HTTP.
  2. This settings should be used only for private wikis: If the wiki is not private (i.e. $wgGroupPermissions['*']['read'] is true) this configuration variable will be ignored. In my case I have set only the edit permission to true and I have not made any changes for the read permission.
  3. In the same section I can also read these instructions: If you do set any property in $wgVirtualRestConfig['modules']['parsoid'] you will have to manually install Parsoid or VisualEditor will not work!

Probably point 3 is what gives me the 404 error, because if that's true VisualEditor can not work out of the box any more.

No, like I have already said, it does not give them the ability to do anything they can't do via the web interface. If you configured $wgGroupPermissions to allow unregistered users to delete pages or whatever, then they can delete pages either via the interface or via the API; otherwise, they can not delete pages, neither via the interface nor via the API. If you're not sure how it works, then try visiting Special:ApiSandbox on your wiki (while logged out) and performing a deletion or whatever using the API, you'll get an appropriate error.

Well, I'm afraid you are wrong.

With the following code I tried the API Sandbox for page deletion (action=delete) as an unregistered user:

$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['*']['writeapi'] = false;
$wgGroupPermissions['user']['writeapi'] = false;

and I got

{
    "error": {
        "code": "writeapidenied",
        "info": "You're not allowed to edit this wiki through the API.",
        "*": "See https://driverspedia.org/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes."
    }
}

as expected. Also there is no link for page deletion for unregistered users on the web interface.

Then I proceeded to comment the 2 lines regarding the writeapi. With the lines commented - again as an unregistered user - I get:

{
    "error": {
        "code": "missingparam",
        "info": "One of the parameters \"title\" and \"pageid\" is required.",
        "*": "See https://driverspedia.org/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes."
    }
}

which means that if I had defined these parameters (I didn't, because I don't want to actually delete any pages and I'm not sure if the API sandbox actually executes the requests) the unregistered user could proceed with the page deletion. Still there in no link for page deletion on the website, like it appears when I'm logged in, but it turns out the deletion could be completed through the API!

which means that if I had defined these parameters (I didn't, because I don't want to actually delete any pages and I'm not sure if the API sandbox actually executes the requests) the unregistered user could proceed with the page deletion. Still there in no link for page deletion on the website, like it appears when I'm logged in, but it turns out the deletion could be completed through the API!

No, it does not, you would have gotten an error if you submitted a valid request. Anyway, I don't care to argue with you about it.

which means that if I had defined these parameters (I didn't, because I don't want to actually delete any pages and I'm not sure if the API sandbox actually executes the requests) the unregistered user could proceed with the page deletion. Still there in no link for page deletion on the website, like it appears when I'm logged in, but it turns out the deletion could be completed through the API!

That is a false conclusion. The fact that the API tells you that you made an invalid request does not mean that a valid request would be allowed to execute. The API cannot check an invalid request for permissions (e.g. to delete a page) since it simply doesn't know what you want to do.

which means that if I had defined these parameters (I didn't, because I don't want to actually delete any pages and I'm not sure if the API sandbox actually executes the requests) the unregistered user could proceed with the page deletion. Still there in no link for page deletion on the website, like it appears when I'm logged in, but it turns out the deletion could be completed through the API!

No, it does not, you would have gotten an error if you submitted a valid request. Anyway, I don't care to argue with you about it.

There is no need to argue. Access the sandbox and try it yourself: https://driverspedia.org/Special:ApiSandbox
I still have the 2 lines of code regarding the writeapi commented and only this line is active:

$wgGroupPermissions['*']['edit'] = false;

which means that if I had defined these parameters (I didn't, because I don't want to actually delete any pages and I'm not sure if the API sandbox actually executes the requests) the unregistered user could proceed with the page deletion. Still there in no link for page deletion on the website, like it appears when I'm logged in, but it turns out the deletion could be completed through the API!

That is a false conclusion. The fact that the API tells you that you made an invalid request does not mean that a valid request would be allowed to execute. The API cannot check an invalid request for permissions (e.g. to delete a page) since it simply doesn't know what you want to do.

Does the API sandbox actually execute the requests or not? If it does not make any real changes I can proceed with completing the parameters and then I will see what the outcome would be. I guess even if the sandbox deletes a page the change can be rolled back though, right?

Yes, it does, as is explained on https://www.mediawiki.org/wiki/Help:ApiSandbox

Just create a test page and try to delete that one with the API

Yes, it does, as is explained on https://www.mediawiki.org/wiki/Help:ApiSandbox

Just create a test page and try to delete that one with the API

Indeed: Note that, despite it being called a sandbox, any write requests performed with this extension will modify the wiki.
I guess that these changes are still reversible, but anyway I will create a test page and report the results.

@TheConen

You were right that my initial assumption was wrong. Now I get:

{
    "error": {
        "code": "permissiondenied",
        "info": "The action you have requested is limited to users in the group: [[Driverspedia:Administrators|Administrators]].",
        "*": "See https://driverspedia.org/api.php for API usage. Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes."
    }
}

The delete right is given by default only to administrators.

I will check the user groups' rights and also the writeapi's write modules and if I see any write action that is given also to anonymous users then I will test it using the API sandbox.

If there isn't such an action I will not disable the writeapi for unregistered users and that will also solve the 403 error.

It will fix one of the two reasons you're getting the 403 error - VisualEditor not only requires the writeapi right, but also the edit right. AFAIK, you still have editing disabled for unregistered users.

It will fix one of the two reasons you're getting the 403 error - VisualEditor not only requires the writeapi right, but also the edit right. AFAIK, you still have editing disabled for unregistered users.

At least as an administrator (which is a group that has the edit right), when I comment the lines about the writeapi, the VisualEditor loads fine. If there aren't any other rights that would create a problem I guess that there wouldn't be a problem for the user group too.

Also my initial confusion about the actions of unregistered users arose from the fact that by default * users have the writeapi right. I guess that doesn't mean automatically that they have access to every action of the writeapi, right?

It will fix one of the two reasons you're getting the 403 error - VisualEditor not only requires the writeapi right, but also the edit right. AFAIK, you still have editing disabled for unregistered users.

OK. I created a test user to make sure that everything works for the user group too. With the lines regarding the writeapi commented the VisualEditor loads fine for that group too.

Just a last question to make things clear for me. What does exactly the writeapi right do? Which actions does it permit for the unregistered users?

Sorry, I forgot about this thread.

Just a last question to make things clear for me. What does exactly the writeapi right do? Which actions does it permit for the unregistered users?

I think it's not documented properly anywhere, or at least I couldn't find it. It is mentioned on https://www.mediawiki.org/wiki/Manual:User_rights and https://www.mediawiki.org/wiki/API:Restricting_API_usage, but neither page explains exactly what it allows.

There is a list of "Write Modules" on https://www.mediawiki.org/wiki/API:Changing_wiki_content, which is probably the best you can get, but I see from your previous comments that you already found it.

Also my initial confusion about the actions of unregistered users arose from the fact that by default * users have the writeapi right. I guess that doesn't mean automatically that they have access to every action of the writeapi, right?

Yes, they need to have both 'writeapi' and whichever right the specific action requires (e.g. 'edit').

matmarex claimed this task.

So, to summarize – to use VisualEditor, you'll need to grant everyone who should be able to edit the 'writeapi' right. There is no way around this, but it should be safe to do even on private wikis. I hope you found a configuration that you're happy with.

I documented this on https://www.mediawiki.org/wiki/Extension:VisualEditor#Troubleshooting (https://www.mediawiki.org/w/index.php?title=Extension:VisualEditor&diff=4285674&oldid=4285160).

@matmarex

My confusion about the writeapi right was cleared by starting this topic: https://www.mediawiki.org/wiki/Topic:Vw6wwobg89cw970u

Thanks for your input!

(also posted to extension talk page)

So, to summarize – to use VisualEditor, you'll need to grant everyone who should be able to edit the 'writeapi' right. There is no way around this, but it should be safe to do even on private wikis. I hope you found a configuration that you're happy with.

I documented this on https://www.mediawiki.org/wiki/Extension:VisualEditor#Troubleshooting (https://www.mediawiki.org/w/index.php?title=Extension:VisualEditor&diff=4285674&oldid=4285160).

i have done this, and i still cannot save edits with Visual Editor. I can view and edit pages, but i get error on clicking Save:

"Error contacting the Parsoid/RESTBase server (HTTP 403)"

Here's my config:

// VISUAL EDITOR
wfLoadExtension( 'VisualEditor' );
$wgGroupPermissions['*']['writeapi'] = true;
$wgRevokePermissions['*']['writeapi'] = false;
$wgGroupPermissions['*']['read'] = true;
$wgGroupPermissions['*']['edit'] = true;

Here are some other parts of my LocalSettings.php which might be relevant. I shared relevant links. Protection is rather complicated, and i struggled with it at the time i set up this wiki (3 yrs ago):

# SUPPOSED TO REMOVE THE "PROTECT" TAB FOR THEIR NAMESPACES
# https://www.mediawiki.org/wiki/Manual:$wgNamespaceProtection
$wgNamespaceProtection[NS_PORTAL] = 
$wgNamespaceProtection['NS_FORM'] = 	
$wgNamespaceProtection[NS_PROJECT] =
$wgNamespaceProtection[NS_HELP] =
$wgNamespaceProtection[NS_CATEGORY] =array( 'editprotected' );
/* https://www.mediawiki.org/wiki/Manual:User_rights#List_of_permissions
The above statement means: Users and groups who have 'editprotected' permission shall have write-access to the Form namespace. editprotected makes sense here, cuz:
- Only admins have editprotected by default, and i want to target admins.
- "wgNamespaceProtection" is all about, well, editing something that's protected :)
- saves me the trouble of creating a new protection and applying to admins.
https://www.mediawiki.org/w/index.php?title=Topic:Ua5fqyzhagx3iso8&action=history
https://www.mediawiki.org/w/index.php?title=Topic:Ua5fqyzhagx3iso8&topic_showPostId=ua7het8puwsmpt4y#flow-post-ua7het8puwsmpt4y
*/


## FLOW & ECHO
wfLoadExtension( 'Flow' );
wfLoadExtension( 'Echo' );
$wgNamespaceContentModels[NS_TALK] = 'flow-board';		# MAIN TALK  https://www.mediawiki.org/wiki/Extension_default_namespaces#MediaWiki_Core
$wgNamespaceContentModels[NS_PROJECT_TALK] = 'flow-board';		
$wgNamespaceContentModels[NS_HELP_TALK] = 'flow-board';		
$wgNamespaceContentModels[NS_CATEGORY_TALK] = 'flow-board';		
$wgNamespaceContentModels[107] = 'flow-board';
$wgNamespaceContentModels[NS_DRAFT_TALK] = 'flow-board';		
$wgNamespaceContentModels[NS_PORTAL_TALK] = 'flow-board';	


## APPROVED REVS
wfLoadExtension( 'ApprovedRevs' );
$egApprovedRevsAutomaticApprovals = true;		# allow auto-approval of admin edits. 
$egApprovedRevsEnabledNamespaces[] = NS_DRAFT;	
$egApprovedRevsSelfOwnedNamespaces[] = NS_USER ;


## MODERATION 
wfLoadExtension( 'Moderation' );
$wgModerationTimeToOverrideRejection = 31556952;
$wgModerationNotificationEnable = true;
$wgGroupPermissions['sysop']['moderation'] = true; # Allow sysops to use Special:Moderation
$wgGroupPermissions['sysop']['skip-moderation'] = true; # Allow sysops to skip moderation
$wgGroupPermissions['automoderated']['skip-move-moderation'] = false;
$wgGroupPermissions['sysop']['skip-move-moderation'] = true;
$wgAutoConfirmCount = 10;	
$wgGroupPermissions['autoconfirmed']['skip-move-moderation'] = false;

$wgWhitelistReadRegexp = 
	['/Portal:/', '/ /', '/Draft:/', '/Template:/', '/Category:/',  '/Topic:/', 
	'/MediaWiki:Common.css/', '/MediaWiki:TopicTags.css/', '/Special:AllPages/', '/Special:RecentChanges/', '/Special:RequestAccount/'
	];

still cannot save edits with Visual Editor. I can view and edit pages, but i get error on clicking Save:

"Error contacting the Parsoid/RESTBase server (HTTP 403)"

This was apparently caused by Softaculous. VisualEditor works on a manual installation of MW 1.35.

I'd throw few more details, which I think can be helpful.
Few users, including myself experienced this issue on Namecheap hosting.
@Rehman figured that was related to their Apache mod_security rules. (see here https://www.mediawiki.org/wiki/Topic:Vv9zl5e9gre77rgq)
I've faced that issue and asked Namecheap tech support to provide more details. Apparently our POST request mosses Content-Length Header, and that's what triggers their mod_security rules.

[client 162.0.229.122] ModSecurity: Access denied with code 403 (phase 1). Match of "endsWith /wp-cron.php" against "REQUEST_FILENAME" required.
[msg "COMODO WAF: HTTP/1.1 POST request missing Content-Length Header||wiki.cyhub.am|F|2"]
[hostname "wiki.cyhub.am"]
[uri "/rest.php/wiki.cyhub.am/v3/transform/html/to/wikitext/%d4%b3%d5%ac%d5%ad%d5%a1%d5%be%d5%b8%d6%80_%d5%a7%d5%bb/7"]

@Xelgen i'm on namecheap shared hosting. As mentioned, i only experienced this issue on a Softaculous install. When i created a manual install, this error went away.

Btw, to transfer old contents from the Softaculous install to the manual install, i used the same db. I copied LocalSettings.php from the Softaculous install into the manual install (keeping it pointing at the Softaculous db) , rsync'd from the Softaculous extensions dir into the manual extensions dir, ran /maintenance/rebuildall.php, and voila, the manual install loaded all the old content and extensions no problem. Except, now the visual editor worked.

I've been struggling with the "Error contacting the Parsoid/RESTBase server (HTTP 403)" error for months (currently on 1.37.1). We disabled ModSecurity and still the issue persisted. And today I finally found the solution. It is probably quite unique to our setup, but maybe this will help someone someday. I realised that we had a Wordpress site at our root domain with Wordfence security enabled in the .user.ini file doing this (stars replace true folder names):

; Wordfence WAF
auto_prepend_file = '/***/***/***/wordfence-waf.php'
; END Wordfence WAF

So in the mediawiki .htaccess I added this to switch this off for the mediawiki subdomain:

#Disable Wordfence from higher level domain
 php_value auto_prepend_file none

And the problem disappeared. I did not expect the Wordfence at the root domain to affect the subdomains but it clearly did.