118 lines
4.5 KiB
C#
118 lines
4.5 KiB
C#
using System.Collections.Generic;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using rockfishCore.Models;
|
|
using rockfishCore.Util;
|
|
using System.Linq;
|
|
using System;
|
|
|
|
//required to inject configuration in constructor
|
|
using Microsoft.Extensions.Configuration;
|
|
|
|
namespace rockfishCore.Controllers
|
|
{
|
|
//Authentication controller
|
|
public class AuthController : Controller
|
|
{
|
|
private readonly rockfishContext _context;
|
|
private readonly IConfiguration _configuration;
|
|
public AuthController(rockfishContext context, IConfiguration configuration)//these two are injected, see startup.cs
|
|
{
|
|
_context = context;
|
|
_configuration = configuration;
|
|
}
|
|
|
|
//AUTHENTICATE CREDS
|
|
//RETURN JWT
|
|
|
|
[HttpPost("/authenticate")]
|
|
public JsonResult PostCreds(string login, string password) //if was a json body then //public JsonResult PostCreds([FromBody] string login, [FromBody] 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 });
|
|
}
|
|
|
|
//DANGER DANGER - this assumes all logins are different...boo bad code
|
|
//FIXME
|
|
//BUGBUG
|
|
//TODO
|
|
//ETC
|
|
/*HOW TO FIX: because of the salt during login it must assume multiple users with the same login and
|
|
fetch each in turn, get the salt, hash the entered password and compare to the password stored password
|
|
|
|
So, instead of singleordefault must be assumed to be a collection of users returned in this code:
|
|
*/
|
|
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 });
|
|
}
|
|
|
|
// string pwnew=Hasher.hash(user.Salt,"2df5cc611ee485d4aa897350daa045caa4015147ae34c6b7b363f1def605d305");
|
|
|
|
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();
|
|
var exp = new DateTimeOffset(DateTime.Now.AddDays(30)).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", "rockfishCore" },
|
|
{ "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 |