1

I'm designing a simple user login/register program with user login/register and a repository. The passwords for users should be encrypted when stored but I don't know where to put the encryption step either on the repository or in the service that handles the logic for registering/login in a user. the user passwords should always be encrypted and for that reason I think it is better to have this logic in the repository as it is the class that will be called every time I want to do something with a user. Putting the encryption logic on the service mean that every service that wants to do something with a user must be aware of the encryption logic.

On the other side, I don't know if the repository should be aware of this logic.

Or maybe it is worth creating a value object "UserPassword" that receives the raw password and a cypher as constructor parameters and it immediately saves the encrypted password for future retrieval?

I'm trying to design an hexagonal architecture. (Don't know if this may help)

2
  • If you're using hexagonal architecture, I'd argue that only one thing should ever know about how password encryption is handled (which I'm sure is going to be a salted hash, right?). Putting it in a service makes perfect sense to me.
    – mgw854
    Apr 26, 2016 at 13:04
  • Do you expect any other component informing user passwords beside your Service ? If there's only one way to add encripted passwords and it goes trhough Service * then it's ok placing the encryption at service Layer. Remember that Repository/DAO should be *agnostics they dont know and they don't want to know what data means or comes from. They are only in charge of persist and recover it. I would keep repositories simples. To delegate encryption to a service is ok. Some DB supports encrypted types also so you delegate such feature to the DB. Depends on your requirements
    – Laiv
    Apr 26, 2016 at 13:20

3 Answers 3

1

Repositories generally shouldn't be involved in encryption unless it's a feature of the persistence-layer, so unless you're asking the database to do encryption/hashing or using some very interesting queries, I'd use a separate service.

It splits up responsibility. Create a service, and if necessary you inject the Service into the Repository as a dependency. As a bonus, this makes it easier to make sure that sensitive information (e.g. encryption keys or global salts) go only to one place and don't leak into other areas of the application.

3
  • I'd go the other way around, injecting the repository into the service. Why should a repository, which is generally considered to be quite coupled with data, know anything about my service layer.
    – Andy
    Apr 26, 2016 at 20:42
  • I think Ideally the service should modify the domain object and then the modified object is passed to the repository, and neither know about the other. I just wanted to point out that injection was a better alternative than putting the hashing/encryption logic directly in the repo.
    – Darien
    Apr 26, 2016 at 21:27
  • Even in that case it's the service who knows about the repository (which retrieves and persists domain objects), not the other way around, afaik. Service taking TRepository and EncryptionInterface as dependencies. Good point though, repository should have no knowledge about encryption itself.
    – Andy
    Apr 26, 2016 at 21:37
1

Does implementing hashing that difficult in the language/framework you use, so that it would justify a separate dedicated service?

What I mean is that, for instance, in Python, it's just three lines of code. In C#, it looks much more complicated, but still not enough in my opinion to have a separate service for that. One interface, one implementation class, one or several stubs/mocks and all the dependency injection logic looks like an overkill for a simple task.

When it comes to unit tests, getting rid of this specific dependency by embedding the hashing directly in the class which manages the user doesn't seem nonsense either. Unit tests will have to compare the output password not to the raw password from the stub, but to a specific hash. This is not that hard, since you can generate a hash with ease anyway (and doing it with a different language helps you to ensure that your code is actually doing it right).

It could make sense to have a separate service in a situation where you need to swap the hashing implementations on regular basis. I've never worked on a project which would require that.

Aside this specific case, a dedicated service is an overkill. Don't over-engineer your code.

1

Your Business Layer is the place where the encryption should happen. Repositories should only concern with data retrieval and storage.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.