Bug 20624: (QA follow-up) Handle missing deps gracefuly
[srvgit] / Koha / REST / V1 / Auth.pm
index 77864eb..b2ccd6b 100644 (file)
@@ -22,10 +22,14 @@ use Modern::Perl;
 use Mojo::Base 'Mojolicious::Controller';
 
 use C4::Auth qw( check_cookie_auth get_session haspermission );
+use C4::Context;
 
+use Koha::ApiKeys;
 use Koha::Account::Lines;
 use Koha::Checkouts;
 use Koha::Holds;
+use Koha::OAuth;
+use Koha::OAuthAccessTokens;
 use Koha::Old::Checkouts;
 use Koha::Patrons;
 
@@ -33,6 +37,7 @@ use Koha::Exceptions;
 use Koha::Exceptions::Authentication;
 use Koha::Exceptions::Authorization;
 
+use Module::Load::Conditional;
 use Scalar::Util qw( blessed );
 use Try::Tiny;
 
@@ -110,6 +115,55 @@ sub authenticate_api_request {
 
     my $spec = $c->match->endpoint->pattern->defaults->{'openapi.op_spec'};
     my $authorization = $spec->{'x-koha-authorization'};
+
+    my $authorization_header = $c->req->headers->authorization;
+
+    if ($authorization_header and $authorization_header =~ /^Bearer /) {
+        # attempt to use OAuth2 authentication
+        if ( ! Module::Load::Conditional::can_load('Net::OAuth2::AuthorizationServer') ) {
+            Koha::Exceptions::Authorization::Unauthorized->throw(
+                error => 'Authentication failure.'
+            );
+        }
+        else {
+            require Net::OAuth2::AuthorizationServer;
+        }
+
+        my $server = Net::OAuth2::AuthorizationServer->new;
+        my $grant = $server->client_credentials_grant(Koha::OAuth::config);
+        my ($type, $token) = split / /, $authorization_header;
+        my ($valid_token, $error) = $grant->verify_access_token(
+            access_token => $token,
+        );
+
+        if ($valid_token) {
+            my $patron_id   = Koha::ApiKeys->find( $valid_token->{client_id} )->patron_id;
+            my $patron      = Koha::Patrons->find($patron_id);
+            my $permissions = $authorization->{'permissions'};
+            # Check if the patron is authorized
+            if ( haspermission($patron->userid, $permissions)
+                or allow_owner($c, $authorization, $patron)
+                or allow_guarantor($c, $authorization, $patron) ) {
+
+                validate_query_parameters( $c, $spec );
+
+                # Everything is ok
+                return 1;
+            }
+
+            Koha::Exceptions::Authorization::Unauthorized->throw(
+                error => "Authorization failure. Missing required permission(s).",
+                required_permissions => $permissions,
+            );
+        }
+
+        # If we have "Authorization: Bearer" header and oauth authentication
+        # failed, do not try other authentication means
+        Koha::Exceptions::Authentication::Required->throw(
+            error => 'Authentication failure.'
+        );
+    }
+
     my $cookie = $c->cookie('CGISESSID');
     my ($session, $user);
     # Mojo doesn't use %ENV the way CGI apps do
@@ -254,7 +308,8 @@ sub check_object_ownership {
 
     my $parameters = {
         accountlines_id => \&_object_ownership_by_accountlines_id,
-        borrowernumber  => \&_object_ownership_by_borrowernumber,
+        borrowernumber  => \&_object_ownership_by_patron_id,
+        patron_id       => \&_object_ownership_by_patron_id,
         checkout_id     => \&_object_ownership_by_checkout_id,
         reserve_id      => \&_object_ownership_by_reserve_id,
     };
@@ -296,10 +351,10 @@ Compares C<$borrowernumber> to currently logged in C<$user>.
 
 =cut
 
-sub _object_ownership_by_borrowernumber {
-    my ($c, $user, $borrowernumber) = @_;
+sub _object_ownership_by_patron_id {
+    my ($c, $user, $patron_id) = @_;
 
-    return $user->borrowernumber == $borrowernumber;
+    return $user->borrowernumber == $patron_id;
 }
 
 =head3 _object_ownership_by_checkout_id