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 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); }) ; } }