Browse Source

Added auth token editing to the user settings page under security.

tags/2.0.6
Teknikode 3 years ago
parent
commit
41e4dca194

+ 34
- 0
Teknik/Areas/User/Controllers/UserController.cs View File

@@ -100,6 +100,7 @@ namespace Teknik.Areas.Users.Controllers
model.UserID = user.UserId;
model.Username = user.Username;
model.TrustedDeviceCount = user.TrustedDevices.Count;
model.AuthTokens = user.AuthTokens.ToList();

model.UserSettings = user.UserSettings;
model.SecuritySettings = user.SecuritySettings;
@@ -777,5 +778,38 @@ namespace Teknik.Areas.Users.Controllers
return Json(new { error = ex.GetFullMessage(true) });
}
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult GenerateToken(string name)
{
try
{
User user = UserHelper.GetUser(db, User.Identity.Name);
if (user != null)
{
string newTokenStr = UserHelper.GenerateAuthToken(Config, user.Username);

if (!string.IsNullOrEmpty(newTokenStr))
{
AuthToken token = db.AuthTokens.Create();
token.UserId = user.UserId;
token.HashedToken = SHA256.Hash(newTokenStr);
token.Name = name;
token.LastDateUsed = DateTime.Now;

db.AuthTokens.Add(token);
db.SaveChanges();
return Json(new { result = newTokenStr });
}
return Json(new { error = "Unable to generate Auth Token" });
}
return Json(new { error = "User does not exist" });
}
catch (Exception ex)
{
return Json(new { error = ex.GetFullMessage(true) });
}
}
}
}

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

@@ -92,6 +92,68 @@
});
});

$('#generate_token').click(function () {
bootbox.prompt("Specify a name for this Auth Token", function (result) {
if (result) {
$.ajax({
type: "POST",
url: generateTokenURL,
data: AddAntiForgeryToken({ name: result }),
success: function (response) {
if (response.result) {
bootbox.dialog({
title: "Authentication Token",
message: '<label for="authToken">Make sure to copy your new personal access token now.<br />You won\'t be able to see it again!</label><input type="text" class="form-control" id="authToken" onClick="this.select();" value="' + response.result + '">',
callback: function () {
window.location.reload();
}
});
}
else {
errorMsg = response;
if (response.error) {
errorMsg = response.error;
if (response.error.message) {
errorMsg = response.error.message;
}
}
$("#top_msg").css('display', 'inline', 'important');
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + errorMsg + '</div>');
}
}
});
}
});
});

$('#revoke_all_tokens').click(function () {
bootbox.confirm("Are you sure you want to revoke all your auth tokens?<br /><br />This is <b>irreversable</b> and all applications using a token will stop working.", function (result) {
if (result) {
$.ajax({
type: "POST",
url: revokeAllTokensURL,
data: AddAntiForgeryToken({}),
success: function (response) {
if (response.result) {
window.location.reload();
}
else {
errorMsg = response;
if (response.error) {
errorMsg = response.error;
if (response.error.message) {
errorMsg = response.error.message;
}
}
$("#top_msg").css('display', 'inline', 'important');
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' + errorMsg + '</div>');
}
}
});
}
});
});

$('#delete_account').click(function () {
bootbox.confirm("Are you sure you want to delete your account?", function (result) {
if (result) {

+ 2
- 2
Teknik/Areas/User/Utility/UserHelper.cs View File

@@ -134,11 +134,11 @@ namespace Teknik.Areas.Users.Utility
}
}

public static string GenerateAuthToken(Config config, User user)
public static string GenerateAuthToken(Config config, string username)
{
try
{
string username = user.Username.ToLower();
username = username.ToLower();
byte[] hashBytes = SHA384.Hash(username, StringHelper.RandomString(24));
string hash = hashBytes.ToHex();


+ 2
- 0
Teknik/Areas/User/ViewModels/SettingsViewModel.cs View File

@@ -15,6 +15,8 @@ namespace Teknik.Areas.Users.ViewModels

public int TrustedDeviceCount { get; set; }

public List<AuthToken> AuthTokens { get; set; }

public UserSettings UserSettings { get; set; }

public SecuritySettings SecuritySettings { get; set; }

+ 55
- 22
Teknik/Areas/User/Views/User/Settings.cshtml View File

@@ -1,6 +1,7 @@
@model Teknik.Areas.Users.ViewModels.SettingsViewModel

@using Teknik.Utilities
@using Teknik.Areas.Users.Models

<script>
var homeUrl = '@Url.SubRouteUrl("www", "Home.Index")';
@@ -9,6 +10,10 @@
var resendVerifyURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "ResendVerifyRecoveryEmail"})';
var confirmAuthSetupURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "VerifyAuthenticatorCode" })';
var clearTrustedDevicesURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "ClearTrustedDevices" })';
var generateTokenURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "GenerateToken" })';
var revokeAllTokensURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "RevokeAllTokens" })';
var editTokenName = '@Url.SubRouteUrl("user", "User.Action", new { action = "EditTokenName" })';
var deleteTokenURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "DeleteToken" })';
</script>

@Styles.Render("~/Content/user")
@@ -127,7 +132,7 @@
</div>
</div>
<div class="row">
<div class="col-sm-4">
<div class="col-sm-4 text-left">
<div class="row">
<div class="form-group col-sm-12">
<label for="update_recovery_email"><h4>Recovery Email</h4></label>
@@ -147,30 +152,58 @@
}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4 text-left">
<label for="update_security_two_factor"><h4>Enable Two Factor Authentication</h4></label>
<div class="checkbox">
<label>
<input id="update_security_two_factor" name="update_security_two_factor" title="whether two factor authentication should occur for this account" type="checkbox" value="true" @(Model.SecuritySettings.TwoFactorEnabled ? "checked" : string.Empty) />
</label>
<div class="row">
<div class="form-group col-sm-12 text-left">
<label for="update_security_two_factor"><h4>Enable Two Factor Authentication</h4></label>
<div class="checkbox">
<label>
<input id="update_security_two_factor" name="update_security_two_factor" title="whether two factor authentication should occur for this account" type="checkbox" value="true" @(Model.SecuritySettings.TwoFactorEnabled ? "checked" : string.Empty) />
</label>
</div>
<p class="form-control-static @(Model.SecuritySettings.TwoFactorEnabled ? string.Empty : "hide")" id="setupAuthenticatorLink">
<small><a href="#" class="text-primary" id="SetupAuthenticator" data-toggle="modal" data-target="#authenticatorSetup"><i class="fa fa-lock"></i> Set Up Authenticator</a></small>
</p>
</div>
</div>
<div class="row">
<div class="form-group col-sm-12 text-left">
<label for="update_security_allow_trusted"><h4>Allow Trusted Devices</h4></label>
<div class="checkbox">
<label>
<input id="update_security_allow_trusted" name="update_security_allow_trusted" title="whether a device could be cached to bypass two factor authentication" type="checkbox" value="true" @(Model.SecuritySettings.AllowTrustedDevices ? "checked" : string.Empty) />
</label>
</div>
<p class="form-control-static @(Model.SecuritySettings.AllowTrustedDevices ? string.Empty : "hide")" id="ClearDevicesLink">
<small><a href="#" class="text-primary" id="ClearDevices">Clear Trusted Devices (@Model.TrustedDeviceCount)</a></small>
</p>
</div>
</div>
<p class="form-control-static @(Model.SecuritySettings.TwoFactorEnabled ? string.Empty : "hide")" id="setupAuthenticatorLink">
<small><a href="#" class="text-primary" id="SetupAuthenticator" data-toggle="modal" data-target="#authenticatorSetup"><i class="fa fa-lock"></i> Set Up Authenticator</a></small>
</p>
</div>
<div class="col-sm-4 text-left">
<label for="update_security_allow_trusted"><h4>Allow Trusted Devices</h4></label>
<div class="checkbox">
<label>
<input id="update_security_allow_trusted" name="update_security_allow_trusted" title="whether a device could be cached to bypass two factor authentication" type="checkbox" value="true" @(Model.SecuritySettings.AllowTrustedDevices ? "checked" : string.Empty) />
</label>
<div class="col-sm-8">
<br />
<label for="authCodes"><h4>Authentication Tokens</h4></label><span class="pull-right"><button type="button" class="btn btn-default" id="generate_token">Generate Token</button> <button type="button" class="btn btn-danger" id="revoke_all_tokens">Revoke All</button></span>
<div id="authCodes" style="overflow-y: auto; max-height: 400px;">
<ul class="list-group">
@if (Model.AuthTokens.Any())
{
foreach (AuthToken token in Model.AuthTokens)
{
<li class="list-group-item">
<div class="btn-group btn-group-sm pull-right" role="group" aria-label="...">
<button type="button" class="btn btn-default">Edit</button>
<button type="button" class="btn btn-danger text-danger">Delete</button>
</div>
<h4 class="list-group-item-heading" id="update_auth_token_name">@token.Name</h4>
<p class="list-group-item-text">Last Used on <time datetime="@token.LastDateUsed.ToString("s")">@token.LastDateUsed.ToString("MMMM dd, yyyy hh:mm tt")</time></p>
</li>
}
}
else
{
<li class="list-group-item text-center">No Auth Codes</li>
}
</ul>
</div>
<p class="form-control-static @(Model.SecuritySettings.AllowTrustedDevices ? string.Empty : "hide")" id="ClearDevicesLink">
<small><a href="#" class="text-primary" id="ClearDevices">Clear Trusted Devices (@Model.TrustedDeviceCount)</a></small>
</p>
</div>
</div>
</div>

Loading…
Cancel
Save