mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Added auth token editing to the user settings page under security.
This commit is contained in:
parent
a40b5804fb
commit
41e4dca194
@ -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) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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">×</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">×</button>' + errorMsg + '</div>');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#delete_account').click(function () {
|
||||
bootbox.confirm("Are you sure you want to delete your account?", function (result) {
|
||||
if (result) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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>
|
||||
<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="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>
|
||||
</div>
|
||||
<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…
Reference in New Issue
Block a user