This commit is contained in:
@@ -193,7 +193,7 @@ namespace AyaNova.Api.Controllers
|
|||||||
DownloadToken = DownloadToken.Replace("+", "");
|
DownloadToken = DownloadToken.Replace("+", "");
|
||||||
u.DlKey = DownloadToken;
|
u.DlKey = DownloadToken;
|
||||||
u.DlKeyExpire = exp.DateTime;
|
u.DlKeyExpire = exp.DateTime;
|
||||||
await ct.SaveChangesAsync();
|
|
||||||
//=======================================================
|
//=======================================================
|
||||||
|
|
||||||
var payload = new Dictionary<string, object>()
|
var payload = new Dictionary<string, object>()
|
||||||
@@ -213,6 +213,10 @@ namespace AyaNova.Api.Controllers
|
|||||||
//issue tokens as well, but it looked cmplex and this works so unless need to remove in future keeping it.
|
//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 token = Jose.JWT.Encode(payload, secretKey, Jose.JwsAlgorithm.HS256);
|
||||||
|
|
||||||
|
//save auth token to ensure single sign on only
|
||||||
|
u.CurrentAuthToken = token;
|
||||||
|
await ct.SaveChangesAsync();
|
||||||
|
|
||||||
log.LogDebug($"User number \"{u.Id}\" logged in from \"{Util.StringUtil.MaskIPAddress(HttpContext.Connection.RemoteIpAddress.ToString())}\" ok");
|
log.LogDebug($"User number \"{u.Id}\" logged in from \"{Util.StringUtil.MaskIPAddress(HttpContext.Connection.RemoteIpAddress.ToString())}\" ok");
|
||||||
metrics.Measure.Meter.Mark(MetricsRegistry.SuccessfulLoginMeter);
|
metrics.Measure.Meter.Mark(MetricsRegistry.SuccessfulLoginMeter);
|
||||||
|
|
||||||
|
|||||||
@@ -360,30 +360,56 @@ namespace AyaNova
|
|||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
|
||||||
//Custom middleware to get user roles and put them into the request so
|
//Custom middleware to ensure token still valid and to
|
||||||
|
//get user roles and put them into the request so
|
||||||
//they can be authorized in routes.
|
//they can be authorized in routes.
|
||||||
app.Use(async (context, next) =>
|
app.Use(async (context, next) =>
|
||||||
{
|
{
|
||||||
if (!context.User.Identity.IsAuthenticated)
|
if (!context.User.Identity.IsAuthenticated)
|
||||||
{
|
{
|
||||||
context.Request.HttpContext.Items["AY_ROLES"] = 0;
|
context.Request.HttpContext.Items["AY_ROLES"] = 0;
|
||||||
|
await next.Invoke();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Get user ID from claims
|
//Get user ID from claims
|
||||||
long userId = Convert.ToInt64(context.User.FindFirst(c => c.Type == "id").Value);
|
long userId = Convert.ToInt64(context.User.FindFirst(c => c.Type == "id").Value);
|
||||||
|
|
||||||
|
//Get JWT
|
||||||
|
string JWT = string.Empty;
|
||||||
|
var AuthHeaders = context.Request.Headers[Microsoft.Net.Http.Headers.HeaderNames.Authorization];
|
||||||
|
foreach (String s in AuthHeaders)
|
||||||
|
{
|
||||||
|
if (s.ToLowerInvariant().Contains("bearer"))
|
||||||
|
{
|
||||||
|
JWT = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Get the database context
|
//Get the database context
|
||||||
var ct = context.RequestServices.GetService<AyContext>();
|
var ct = context.RequestServices.GetService<AyContext>();
|
||||||
|
|
||||||
//get the user record
|
//get the user record
|
||||||
var u = await ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, translationId = m.UserOptions.TranslationId }).FirstAsync();
|
var u = await ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, translationId = m.UserOptions.TranslationId, currentAuthToken = m.CurrentAuthToken }).FirstAsync();
|
||||||
context.Request.HttpContext.Items["AY_ROLES"] = u.roles;
|
context.Request.HttpContext.Items["AY_ROLES"] = u.roles;
|
||||||
context.Request.HttpContext.Items["AY_USERNAME"] = u.name;
|
context.Request.HttpContext.Items["AY_USERNAME"] = u.name;
|
||||||
context.Request.HttpContext.Items["AY_USER_ID"] = u.id;
|
context.Request.HttpContext.Items["AY_USER_ID"] = u.id;
|
||||||
context.Request.HttpContext.Items["AY_TRANSLATION_ID"] = u.translationId;
|
context.Request.HttpContext.Items["AY_TRANSLATION_ID"] = u.translationId;
|
||||||
|
|
||||||
|
//CHECK JWT
|
||||||
|
if (u.currentAuthToken != JWT)
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = 401;
|
||||||
|
context.Response.Headers.Add("X-AyaNova-Authorization-Error", "Authorization token was replaced by more recent login");
|
||||||
|
await context.Response.WriteAsync("Authorization token was replaced by more recent login");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await next.Invoke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await next.Invoke();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ namespace AyaNova.Models
|
|||||||
public string Salt { get; set; }
|
public string Salt { get; set; }
|
||||||
[Required]
|
[Required]
|
||||||
public AuthorizationRoles Roles { get; set; }
|
public AuthorizationRoles Roles { get; set; }
|
||||||
// [Required]
|
[JsonIgnore]
|
||||||
// public long TranslationId { get; set; }
|
public string CurrentAuthToken { get; set; }
|
||||||
public string DlKey { get; set; }
|
public string DlKey { get; set; }
|
||||||
public DateTime? DlKeyExpire { get; set; }
|
public DateTime? DlKeyExpire { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace AyaNova.Util
|
|||||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
||||||
private const int DESIRED_SCHEMA_LEVEL = 11;
|
private const int DESIRED_SCHEMA_LEVEL = 11;
|
||||||
|
|
||||||
internal const long EXPECTED_COLUMN_COUNT = 271;
|
internal const long EXPECTED_COLUMN_COUNT = 272;
|
||||||
internal const long EXPECTED_INDEX_COUNT = 118;
|
internal const long EXPECTED_INDEX_COUNT = 118;
|
||||||
|
|
||||||
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
//!!!!WARNING: BE SURE TO UPDATE THE DbUtil::EmptyBizDataFromDatabaseForSeedingOrImporting WHEN NEW TABLES ADDED!!!!
|
||||||
@@ -170,7 +170,7 @@ namespace AyaNova.Util
|
|||||||
|
|
||||||
//Add user table
|
//Add user table
|
||||||
await ExecQueryAsync("CREATE TABLE auser (id BIGSERIAL PRIMARY KEY, active bool not null, name varchar(255) not null unique, " +
|
await ExecQueryAsync("CREATE TABLE auser (id BIGSERIAL PRIMARY KEY, active bool not null, name varchar(255) not null unique, " +
|
||||||
"login text not null, password text not null, salt text not null, roles integer not null, " +
|
"login text not null, password text not null, salt text not null, roles integer not null, currentauthtoken text, " +
|
||||||
"dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, customerid bigint, " +
|
"dlkey text, dlkeyexpire timestamp, usertype integer not null, employeenumber varchar(255), notes text, customerid bigint, " +
|
||||||
"headofficeid bigint, subvendorid bigint, wiki text null, customfields text, tags varchar(255) ARRAY)");
|
"headofficeid bigint, subvendorid bigint, wiki text null, customfields text, tags varchar(255) ARRAY)");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user