added abstraction layer for password hashing

This commit is contained in:
Johannes Loher 2017-10-27 18:58:46 +02:00
parent 0143b933d5
commit ec0c7a64b5
4 changed files with 40 additions and 9 deletions

View file

@ -1,5 +1,7 @@
module calendarwebapp.authenticator;
import calendarwebapp.passhash : PasswordHasher;
import poodinis;
import std.range : InputRange;
@ -21,6 +23,7 @@ class MongoDBAuthenticator(Collection = MongoCollection) : Authenticator
private:
@Value("users")
Collection users;
@Autowire PasswordHasher passwordHasher;
public:
Nullable!AuthInfo checkUser(string username, string password) @safe
@ -28,13 +31,13 @@ public:
import botan.passhash.bcrypt : checkBcrypt;
auto result = users.findOne(["username" : username]);
/* checkBcrypt should be called using vibe.core.concurrency.async to
/* checkHash should be called using vibe.core.concurrency.async to
avoid blocking, but https://github.com/vibe-d/vibe.d/issues/1521 is
blocking this */
if (result != Bson(null))
{
auto authInfo = result.deserializeBson!AuthInfo;
if ((()@trusted => checkBcrypt(password, authInfo.passwordHash))())
if (passwordHasher.checkHash(password, authInfo.passwordHash))
{
return authInfo.nullable;
}

View file

@ -1,9 +1,8 @@
module calendarwebapp.calendarwebapp;
import botan.rng.rng : RandomNumberGenerator;
import calendarwebapp.authenticator;
import calendarwebapp.event;
import calendarwebapp.passhash : PasswordHasher;
import core.time : days;
@ -108,12 +107,10 @@ public:
}
@auth(Role.admin) @errorDisplay!getCreateuser void postCreateuser(string username,
string password, Privilege role)
string password, Privilege role) @safe
{
import botan.passhash.bcrypt;
authenticator.addUser(AuthInfo(BsonObjectID.generate, username,
generateBcrypt(password, rng, 10), role));
passwordHasher.generateHash(password), role));
redirect("/users");
}
@ -129,5 +126,5 @@ private:
@Autowire EventStore eventStore;
@Autowire Authenticator authenticator;
@Autowire RandomNumberGenerator rng;
@Autowire PasswordHasher passwordHasher;
}

View file

@ -6,6 +6,7 @@ import botan.rng.rng : RandomNumberGenerator;
import calendarwebapp.authenticator : Authenticator, MongoDBAuthenticator;
import calendarwebapp.calendarwebapp : CalendarWebapp;
import calendarwebapp.event : EventStore, MongoDBEventStore;
import calendarwebapp.passhash : BcryptPasswordHasher, PasswordHasher;
import poodinis;
@ -22,6 +23,7 @@ public:
container.register!MongoClient.existingInstance(mongoClient);
container.register!(EventStore, MongoDBEventStore!());
container.register!(Authenticator, MongoDBAuthenticator!());
container.register!(PasswordHasher, BcryptPasswordHasher);
container.register!(RandomNumberGenerator, AutoSeededRNG);
container.register!CalendarWebapp;
container.register!(ValueInjector!string, StringInjector);

View file

@ -0,0 +1,29 @@
module calendarwebapp.passhash;
import poodinis;
interface PasswordHasher
{
string generateHash(in string password) @safe;
bool checkHash(in string password, in string hash) @safe;
}
class BcryptPasswordHasher : PasswordHasher
{
import botan.passhash.bcrypt : checkBcrypt, generateBcrypt;
import botan.rng.rng : RandomNumberGenerator;
string generateHash(in string password) @safe
{
return (() @trusted => generateBcrypt(password, rng, cost))();
}
bool checkHash(in string password, in string hash) @safe
{
return (()@trusted => checkBcrypt(password, hash))();
}
private:
@Autowire RandomNumberGenerator rng;
enum cost = 10;
}