142 lines
6.5 KiB
C#

using System;
using System.Text.Json;
namespace perubahan;
public static class Auth
{
internal static bool TryGetUser(HttpContext context, out SafeUser user)
{
if (context.Items.TryGetValue("AuthorizedUser", out object? userObj) && userObj is SafeUser safeUser)
{
user = safeUser;
return true;
}
user = null!;
return false;
}
internal static bool IsAuthorized(HttpContext context, int requiredLevel)
{
return TryGetUser(context, out SafeUser user) && user.Level <= requiredLevel;
}
internal static bool IsAuthorized(HttpContext context, string Username)
{
return TryGetUser(context, out SafeUser user) && user.Username == Username;
}
internal static Task RejectUnauthorized(HttpContext context)
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return context.Response.WriteAsJsonAsync(new SimpleApiResponse(401, "Unauthorized."), SGContext.Default.SimpleApiResponse);
}
internal static void Handle(IApplicationBuilder App)
{
App
.Map("/logout", logout =>
{
logout.Run(async runner =>
{
if (!HttpMethods.IsGet(runner.Request.Method) || runner.Request.HasJsonContentType() || runner.Request.HasFormContentType)
{
await runner.WriteJsonResponse(StatusCodes.Status400BadRequest, "Improper request to log out.");
return;
}
runner.Response.Cookies.Append("session", "", Delete);
if (runner.Items.ContainsKey("AuthorizedUser"))
{
await runner.WriteJsonResponse(StatusCodes.Status200OK, "Log out successful. Authorisation token deleted.");
}
else
{
await runner.WriteJsonResponse(StatusCodes.Status200OK, "No user to log out. Authorisation token does not exists.");
}
});
})
.Map("/login", login =>
{
login.Run(async runner =>
{
if (runner.Items.ContainsKey("AuthorizedUser"))
{
await runner.WriteJsonResponse(StatusCodes.Status409Conflict, "Log in not allowed when an authorized user is already logged in.");
}
else if (runner.Request.ContentType != "application/json")
{
await runner.WriteJsonResponse(StatusCodes.Status400BadRequest, "Request Content-Type mismatch.");
}
else
{
LoginUser LoginInfo = (await runner.Request.ReadFromJsonAsync(SGContext.Default.LoginUser))!;
if (LoginInfo.Username is null || LoginInfo.Password is null)
{
await runner.WriteJsonResponse(StatusCodes.Status401Unauthorized, "No valid user information provided.");
return;
}
string SHA256Pass = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(LoginInfo.Password)));
if (UserAccounts.TryGetValue(LoginInfo.Username, out User? FoundUser) && FoundUser.Password.Equals(SHA256Pass, StringComparison.InvariantCultureIgnoreCase) && FoundUser.Active)
{
SafeUser LoggedIn = SafeUser.FromUser(FoundUser);
string LoggedInBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(LoggedIn, SGContext.Default.SafeUser)));
string Signature = Convert.ToBase64String(SHA256.HashData(Encoding.UTF8.GetBytes(LoggedInBase64 + SecretKey)));
runner.Response.Cookies.Append("session", $"{LoggedInBase64}.{Signature}", HttpOnly);
await runner.WriteJsonResponse(StatusCodes.Status200OK, "User authorised. Authorisation token created.", LoggedIn);
}
else
{
await runner.WriteJsonResponse(StatusCodes.Status401Unauthorized, "Provided user information cannot be authorized");
}
}
});
})
.Map("/gate", auth =>
{
auth.Run(async runner =>
{
if (runner.Request.ContentType != "application/json")
{
await runner.WriteJsonResponse(StatusCodes.Status400BadRequest, "Request Content-Type mismatch.");
}
else
{
LoginUser LoginInfo = (await runner.Request.ReadFromJsonAsync(SGContext.Default.LoginUser))!;
if (LoginInfo.Username is null || LoginInfo.Password is null)
{
await runner.WriteJsonResponse(StatusCodes.Status401Unauthorized, "No valid user information provided.");
return;
}
string SHA256Pass = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(LoginInfo.Password)));
if (UserAccounts.TryGetValue(LoginInfo.Username, out User? FoundUser) && FoundUser.Password.Equals(SHA256Pass, StringComparison.InvariantCultureIgnoreCase) && FoundUser.Active)
{
await runner.WriteJsonResponse(StatusCodes.Status200OK, "User authorised. Operation may continue.", SafeUser.FromUser(FoundUser));
}
else
{
await runner.WriteJsonResponse(StatusCodes.Status401Unauthorized, "Provided user information cannot be authorized");
}
}
});
})
.Map("/me", me =>
{
me.Run(async runner =>
{
if (TryGetUser(runner, out SafeUser user))
{
await runner.WriteJsonResponse(StatusCodes.Status200OK, "Success.", user);
}
else
{
await runner.WriteJsonResponse(StatusCodes.Status401Unauthorized, "No user session token is included with the request.");
}
});
})
.Run(async runner=>
{
await runner.WriteJsonResponse(StatusCodes.Status404NotFound);
})
;
}
}