diff --git a/src/Umbraco.Core/Security/MachineKeyGenerator.cs b/src/Umbraco.Core/Security/MachineKeyGenerator.cs
new file mode 100644
index 0000000000..9dd06f44bd
--- /dev/null
+++ b/src/Umbraco.Core/Security/MachineKeyGenerator.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Umbraco.Core.Security
+{
+ ///
+ /// Used to generate a machine key
+ ///
+ internal class MachineKeyGenerator
+ {
+ ///
+ /// Generates the string to be stored in the web.config
+ ///
+ ///
+ ///
+ /// Machine key details are here: https://msdn.microsoft.com/en-us/library/vstudio/w8h3skw9%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
+ ///
+ public string GenerateConfigurationBlock()
+ {
+ var c = @"";
+
+ var Xxx = 3;
+
+ return string.Format(c, GenerateAESDecryptionKey(), GenerateHMACSHA256ValidationKey());
+ }
+
+ public string GenerateHMACSHA256ValidationKey()
+ {
+ //See: https://msdn.microsoft.com/en-us/library/vstudio/w8h3skw9%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
+ //See: https://msdn.microsoft.com/en-us/library/ff649308.aspx?f=255&MSPPError=-2147217396
+ /*
+ key value Specifies a manually assigned key.
+ The validationKey value must be manually set to a string of hexadecimal
+ characters to ensure consistent configuration across all servers in a Web farm.
+ The length of the key depends on the hash algorithm that is used:
+
+ AES requires a 256-bit key (64 hexadecimal characters).
+ MD5 requires a 128-bit key (32 hexadecimal characters).
+ SHA1 requires a 160-bit key (40 hexadecimal characters).
+ 3DES requires a 192-bit key (48 hexadecimal characters).
+ HMACSHA256 requires a 256-bit key (64 hexadecimal characters) == DEFAULT
+ HMACSHA384 requires a 384-bit key (96 hexadecimal characters).
+ HMACSHA512 requires a 512-bit key (128 hexadecimal characters).
+ */
+
+ //64 in length = 256 bits
+ return GenerateKey(64);
+ }
+
+ public string GenerateAESDecryptionKey()
+ {
+ //See: //See: https://msdn.microsoft.com/en-us/library/vstudio/w8h3skw9%28v=vs.100%29.aspx?f=255&MSPPError=-2147217396
+ /*
+ key value Specifies a manually assigned key.
+ The decryptionKey value must be manually set to a string of
+ hexadecimal characters to ensure consistent configuration across all servers in a Web farm.
+ The key should be 64 bits (16 hexadecimal characters) long for DES encryption, or 192 bits
+ (48 hexadecimal characters) long for 3DES. For AES, the key can be 128 bits (32 characters),
+ 192 bits (48 characters), or 256 bits (64 characters) long.
+ */
+
+ //64 in length = 256 bits
+ return GenerateKey(64);
+ }
+
+ private string GenerateKey(int len = 64)
+ {
+ var buff = new byte[len / 2];
+ var rng = new RNGCryptoServiceProvider();
+ rng.GetBytes(buff);
+ var sb = new StringBuilder(len);
+
+ for (int i = 0; i < buff.Length; i++)
+ sb.Append(string.Format("{0:X2}", buff[i]));
+
+ return sb.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 596c72b56a..43e94fce8e 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -666,6 +666,7 @@
+
diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.controller.js b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.controller.js
new file mode 100644
index 0000000000..bdcef63d95
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.controller.js
@@ -0,0 +1,14 @@
+angular.module("umbraco.install").controller("Umbraco.Installer.MachineKeyController", function ($scope, installerService) {
+
+
+ $scope.continue = function () {
+ installerService.status.current.model = true;
+ installerService.forward();
+ };
+
+ $scope.ignoreKey = function () {
+ installerService.status.current.model = false;
+ installerService.forward();
+ };
+
+});
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.html b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.html
new file mode 100644
index 0000000000..732c7c1d56
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.html
@@ -0,0 +1,23 @@
+
+
Configure an ASP.Net Machine Key
+
+ By default the installer will generate a custom ASP.Net Machine Key for your site and install it into your web.config file.
+ A Machine Key is used for hashing and encryption and it is recommended that you install a custom one into your site.
+ This ensures that your site is fully portable between environments that might have different Machine Key settings and that
+ your site by default will work with load balancing when installed between various server environments.
+
+
+
+
\ No newline at end of file
diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs
index 6c088365a1..a3069342fc 100644
--- a/src/Umbraco.Web/Install/InstallHelper.cs
+++ b/src/Umbraco.Web/Install/InstallHelper.cs
@@ -48,6 +48,7 @@ namespace Umbraco.Web.Install
new MajorVersion7UpgradeReport(_umbContext.Application),
new Version73FileCleanup(_umbContext.HttpContext, _umbContext.Application.ProfilingLogger.Logger),
new DatabaseConfigureStep(_umbContext.Application),
+ new ConfigureMachineKey(_umbContext.Application),
new DatabaseInstallStep(_umbContext.Application),
new DatabaseUpgradeStep(_umbContext.Application),
new StarterKitDownloadStep(_umbContext.Application, _umbContext.Security, _umbContext.HttpContext),
diff --git a/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs b/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs
new file mode 100644
index 0000000000..e4038df4ab
--- /dev/null
+++ b/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Configuration;
+using System.Linq;
+using System.Web.Configuration;
+using System.Xml.Linq;
+using Umbraco.Core;
+using Umbraco.Core.IO;
+using Umbraco.Core.Security;
+using Umbraco.Web.Install.Models;
+
+namespace Umbraco.Web.Install.InstallSteps
+{
+ [InstallSetupStep(InstallationType.NewInstall,
+ "ConfigureMachineKey", "machinekey", 2,
+ "Updating some security settings...",
+ PerformsAppRestart = true)]
+ internal class ConfigureMachineKey : InstallSetupStep
+ {
+ private readonly ApplicationContext _appContext;
+
+ public ConfigureMachineKey(ApplicationContext appContext)
+ {
+ if (appContext == null) throw new ArgumentNullException("appContext");
+ _appContext = appContext;
+ }
+
+ public override string View
+ {
+ get { return HasMachineKey() == false ? base.View : ""; }
+ }
+
+ ///
+ /// Don't display the view or execute if a machine key already exists
+ ///
+ ///
+ private bool HasMachineKey()
+ {
+ var section = (MachineKeySection)WebConfigurationManager.GetSection("system.web/machineKey");
+ return section.ElementInformation.Source != null;
+ }
+
+ ///
+ /// The step execution method
+ ///
+ ///
+ ///
+ public override InstallSetupResult Execute(bool? model)
+ {
+ if (model.HasValue && model.Value == false) return null;
+
+ //install the machine key
+ var fileName = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
+ var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
+
+ var systemWeb = xml.Root.DescendantsAndSelf("system.web").Single();
+
+ // Update appSetting if it exists, or else create a new appSetting for the given key and value
+ var machineKey = systemWeb.Descendants("machineKey").FirstOrDefault();
+ if (machineKey != null) return null;
+
+ var generator = new MachineKeyGenerator();
+ var generatedSection = generator.GenerateConfigurationBlock();
+ systemWeb.Add(XElement.Parse(generatedSection));
+
+ xml.Save(fileName, SaveOptions.DisableFormatting);
+
+ return null;
+ }
+
+ public override bool RequiresExecution(bool? model)
+ {
+ return HasMachineKey() == false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
index ce28a26176..9f74596ca2 100644
--- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
@@ -8,6 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Configuration;
+using Umbraco.Core.Logging;
using Umbraco.Core.Persistence;
using Umbraco.Web.Install.Models;
@@ -94,8 +95,9 @@ namespace Umbraco.Web.Install.InstallSteps
result.DetermineInstalledVersion();
return false;
}
- catch (Exception)
+ catch (Exception ex)
{
+ _applicationContext.ProfilingLogger.Logger.Error("An error occurred, reconfiguring...", ex);
//something went wrong, could not connect so probably need to reconfigure
return true;
}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 59d066093e..950e494e35 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -359,6 +359,7 @@
+