I'm looking into crafting an app with DDD+CQRS+EventSourcing, and I have some trouble figuring out how to do user auth.
Users are intrinsically part of my domain, as they are responsible for clients. I'm using ASP.NET MVC 4, and I was looking to just use the SimpleMembership. Since logging in and authorising users is a synchronous operation, how is this tackled in an eventually consistent architecture?
Will I have to roll my own auth system where I keep denormalized auth tables on the read side? How to handle the security of this? Will I end up storing password hashes in both my event store and my view tables?
So many questions, if anyone can shed some light, I would be very thankful :)
tldr; How do you do User Auth in EventSource-applications?
Not every "Domain" or business component has to use DDD or CQRS. In most cases, user information is really cruddy, so you can usually not use DDD for that. Other domains don't really depend on the actual user. There's usually a correlation id (UserId) that gets shared by the various domains.
If using messaging in your system, one option is to register and manage users without CQRS, then send a command (RegisterUser { UserId } ). This would publish an event User Registered. Other domains can listen to this event to kick-off any workflows or ARs that are needed.
For our MVC CQRS app, we originally started off keeping all the user related information in the domain, and, like somebody mentioned, there was a RegisterUserCommand and a UserRegisteredEvent. After storing the user information in the domain, that event got published and picked up on the read side, which also created a user and generated all the password hashes, etc. We then done the authentication on the read side: the controller would make a call out to a 'read model authentication service' to authenticate against.
Later on down the road, we ended up completely refactoring this. It turned out that we needed access to the user related information to build in security for authorising our commands, which we done on the command processing side (our app is a distributed app that sends 'fire and forget' asynchronous commands to a queue, with an autonomous listener on the other side). The security component then needed a reference to our domain to go and get the user profile, which led to cumbersome referencing issues.
We decided to put the user security stuff into a separate database that we considered to be more of a central component, rather than belonging to the domain or read model. We still maintain user profile related information in the domain and read models (e.g. job title, twitter account URL etc.), but all the security related stuff, like password hashes, are stored in this central database. That's then accessible with a service, that's available to both MVC and the command authoriser.
We didn't actually have to change anything in the UI for this refactor, as we just called the service to register the users from the register user command handler. If you're going to do it that way, you need to be careful here to make your user service related operations idempotent. This is so that you can give your commands the opportunity to be retried without side effects, because you're updating 2 sources of information (the ES and the user database).
Finally, you could of course use the membership providers for this central component, but there can be pitfalls with that. We ended up just writing our own - it's pretty simple to do. That article links to this, which provides a good example of how to implement it.
You should consider creating separate entities like: visitor (just visited your site), user (registered), customer (bought something), etc. Try to split your system in this way, even if it causes a little bit of data redundancy. Disk space is not an issue but ability to modify different components of the system independently is usually very critical.
People create denormalized auth tables only for the purpose of scaling and only if your auth read side is a performance bottleneck. If not - usual 3rd normal form is a way to go.
In SimpleMembership scenario all tables created by SimpleMembership can be viewed as snapshot of "user" aggregate. And yes, they will duplicate some data in your event store.
You may have events like: UserCreated, UserUpdated, UserAssignedToRole, etc.
And don't be tricked by the name of that membership provider. It's not so simple and usually has lots of things that you can easily live without (depends on your domain). So, maybe you can use something like this: https://gist.github.com/Kayli/fe73769f19fdff40c3a7