‹ All interview questions

Core Concepts

You've configured [Authorize(Roles = 'Admin')] and policy-based authorization in dozens of .NET apps.

The question

You've configured [Authorize(Roles = 'Admin')] and policy-based authorization in dozens of .NET apps. ServiceNow uses 'ACLs' — Access Control Lists — to protect data at the table, row, and field level. Walk me through how ACLs work, the evaluation order, and what surprises a developer used to role-based auth in .NET.

Why This Comes Up in Interviews

ServiceNow ACLs are a declarative security layer that evaluates automatically on every data access — UI, API, scripts, everywhere. Unlike .NET where you explicitly decorate endpoints with [Authorize], ACLs are always on. This is closer to SQL Server's row-level security or Azure AD's conditional access than ASP.NET's attribute-based auth.

Evaluation Order (Most to Least Specific)

// ACL Evaluation Hierarchy
// Think of it like CSS specificity — most specific wins
//
// 1. table.field    (e.g., incident.caller_id)     → Most specific
// 2. table.*        (e.g., incident.*)              → Table-level
// 3. *.field        (e.g., *.caller_id)             → Field across all tables
// 4. *.*            (e.g., *.*)                     → Global default
//
// Operations: read, write, create, delete
// Must pass BOTH the matching field rule AND the matching table rule.
// More-specific rules stop processing of less-specific ones, and
// several rules matching at the SAME point are OR'd (pass any one).

// .NET Equivalent Mental Model:
// [Authorize(Roles = "itil")]           → Role check in ACL
// [Authorize(Policy = "SameTeam")]      → Script/Condition in ACL
// Both must pass = AND behavior

The Three ACL Components

  • Role requirement: Like [Authorize(Roles = "itil")]. User must have the specified role.
  • Condition: A filter query on the record — like a LINQ .Where() clause. Example: active=true^assigned_to=javascript:gs.getUserID() means 'only if the record is active AND assigned to the current user.'
  • Script: Advanced logic in JavaScript. Like writing a custom IAuthorizationHandler in .NET policy-based auth. Returns true/false.
// ACL Script example — like a custom IAuthorizationHandler
// This runs on every read of the incident table
answer = (function() {
  // Allow if user is in the same department as the caller
  var caller = current.caller_id.department;
  var userDept = gs.getUser().getDepartmentID();
  return caller == userDept;
})();

What Surprises .NET Developers

  • ACLs are always enforced: Unlike .NET where forgetting [Authorize] means open access, ServiceNow denies access by default if no ACL grants it. It's a whitelist model, not a blacklist.
  • Admin bypasses everything: The admin role skips ACL evaluation entirely — unless the ACL script explicitly checks for admin. This is like having a global [AllowAnonymous] override for admins, which can be a security concern.
  • API calls respect ACLs: If you call the Table API as a service account, ACLs on that user's roles determine what's returned. There's no separate API auth layer — unlike .NET where you might have different auth for UI vs API.
  • Row + field AND catches people: If the table-level ACL requires role 'itil' AND the field-level ACL requires role 'incident_manager', the user needs BOTH roles — like stacking [Authorize] attributes. But note the flip side: multiple ACLs matching at the same point are OR'd, so passing any one of them is enough.
💡 .NET Developer Pro Tip

Enable Debug Security Rules (System Security > Debugging) in your dev instance — it's like adding app.UseDeveloperExceptionPage() for auth. You'll see exactly which ACLs evaluated, which passed, and which blocked access. Essential for debugging 'why can't this user see this record?' issues.