Bug 22132: Add Basic authentication to the API

This patch implements Basic authentication for the API to aid testers
and developers with tools like Postman.

To test:
- Apply this patches
- Run:
  $ kshell
 k$ prove t/db_dependent/api/v1/auth_basic.t
=> SUCCESS: Tests pass!
- Open Postman or your favourite tool
- In Authorization, choose Basic auth.
- Enter the username and password of a known privileged user.
- Hit an endpoint with Postman, for example:
  ] GET http://kohadev-intra.myDNSname.org:8081/api/v1/patrons
=> SUCCESS: Basic authentication is great!
- Sign off :-D

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
This commit is contained in:
Tomás Cohen Arazi 2019-01-15 13:23:23 -03:00 committed by Nick Clemens
parent 103670e726
commit 26af040c79

View file

@ -19,7 +19,7 @@ package Koha::REST::V1::Auth;
use Mojo::Base 'Mojolicious::Controller';
use C4::Auth qw( check_cookie_auth get_session haspermission );
use C4::Auth qw( check_cookie_auth checkpw_internal get_session haspermission );
use C4::Context;
use Koha::ApiKeys;
@ -35,6 +35,7 @@ use Koha::Exceptions;
use Koha::Exceptions::Authentication;
use Koha::Exceptions::Authorization;
use MIME::Base64;
use Module::Load::Conditional;
use Scalar::Util qw( blessed );
use Try::Tiny;
@ -87,7 +88,7 @@ sub under {
return $c->render(status => 401, json => { error => $_->error });
}
elsif ($_->isa('Koha::Exceptions::Authentication')) {
return $c->render(status => 500, json => { error => $_->error });
return $c->render(status => 401, json => { error => $_->error });
}
elsif ($_->isa('Koha::Exceptions::BadParameter')) {
return $c->render(status => 400, json => $_->error );
@ -163,6 +164,21 @@ sub authenticate_api_request {
);
}
}
elsif ( $authorization_header and $authorization_header =~ /^Basic / ) {
unless ( C4::Context->preference('RESTBasicAuth') ) {
Koha::Exceptions::Authentication::Required->throw(
error => 'Basic authentication disabled'
);
}
$user = $c->_basic_auth( $authorization_header );
unless ( $user ) {
# If we have "Authorization: Basic" header and authentication
# failed, do not try other authentication means
Koha::Exceptions::Authentication::Required->throw(
error => 'Authentication failure.'
);
}
}
else {
my $cookie = $c->cookie('CGISESSID');
@ -402,4 +418,30 @@ sub _object_ownership_by_reserve_id {
return $reserve && $user->borrowernumber == $reserve->borrowernumber;
}
=head3 _basic_auth
Internal method that performs Basic authentication.
=cut
sub _basic_auth {
my ( $c, $authorization_header ) = @_;
my ( $type, $credentials ) = split / /, $authorization_header;
unless ($credentials) {
Koha::Exceptions::Authentication::Required->throw( error => 'Authentication failure.' );
}
my $decoded_credentials = decode_base64( $credentials );
my ( $user_id, $password ) = split( /:/, $decoded_credentials, 2 );
my $dbh = C4::Context->dbh;
unless ( checkpw_internal($dbh, $user_id, $password ) ) {
Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Invalid password' );
}
return Koha::Patrons->find({ userid => $user_id });
}
1;