115 lines
4.3 KiB
C#
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 |