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 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 WriteJsonResponse(runner,StatusCodes.Status400BadRequest,"Improper request to log out."); return; } runner.Response.Cookies.Append("session", "", Delete); if(runner.Items.ContainsKey("AuthorizedUser")) { await WriteJsonResponse(runner,StatusCodes.Status200OK,"Log out successful. Authorisation token deleted."); } else { await WriteJsonResponse(runner,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 WriteJsonResponse(runner,StatusCodes.Status409Conflict,"Log in not allowed when an authorized user is already logged in."); } else if(runner.Request.ContentType != "application/json") { await WriteJsonResponse(runner,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 WriteJsonResponse(runner,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 WriteJsonResponse(runner,StatusCodes.Status200OK,"User authorised. Authorisation token created.",LoggedIn); } else { await WriteJsonResponse(runner,StatusCodes.Status401Unauthorized,"Provided user information cannot be authorized"); } } }); }) .Map("/gate", auth =>{ auth.Run(async runner=>{ if(runner.Request.ContentType != "application/json") { await WriteJsonResponse(runner,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 WriteJsonResponse(runner,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 WriteJsonResponse(runner,StatusCodes.Status200OK,"User authorised. Operation may continue.",SafeUser.FromUser(FoundUser)); } else { await WriteJsonResponse(runner,StatusCodes.Status401Unauthorized,"Provided user information cannot be authorized"); } } }); }); } }