Generating passwords in an application that uses event sourcing

726 views
Skip to first unread message

Vytautas Mackonis

unread,
Feb 20, 2012, 3:35:59 PM2/20/12
to DDD/CQRS
Hi,
I have a very simple and common usecase I'm struggling with. When a
system user is created we need to send an email to him with his login
credentials. In a standard application (one without event sourcing) we
generate a password, we send an email, we hash the value and persist
it. The creator of the user does not know the password and the system
does not store it in a non-hashed form. This way the privacy of the
user is preserved. How is it possible to achieve a similar behavior in
an application that is using event sourcing?

If we publish an event with a prehashed password, we will be unable to
send an email - the event handler will only get a hash. If we publish
an event with a non-hashed password, we will store the non-hashed
version of the password in our event stream. We can, of course,
encrypt the password in the event but this only sweeps the breach of
privacy under the rug.

I can see 2 possible options:

1. Raise an event with hashed password and send the email with non-
hashed password after event is raised inside the same aggregate
method. This will be reliable enough so that if the email does not get
sent for some reason, the command will be retried a few more times.
2. Have a UserCreated event handler generate a password, send a
SetPasswordHash command and an email right after. Again, the event
would get retried a few times if email sending fails.

If we use option 1, we leak things like email sending into the domain.
If we use option 2, we have a "dummy" command that is not part of
ubiquitous language. Both feel like a hack to me and differ only by
whether we actually want the user to get created if email sending
fails or not. Are there any other options before I pick one?

@yreynhout

unread,
Feb 20, 2012, 4:05:36 PM2/20/12
to DDD/CQRS
I have another idea, let's not build another user management system,
for which there are more secure off the shelf solutions than you can
author yourself. Sarcasm aside, there's an answer to this question,
but I've had it with username/password examples(nothing personal). I
do hope you have at least considered an off the shelf solution.

On 20 feb, 21:35, Vytautas Mackonis <vytautas.macko...@gmail.com>
wrote:

Vytautas Mackonis

unread,
Feb 20, 2012, 4:42:44 PM2/20/12
to DDD/CQRS
Hi,

If I:
a) Have an aggregate that models a real world person
b) There are a bunch of things you can do with that aggregate
c) The person being modeled can also log in to the system and do other
things
d) I have only a small part of data (including password) that domain
does not care about in this BC

Why do i have to overcomplicate things by adding an off-the shelf
solution just for the password? Im pretty sure it is not a trivial
task to make an eventsourced application "behave nicely" with a common
off the shelf solution, taking into account that i might need to
rebuild everything from my event store.

Nils Kilden-Pedersen

unread,
Feb 20, 2012, 5:02:27 PM2/20/12
to ddd...@googlegroups.com
On Mon, Feb 20, 2012 at 2:35 PM, Vytautas Mackonis <vytautas...@gmail.com> wrote:
Hi,
I have a very simple and common usecase I'm struggling with. When a
system user is created we need to send an email to him with his login
credentials. In a standard application (one without event sourcing) we
generate a password, we send an email, we hash the value and persist
it. The creator of the user does not know the password and the system
does not store it in a non-hashed form. This way the privacy of the
user is preserved. How is it possible to achieve a similar behavior in
an application that is using event sourcing?

Exact same way as if not using ES.
 
If we publish an event with a prehashed password, we will be unable to
send an email - the event handler will only get a hash. If we publish
an event with a non-hashed password, we will store the non-hashed
version of the password in our event stream. We can, of course,
encrypt the password in the event but this only sweeps the breach of
privacy under the rug.

I can see 2 possible options:

1. Raise an event with hashed password and send the email with non-
hashed password after event is raised inside the same aggregate
method. This will be reliable enough so that if the email does not get
sent for some reason, the command will be retried a few more times.
2. Have a UserCreated event handler generate a password, send a
SetPasswordHash command and an email right after. Again, the event
would get retried a few times if email sending fails.

If we use option 1, we leak things like email sending into the domain.
If we use option 2, we have a "dummy" command that is not part of
ubiquitous language. Both feel like a hack to me and differ only by
whether we actually want the user to get created if email sending
fails or not. Are there any other options before I pick one?

Is this a trusted environment or not? It seems to me that if it's trusted, then it shouldn't matter if the generated password (temporary presumably) is present in some events. And if not trusted, you probably shouldn't be emailing a password to begin with.

Vytautas Mackonis

unread,
Feb 20, 2012, 5:07:07 PM2/20/12
to DDD/CQRS
If the password is in an event, it is not temporary. The issue here is
not secure/insecure environment. It is more of a legal/company policy
issue that unhashed passwords should be transient. They are not
transient if they sit in event store....

On Feb 21, 12:02 am, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
> On Mon, Feb 20, 2012 at 2:35 PM, Vytautas Mackonis <
>

Nils Kilden-Pedersen

unread,
Feb 20, 2012, 5:22:36 PM2/20/12
to ddd...@googlegroups.com
On Mon, Feb 20, 2012 at 4:07 PM, Vytautas Mackonis <vytautas...@gmail.com> wrote:
If the password is in an event, it is not temporary. The issue here is
not secure/insecure environment. It is more of a legal/company policy
issue that unhashed passwords should be transient. They are not
transient if they sit in event store....

Now we're talking semantics at a level that's unclear to me. Let's be clear on these things:
  • When you email a password out, that password is probably stored in email server logs (in some industries, a regulatory requirement). This is no different than an event store holding a password.
  • If the user is prompted to change the password and that password is never put into an email or an event, then I consider the previously generated password to be temporary and transient.

Vytautas Mackonis

unread,
Feb 20, 2012, 5:38:28 PM2/20/12
to DDD/CQRS
Hi,
Regarding point 1, that is only valid if the company has access to
email server logs. Some companies don't have inhouse email servers
(nor other logs regarding email).
Regarding point 2 - thanks, ill bring this on my table next time and
hopefully that'll keep my domain clean :)

On Feb 21, 12:22 am, Nils Kilden-Pedersen <nil...@gmail.com> wrote:
> On Mon, Feb 20, 2012 at 4:07 PM, Vytautas Mackonis <
>
> vytautas.macko...@gmail.com> wrote:
> > If the password is in an event, it is not temporary. The issue here is
> > not secure/insecure environment. It is more of a legal/company policy
> > issue that unhashed passwords should be transient. They are not
> > transient if they sit in event store....
>
> Now we're talking semantics at a level that's unclear to me. Let's be clear
> on these things:
>
>    - When you email a password out, that password is probably stored in
>    email server logs (in some industries, a regulatory requirement). This is
>    no different than an event store holding a password.
>    - If the user is prompted to change the password and that password is

Joseph Daigle

unread,
Feb 20, 2012, 8:39:44 PM2/20/12
to ddd...@googlegroups.com
I would say don't use event sourcing. I've never seen a user management system built that way, I can't think of how you would benefit. I wouldn't even use apply CQRS principals for much of it as it just adds unneeded complexity.

Julian Dominguez

unread,
Feb 20, 2012, 9:35:51 PM2/20/12
to ddd...@googlegroups.com
I agree with this comment. CQRS/ES should not be used as an
all-or-nothing (top level) architecture. Implement this particular
part of the code without using ES.
Nevertheless, I also agree that if you are worried about storing the
password in your own event store (which you can easily secure), it is
even worse that it is sent in an e-mail, so just deal with that at the
business level, and force the user to change the password in the first
login. This way it does not matter at all if the temporary password
was sitting in the event store for a while.

Alexey Raga

unread,
Feb 20, 2012, 9:57:49 PM2/20/12
to DDD/CQRS
@Vytautas

When a system is creating a user it publishes an event "UserCreated".
This UserCreated event can be handled by some "ResetPassword" saga
object which is using some PasswordGenerator component to generate a
random password and a hash.
The saga issues two commands: "SetUserPassword(hashedPassword)" and
"SendNewPasswordByEmail(plainPassword)".

As a result of handling the "SetUserPassword" command the hashed
password is stored "somewhere in the event storage", but when handling
the "SendNewPasswordByEmail" you don't publish the event that contains
the plain password, you simply send it to user and forget about it.
Even if you publish an event like "PasswordSentToUser" (I have no idea
why would you do that, maybe for some statistical reasons), you simply
not include the plain password there.

This saga can be used for "Forgot Password" functionality and for any
other business aspects when user's password needs to be reset.

It is just from the top of my head, maybe you can just use a domain
service instead of a saga...

Cheers,
Alexey.


On Feb 21, 7:35 am, Vytautas Mackonis <vytautas.macko...@gmail.com>
wrote:

Paco Wensveen

unread,
Feb 21, 2012, 8:36:39 AM2/21/12
to ddd...@googlegroups.com
A different way:
Mail a password ticket to the user and let the user pick a password.

Passwords shouldn't be mailed, or should be immediately changed after
receiving it by mail if you want to be secure.

Nuno Lopes

unread,
Feb 22, 2012, 5:47:05 AM2/22/12
to ddd...@googlegroups.com
Hi,

This way the privacy of the user is preserved

Clear password in an email? Are you serious?

If you are talking about securely storing and sending events there are solutions for that. It's not different then encrypting / decrypting peaces of data.

Nuno
Reply all
Reply to author
Forward
0 new messages