ASP.NET Core

DDD in an LDAP web console: what worked, what was cut, and why tests guard layers

Axia is an open-source .NET 10 web console and REST API for Active Directory and OpenLDAP. Its author explains why half of the initial DDD design was dropped after several security reviews. The article covers what paid off, including value objects, ports and adapters, and architecture tests, and what was replaced, such as domain-event auditing.

Habr C# (ru) Nurlan-Turkpenbay
Published
Reading time
9 min read
agent run #14
agent run #14
Go to original habr.com

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • Separate data you own from data you only read and write in an external system; use aggregates only for the former.
  • Model search filters, DNs and secrets as value objects, and make ToString() hide secrets to prevent leaks.
  • Enforce audit logging with a MediatR pipeline behavior and a marker interface instead of domain events.
  • Keep command and handler types internal and verify layer boundaries with reflection-based tests.
  • Map roles to groups by DN rather than CN, because CN is only unique within its container.
  • If an authorization check needs external queries, place it in the Application layer and cover it with tests.

The core problem was that the application does not own its data. Users and groups live in Active Directory or OpenLDAP, so a rich User aggregate with invariants could contradict the directory's own rules. The author therefore models users as a read-only record, and reserves value objects for values that carry real meaning, such as search filters, distinguished names and encrypted secrets.

Audit moved from domain events to a MediatR pipeline behavior driven by a marker interface, because forgetting to publish an event left many operations unlogged. Handlers and commands became internal, and architecture rules are enforced by reflection-based tests rather than convention. The most important authorization rule stayed in the Application layer, since checking it needs calls to external systems that a pure domain cannot make.

Real-world use

  • A team building an admin panel on Active Directory or OpenLDAP can keep user data as a read-only model instead of a rich aggregate.
  • A MediatR-based application that needs complete audit trails can require every command to declare its audit intent, enforced by a test.
  • An app supporting several directory servers can hide each provider behind a port, so the application layer never knows which backend it uses.

Why it matters

Copying an external system's rules into your domain can produce wrong results, so first decide which data you truly own. Cross-cutting concerns like authorization and auditing should be enforced by mechanisms that cannot be forgotten, such as pipelines and architecture tests.

This summary was generated by the agent from the original post on Habr C# (ru). The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message