diff --git a/.gitignore b/.gitignore
index e17b0bc274afa..e107b1e221218 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,6 +69,14 @@ Desktop.ini
# Extra files installed by Composer not needed in the CMS environment
# This should only ignore files like unit testing or READMEs, production
# code must remain to ensure all libraries properly function
+/libraries/vendor/google/recaptcha/examples
+/libraries/vendor/google/recaptcha/tests
+/libraries/vendor/google/recaptcha/.gitignore
+/libraries/vendor/google/recaptcha/.travis.yml
+/libraries/vendor/google/recaptcha/composer.json
+/libraries/vendor/google/recaptcha/CONTRIBUTING.md
+/libraries/vendor/google/recaptcha/phpunit.xml.dist
+/libraries/vendor/google/recaptcha/README.md
/libraries/vendor/ircmaxell/password-compat/test
/libraries/vendor/ircmaxell/password-compat/.travis.yml
/libraries/vendor/ircmaxell/password-compat/composer.json
diff --git a/administrator/components/com_admin/script.php b/administrator/components/com_admin/script.php
index 6cd473f2ebee2..db4d3a3856e0b 100644
--- a/administrator/components/com_admin/script.php
+++ b/administrator/components/com_admin/script.php
@@ -1973,6 +1973,7 @@ public function deleteUnexistingFiles()
* Joomla! 3.8.0 thru 3.9.0
*/
'/libraries/src/Mail/language/phpmailer.lang-joomla.php',
+ '/plugins/captcha/recaptcha/recaptchalib.php',
/*
* Legacy FOF
diff --git a/administrator/components/com_admin/sql/updates/mysql/3.9.0-2018-08-29.sql b/administrator/components/com_admin/sql/updates/mysql/3.9.0-2018-08-29.sql
new file mode 100644
index 0000000000000..9fe0097bbc15a
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/mysql/3.9.0-2018-08-29.sql
@@ -0,0 +1,2 @@
+INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `manifest_cache`, `params`, `custom_data`, `system_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES
+(494, 0, 'plg_captcha_recaptcha_invisible', 'plugin', 'recaptcha_invisible', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"clean"}', '', '', 0, '0000-00-00 00:00:00', 0, 0);
diff --git a/administrator/components/com_admin/sql/updates/postgresql/3.9.0-2018-08-29.sql b/administrator/components/com_admin/sql/updates/postgresql/3.9.0-2018-08-29.sql
new file mode 100644
index 0000000000000..b4421597d895b
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/postgresql/3.9.0-2018-08-29.sql
@@ -0,0 +1,2 @@
+INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
+(494, 0, 'plg_captcha_recaptcha_invisible', 'plugin', 'recaptcha_invisible', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"clean"}', '', '', 0, '1970-01-01 00:00:00', 0, 0);
diff --git a/administrator/components/com_admin/sql/updates/sqlazure/3.9.0-2018-08-29.sql b/administrator/components/com_admin/sql/updates/sqlazure/3.9.0-2018-08-29.sql
new file mode 100644
index 0000000000000..e4499c2335620
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/sqlazure/3.9.0-2018-08-29.sql
@@ -0,0 +1,2 @@
+INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "manifest_cache", "params", "custom_data", "system_data", "checked_out", "checked_out_time", "ordering", "state") VALUES
+(494, 0, 'plg_captcha_recaptcha_invisible', 'plugin', 'recaptcha_invisible', 'captcha', 0, 0, 1, 0, '', '{"public_key":"","private_key":"","theme":"clean"}', '', '', 0, '1900-01-01 00:00:00', 0, 0);
diff --git a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini
index 8a501818501b4..0eff9e05d1438 100644
--- a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini
+++ b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini
@@ -35,6 +35,14 @@ PLG_RECAPTCHA_SIZE_LABEL="Size"
PLG_RECAPTCHA_SIZE_DESC="Select the size for the reCAPTCHA field."
PLG_RECAPTCHA_THEME_NORMAL="Normal"
PLG_RECAPTCHA_THEME_COMPACT="Compact"
+PLG_RECAPTCHA_TABINDEX_LABEL="Tabindex"
+PLG_RECAPTCHA_TABINDEX_DESC="The tabindex of the reCAPTCHA widget"
+PLG_RECAPTCHA_CALLBACK_LABEL="Callback"
+PLG_RECAPTCHA_CALLBACK_DESC="(Optional) JavaScript callback, executed after successful reCAPTCHA response"
+PLG_RECAPTCHA_EXPIRED_CALLBACK_LABEL="Expired callback"
+PLG_RECAPTCHA_EXPIRED_CALLBACK_DESC="(Optional) JavaScript callback, executed when the reCAPTCHA expired"
+PLG_RECAPTCHA_EXPIRED_CALLBACK_LABEL="Error callback"
+PLG_RECAPTCHA_EXPIRED_CALLBACK_DESC="(Optional) JavaScript callback, executed when the reCAPTCHA encounters an error"
; Error messages
PLG_RECAPTCHA_ERROR_NO_PRIVATE_KEY="reCAPTCHA plugin needs a secret key to be set in its parameters. Please contact a site administrator."
diff --git a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.sys.ini b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.sys.ini
index 929448dc46b01..b914a40e586d0 100644
--- a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.sys.ini
+++ b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.sys.ini
@@ -3,5 +3,5 @@
; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
; Note : All ini files need to be saved as UTF-8
-PLG_CAPTCHA_RECAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin uses the reCAPTCHA service to prevent spammers while it helps to digitize books, newspapers and old radio shows. To get a site and secret key for your domain, go to https://www.google.com/recaptcha. To use this for new account registration, go to Options in the User Manager and select Captcha - reCaptcha as the Captcha."
-PLG_CAPTCHA_RECAPTCHA="Captcha - ReCaptcha"
+PLG_CAPTCHA_RECAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin uses the reCAPTCHA service to prevent spammers while it helps to digitize books, newspapers and old radio shows. To get a site and secret key for your domain, go to https://www.google.com/recaptcha. To use this for new account registration, go to Options in the User Manager and select CAPTCHA - reCAPTCHA as the CAPTCHA."
+PLG_CAPTCHA_RECAPTCHA="CAPTCHA - reCAPTCHA"
diff --git a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha_invisible.ini b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha_invisible.ini
new file mode 100644
index 0000000000000..d2a556fab0501
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha_invisible.ini
@@ -0,0 +1,32 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2017 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_CAPTCHA_RECAPTCHA_INVISIBLE_XML_DESCRIPTION="This CAPTCHA plugin uses the Invisible reCAPTCHA service. To get a site and secret key for your domain, go to https://www.google.com/recaptcha."
+PLG_CAPTCHA_RECAPTCHA_INVISIBLE="CAPTCHA - Invisible reCAPTCHA "
+
+; Params
+PLG_RECAPTCHA_INVISIBLE_PUBLIC_KEY_LABEL="Site Key"
+PLG_RECAPTCHA_INVISIBLE_PUBLIC_KEY_DESC="Used in the JavaScript code that is served to your users."
+PLG_RECAPTCHA_INVISIBLE_PRIVATE_KEY_LABEL="Secret Key"
+PLG_RECAPTCHA_INVISIBLE_PRIVATE_KEY_DESC="Used in the communication between your server and the reCAPTCHA server. Be sure to keep it a secret."
+PLG_RECAPTCHA_INVISIBLE_BADGE_LABEL="Badge"
+PLG_RECAPTCHA_INVISIBLE_BADGE_DESC="Positioning of the reCAPTCHA badge."
+PLG_RECAPTCHA_INVISIBLE_BADGE_BOTTOMRIGHT="Bottom right"
+PLG_RECAPTCHA_INVISIBLE_BADGE_BOTTOMLEFT="Bottom left"
+PLG_RECAPTCHA_INVISIBLE_BADGE_INLINE="Inline"
+PLG_RECAPTCHA_INVISIBLE_TABINDEX_LABEL="Tabindex"
+PLG_RECAPTCHA_INVISIBLE_TABINDEX_DESC="The tabindex of the challenge."
+PLG_RECAPTCHA_INVISIBLE_CALLBACK_LABEL="Callback"
+PLG_RECAPTCHA_INVISIBLE_CALLBACK_DESC="(Optional) JavaScript callback, executed after successful reCAPTCHA response"
+PLG_RECAPTCHA_INVISIBLE_EXPIRED_CALLBACK_LABEL="Expired callback"
+PLG_RECAPTCHA_INVISIBLE_EXPIRED_CALLBACK_DESC="(Optional) JavaScript callback, executed when the reCAPTCHA expired"
+PLG_RECAPTCHA_INVISIBLE_ERROR_CALLBACK_LABEL="Error callback"
+PLG_RECAPTCHA_INVISIBLE_ERROR_CALLBACK_DESC="(Optional) JavaScript callback, executed when the reCAPTCHA encounters an error"
+
+; Error messages
+PLG_RECAPTCHA_INVISIBLE_ERROR_NO_PRIVATE_KEY="reCAPTCHA plugin needs a secret key to be set in its parameters. Please contact a site administrator."
+PLG_RECAPTCHA_INVISIBLE_ERROR_NO_PUBLIC_KEY="reCAPTCHA plugin needs a site key to be set in its parameters. Please contact a site administrator."
+PLG_RECAPTCHA_INVISIBLE_ERROR_EMPTY_SOLUTION="Empty solution not allowed."
+PLG_RECAPTCHA_INVISIBLE_ERROR_NO_IP="For security reasons, you must pass the remote IP address to reCAPTCHA."
diff --git a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha_invisible.sys.ini b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha_invisible.sys.ini
new file mode 100644
index 0000000000000..227d2e9d79348
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha_invisible.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2017 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_CAPTCHA_RECAPTCHA_INVISIBLE_XML_DESCRIPTION="This CAPTCHA plugin uses the Invisible reCAPTCHA service. To get a site and secret key for your domain, go to https://www.google.com/recaptcha."
+PLG_CAPTCHA_RECAPTCHA_INVISIBLE="CAPTCHA - Invisible reCAPTCHA "
diff --git a/components/com_users/layouts/joomla/form/renderfield.php b/components/com_users/layouts/joomla/form/renderfield.php
new file mode 100644
index 0000000000000..d86dded0df3ef
--- /dev/null
+++ b/components/com_users/layouts/joomla/form/renderfield.php
@@ -0,0 +1,60 @@
+ 'auto', 'relative' => true));
+}
+
+$class = empty($options['class']) ? '' : ' ' . $options['class'];
+$rel = empty($options['rel']) ? '' : ' ' . $options['rel'];
+
+/**
+ * @TODO:
+ *
+ * As mentioned in #8473 (https://github.com/joomla/joomla-cms/pull/8473), ...
+ * as long as we cannot access the field properties properly, this seems to
+ * be the way to go for now.
+ *
+ * On a side note: Parsing html is seldom a good idea.
+ * https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454
+ */
+preg_match('/class=\"([^\"]+)\"/i', $input, $match);
+
+$required = (strpos($input, 'aria-required="true"') !== false || (!empty($match[1]) && strpos($match[1], 'required') !== false));
+$typeOfSpacer = (strpos($label, 'spacer-lbl') !== false);
+
+?>
+
+