ITraxAuditRedactor

NO WARRANTY. Trax auth is plumbing, not a security product. You are solely responsible for securing systems that use it. See API Security.

Decides which GraphQL variables, if any, an audit entry records. Variables carry whatever the caller sent, so the default records none of them: a host that wants them registers its own redactor with services.AddSingleton<ITraxAuditRedactor, MyRedactor>() and chooses what to keep.

Signature

public interface ITraxAuditRedactor
{
    JsonObject? Redact(JsonObject? variables);
}

variables is a System.Text.Json.Nodes.JsonObject built for this call, or null when the request had none. An input object is a nested JsonObject and a list a JsonArray, so a field such as $input.password can be found at any depth. Change the object in place and return it, return a different one, or return null to record no variables. If the redactor throws, the entry is recorded without variables.

The default implementation, DefaultAuditRedactor, returns null: no variables are recorded.

Literal values written in the document itself never reach the redactor or the entry. The listener replaces every string with "" and every number with 0 before it records the document. See API Security.

Example

Keep the variables, minus a set of sensitive fields at any depth:

public sealed class SensitiveFieldRedactor : ITraxAuditRedactor
{
    private static readonly HashSet<string> Sensitive = new(StringComparer.OrdinalIgnoreCase)
    {
        "password", "token", "apiKey", "secret", "ssn",
    };
 
    public JsonObject? Redact(JsonObject? variables)
    {
        Strip(variables);
        return variables;
    }
 
    private static void Strip(JsonNode? node)
    {
        switch (node)
        {
            case JsonObject obj:
                foreach (var key in obj.Select(p => p.Key).Where(Sensitive.Contains).ToList())
                    obj.Remove(key);
                foreach (var (_, child) in obj)
                    Strip(child);
                break;
            case JsonArray array:
                foreach (var child in array)
                    Strip(child);
                break;
        }
    }
}

A removal list misses a field nobody thought of. Where that matters, copy across only the fields you mean to record.