Browse Source

Added initial structure for Two Factor authentication

tags/2.0.3
Teknikode 3 years ago
parent
commit
54a9d8e4f0

+ 42
- 1
Teknik/Areas/User/Controllers/UserController.cs View File

@@ -20,6 +20,9 @@ using System.Windows;
using System.Net;
using Teknik.Areas.Users.Utility;
using Teknik.Filters;
using QRCoder;
using System.Text;
using TwoStepsAuthenticator;

namespace Teknik.Areas.Users.Controllers
{
@@ -274,7 +277,7 @@ namespace Teknik.Areas.Users.Controllers
}

[HttpPost]
public ActionResult Edit(string curPass, string newPass, string newPassConfirm, string pgpPublicKey, string recoveryEmail, string website, string quote, string about, string blogTitle, string blogDesc, bool saveKey, bool serverSideEncrypt)
public ActionResult Edit(string curPass, string newPass, string newPassConfirm, string pgpPublicKey, string recoveryEmail, bool twoFactorEnabled, string website, string quote, string about, string blogTitle, string blogDesc, bool saveKey, bool serverSideEncrypt)
{
if (ModelState.IsValid)
{
@@ -316,6 +319,14 @@ namespace Teknik.Areas.Users.Controllers
user.SecuritySettings.RecoveryVerified = false;
}

user.SecuritySettings.TwoFactorEnabled = twoFactorEnabled;
string newKey = string.Empty;
if (twoFactorEnabled)
{
newKey = Authenticator.GenerateKey();
}
user.SecuritySettings.TwoFactorKey = newKey;

user.UserSettings.Website = website;
user.UserSettings.Quote = quote;
user.UserSettings.About = about;
@@ -517,5 +528,35 @@ namespace Teknik.Areas.Users.Controllers
}
return Json(new { error = "Unable to reset user password" });
}

[HttpPost]
public ActionResult ConfirmAuthenticatorCode(string code)
{
User user = UserHelper.GetUser(db, User.Identity.Name);
if (user != null)
{
if (user.SecuritySettings.TwoFactorEnabled)
{
string key = user.SecuritySettings.TwoFactorKey;

TimeAuthenticator ta = new TimeAuthenticator();
bool isValid = false;

return Json(new { result = true });
}
return Json(new { error = "User does not have Two Factor Authentication enabled" });
}
return Json(new { error = "User does not exist" });
}

[HttpPost]
public ActionResult GenerateQrCode(string content)
{
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(content, QRCodeGenerator.ECCLevel.Q);
SvgQRCode qrCode = new SvgQRCode(qrCodeData);
string qrCodeImage = qrCode.GetGraphic(20);
return File(Encoding.UTF8.GetBytes(qrCodeImage), "image/svg+xml");
}
}
}

+ 1
- 0
Teknik/Areas/User/Scripts/User.js View File

@@ -62,6 +62,7 @@
password = $("#update_password").val();
password_confirm = $("#update_password_confirm").val();
update_pgp_public_key = $("#update_pgp_public_key").val();
update_security_two_factor = $("#update_security_two_factor").val();
recovery = $("#update_recovery_email").val();
website = $("#update_website").val();
quote = $("#update_quote").val();

+ 1
- 0
Teknik/Areas/User/Views/User/AuthenticatorSetup.cshtml View File

@@ -0,0 +1 @@


+ 70
- 0
Teknik/Areas/User/Views/User/Settings.cshtml View File

@@ -15,6 +15,60 @@
<div class="container">
@if (!Model.Error)
{
<div class="modal fade" id="authenticatorSetup" tabindex="-1" role="dialog" aria-labelledby="authenticatorSetupLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="authSetupTitleLabel">Set Up a Third Party App to Generate Codes</h4>
</div>
<div class="modal-body">
@if (Model.SecuritySettings.TwoFactorEnabled)
{
<form class="form" action="@Url.SubRouteUrl("user", "User.Action", new { action = "ConfirmAuthenticatorCode" })" method="post" id="confirmAuthSetup">
<p>To get a third party app working, either scan the QR code below or type the secret key into the app.</p>
<div class="row">
<div class="col-sm-2">
QR Code:
</div>
<div class="col-sm-10 text-right">
<!-- QR Code -->
<img src="@Url.SubRouteUrl("user", "User.Action", new { action = "GenerateQRCode", content = Model.SecuritySettings.TwoFactorKey })" alt="qr code" />
</div>
</div>
<div class="row">
<div class="col-sm-2">
Secret Key:
</div>
<div class="col-sm-10">
<span class="text-success" id="authSetupSecretKey"></span>
</div>
</div>
<hr />
<p>To confirm the third party app is set up correctly, enter the security code that appears on your phone.</p>
<div class="row">
<div class="col-sm-2">
Security Code:
</div>
<div class="col-sm-10">
<input class="form-control" id="auth_setup_code" name="auth_setup_code" title="Authenticator Security Code" type="text" />
</div>
</div>
<hr />
<br />
<div class="row">
<div class="col-sm-12">
<div class="form-group text-right">
<button class="btn btn-primary" id="auth_setup_confirm" type="submit" name="auth_setup_confirm">Confirm</button>
</div>
</div>
</div>
</form>
}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<form class="form" action="##" method="post" id="updateForm">
@@ -97,6 +151,22 @@
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="checkbox">
<label>
<label for="update_security_two_factor"><h4>Enable Two Factor Authentication</h4></label>
<input id="update_security_two_factor" name="update_security_two_factor" title="whether the key should be saved on the server or not" type="checkbox" value="true" @(Model.SecuritySettings.TwoFactorEnabled ? "checked" : string.Empty) />
@if (Model.SecuritySettings.TwoFactorEnabled)
{
<p class="form-control-static">
<small><a href="#" class="text-primary" id="SetupAuthenticator"><i class="fa fa-lock"></i> Set Up Authenticator</a></small>
</p>
}
</label>
</div>
</div>
</div>
</div>
<!-- Blog Settings -->
<div class="tab-pane" id="blog">

+ 14
- 0
Teknik/Helpers/Utility.cs View File

@@ -1,6 +1,7 @@
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Dynamic;
using System.IO;
using System.Linq;
@@ -157,5 +158,18 @@ namespace Teknik
}
return hashString;
}

public static byte[] ImageToByte(Image img)
{
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();

byteArray = stream.ToArray();
}
return byteArray;
}
}
}

+ 13
- 0
Teknik/Teknik.csproj View File

@@ -91,6 +91,10 @@
<Private>True</Private>
</Reference>
<Reference Include="PresentationFramework" />
<Reference Include="QRCoder, Version=1.1.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\QRCoder.1.1.8\lib\net40\QRCoder.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="RouteDebugger, Version=2.1.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\routedebugger.2.1.5\lib\net40\RouteDebugger.dll</HintPath>
<Private>True</Private>
@@ -154,6 +158,14 @@
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="TwoStepsAuthenticator, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\TwoStepsAuthenticator.1.1.0\lib\net45\TwoStepsAuthenticator.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\QRCoder.1.1.8\lib\net40\UnityEngine.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="WebGrease, Version=1.6.5135.21930, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\WebGrease.1.6.0\lib\WebGrease.dll</HintPath>
<Private>True</Private>
@@ -544,6 +556,7 @@
<Content Include="Areas\User\Views\User\ViewRecoveryEmailVerification.cshtml" />
<Content Include="Areas\User\Views\User\ResetPasswordVerification.cshtml" />
<Content Include="Areas\User\Views\User\ResetPassword.cshtml" />
<Content Include="Areas\User\Views\User\AuthenticatorSetup.cshtml" />
<None Include="Properties\PublishProfiles\Teknik Dev.pubxml" />
<None Include="Properties\PublishProfiles\Teknik Production.pubxml" />
<None Include="Scripts\jquery-2.1.4.intellisense.js" />

+ 2
- 0
Teknik/packages.config View File

@@ -27,7 +27,9 @@
<package id="nClam" version="2.0.6.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" userInstalled="true" />
<package id="Piwik.Tracker" version="2.8.0.0" targetFramework="net452" />
<package id="QRCoder" version="1.1.8" targetFramework="net452" />
<package id="Respond" version="1.4.2" targetFramework="net452" userInstalled="true" />
<package id="routedebugger" version="2.1.5" targetFramework="net452" userInstalled="true" />
<package id="TwoStepsAuthenticator" version="1.1.0" targetFramework="net452" />
<package id="WebGrease" version="1.6.0" targetFramework="net46" userInstalled="true" />
</packages>

Loading…
Cancel
Save