diff --git a/Makefile.PL b/Makefile.PL index 8912d15..fe83f62 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -11,6 +11,8 @@ WriteMakefile( 'Mojo::Pg' => '4.27', 'Mojo::SQLite' => '3.009', 'Crypt::Random' => '1.25', + 'Crypt::Argon2' => '0.013', + 'Bytes::Random::Secure' => '0.29', 'Number::Bytes::Human' => '0.11', }, test => {TESTS => 't/*.t'} diff --git a/lib/IpfsUpload.pm b/lib/IpfsUpload.pm index 663fe5a..308c672 100644 --- a/lib/IpfsUpload.pm +++ b/lib/IpfsUpload.pm @@ -37,6 +37,11 @@ sub startup($self) { die "Database type is not supported"; } + my @auths = qw/ldap db/; + my $auth = $config->{auth}; + if (not grep $_ eq $auth, @auths) { + die "Auth type is not supported"; + } $self->helper(sql => sub ($app) { if ($dbtype eq "postgres") { diff --git a/lib/IpfsUpload/Controller/Login.pm b/lib/IpfsUpload/Controller/Login.pm index 69aeef6..b668051 100644 --- a/lib/IpfsUpload/Controller/Login.pm +++ b/lib/IpfsUpload/Controller/Login.pm @@ -21,24 +21,44 @@ sub auth($c) { my $config = $c->config; - my $connStr = $config->{'ldap'}->{'uri'}; - my $bindDN = $config->{'ldap'}->{'dnBase'}; - $bindDN =~ s/%u/$username/; + if ($config->{auth} eq 'ldap') { + my $connStr = $config->{'ldap'}->{'uri'}; + my $bindDN = $config->{'ldap'}->{'dnBase'}; + $bindDN =~ s/%u/$username/; - return Mojo::IOLoop->subprocess->run_p(sub { - my $ldap= Net::LDAPS->new($connStr, verify=>'none', version=>3) or die "$@"; - my $mesg = $ldap->bind($bindDN, password=>$password); - $mesg->code and die $mesg->error; - })->then(sub ($res) { - return $c->users->getOrMake($username); - })->then(sub ($res) { - $c->session->{uid} = $res; - $c->flash(msg => "Logged in."); - $c->redirect_to('/my'); - })->catch(sub ($err) { - $c->flash(msg => "Login failed."); - $c->redirect_to('/login'); - }); + return Mojo::IOLoop->subprocess->run_p(sub { + my $ldap= Net::LDAPS->new($connStr, verify=>'none', version=>3) or die "$@"; + my $mesg = $ldap->bind($bindDN, password=>$password); + $mesg->code and die $mesg->error; + })->then(sub ($res) { + return $c->users->getOrMake($username); + })->then(sub ($res) { + $c->session->{uid} = $res; + $c->flash(msg => "Logged in."); + $c->redirect_to('/my'); + })->catch(sub ($err) { + $c->flash(msg => "Login failed."); + $c->redirect_to('/login'); + }); + } elsif ($config->{auth} eq 'db') { + return $c->users->get($username)->then(sub ($uid) { + if (!defined $uid) { + $c->flash(msg => "Login failed."); + return $c->redirect_to('/login'); + } + return $c->users->get_pass_hash($uid)->then(sub ($hash) { + if (IpfsUpload::Util::check_pass($password, $hash)) { + $c->session->{uid} = $uid; + $c->flash(msg => "Logged in."); + return $c->redirect_to('/my'); + } + die "Login failed."; + }); + })->catch(sub ($err) { + $c->flash(msg => "Login failed."); + $c->redirect_to('/login'); + }); + } } sub login($c) { diff --git a/lib/IpfsUpload/Model/Users.pm b/lib/IpfsUpload/Model/Users.pm index cc6d99d..d6ec102 100644 --- a/lib/IpfsUpload/Model/Users.pm +++ b/lib/IpfsUpload/Model/Users.pm @@ -69,4 +69,20 @@ sub getOrMake($self, $username) { }); } +sub get($self, $username) { + return $self->sql->db->select_p('users', ['uid'], {username => $username})->then(sub ($res) { + my $val = $res->hash; + if (defined $val) { + return $val->{uid}; + } + return undef; + }); +} + +sub get_pass_hash($self, $uid) { + return $self->sql->db->select_p('users', ['pass'], {uid => $uid})->then(sub ($res) { + return $res->hash->{pass}; + }); +} + 1; diff --git a/lib/IpfsUpload/Util.pm b/lib/IpfsUpload/Util.pm index 4a01333..fcbea80 100644 --- a/lib/IpfsUpload/Util.pm +++ b/lib/IpfsUpload/Util.pm @@ -6,6 +6,18 @@ use experimental qw/signatures/; use Mojo::JSON qw/decode_json encode_json/; use Time::Piece; +use Crypt::Argon2 qw/argon2id_pass argon2id_verify/; +use Bytes::Random::Secure qw/random_bytes_hex/; + +sub add_pass($pass) { + my $salt = random_bytes_hex(16); + my $encoded = argon2id_pass($pass, $salt, '32M', 1, 16); + return $encoded; +} + +sub check_pass($pass, $hash) { + return argon2id_verify($hash, $pass); +} sub date_format($date) { $date =~ s/ /T/; diff --git a/schema/dbauth.psql b/schema/dbauth.psql new file mode 100644 index 0000000..ccb42a7 --- /dev/null +++ b/schema/dbauth.psql @@ -0,0 +1 @@ +ALTER TABLE users ADD pass varchar(512); diff --git a/schema/dbauth.sql b/schema/dbauth.sql new file mode 100644 index 0000000..1e292c8 --- /dev/null +++ b/schema/dbauth.sql @@ -0,0 +1 @@ +alter table users add pass text;