Files
pecklist/Controllers/AuthController.cs
2018-06-28 23:08:13 +00:00

115 lines
4.3 KiB
C#

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using GZTW.Pecklist.Models;
using GZTW.Pecklist.Util;
using System.Linq;
using System;
//required to inject configuration in constructor
using Microsoft.Extensions.Configuration;
namespace GZTW.Pecklist.Controllers
{
//Authentication controller
public class AuthController : Controller
{
private readonly PecklistContext _context;
private readonly IConfiguration _configuration;
public AuthController(PecklistContext context, IConfiguration configuration)//these two are injected, see startup.cs
{
_context = context;
//_configuration = configuration;
//guard clause
_configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
}
//AUTHENTICATE CREDS
//RETURN JWT
[HttpPost("/authenticate")]
public JsonResult PostCreds(string login, string password)
{
int nFailedAuthDelay = 10000;
if (string.IsNullOrWhiteSpace(login) || string.IsNullOrWhiteSpace(password))
{
//Make a failed pw wait
System.Threading.Thread.Sleep(nFailedAuthDelay);
return Json(new { msg = "authentication failed", error = 1 });
}
var user = _context.User.SingleOrDefault(m => m.Login == login);
if (user == null)
{
//Make a failed pw wait
System.Threading.Thread.Sleep(nFailedAuthDelay);
return Json(new { msg = "authentication failed", error = 1 });
}
//TODO: do a test login from postman, login as john, then copy pw into db
//string pwnewJohn=Hasher.hash(user.Salt,"XXX");
//then login as Joyce and copy pw into db
// string pwnewJoyce=Hasher.hash(user.Salt,"XXX");
string hashed = Hasher.hash(user.Salt, password);
if (hashed == user.Password)
{
//get teh secret from appsettings.json
var secret = _configuration.GetSection("JWT").GetValue<string>("secret");
byte[] secretKey = System.Text.Encoding.ASCII.GetBytes(secret);
var iat = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds();
//NOTE: pecklist is appropriate for a really long expiry
var exp = new DateTimeOffset(DateTime.Now.AddDays(365)).ToUnixTimeSeconds();
//Generate a download token and store it with the user account and return it for the client
Guid g = Guid.NewGuid();
string dlkey = Convert.ToBase64String(g.ToByteArray());
dlkey = dlkey.Replace("=", "");
dlkey = dlkey.Replace("+", "");
user.DlKey = dlkey;
user.DlKeyExp = exp;
_context.User.Update(user);
_context.SaveChanges();
var payload = new Dictionary<string, object>()
{
{ "iat", iat.ToString() },
{ "exp", exp.ToString() },
{ "iss", "GZTW_Pecklist" },
{ "id", user.Id.ToString() }
};
//NOTE: probably don't need Jose.JWT as am using Microsoft jwt stuff to validate routes so it should also be able to
//issue tokens as well, but it looked cmplex and this works so unless need to remove in future keeping it.
string token = Jose.JWT.Encode(payload, secretKey, Jose.JwsAlgorithm.HS256);
//string jsonDecoded = Jose.JWT.Decode(token, secretKey);
return Json(new
{
ok = 1,
issued = iat,
expires = exp,
token = token,
dlkey = dlkey,
name = user.Name,
id = user.Id
});
}
else
{
//Make a failed pw wait
System.Threading.Thread.Sleep(nFailedAuthDelay);
return Json(new { msg = "authentication failed", error = 1 });
}
}
//------------------------------------------------------
}//eoc
}//eons