Bug 31378: Add API routes

Signed-off-by: Lukasz Koszyk <lukasz.koszyk@kit.edu>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
Agustin Moyano 2022-08-18 16:42:10 -03:00 committed by Tomas Cohen Arazi
parent 73769c132a
commit 5c8ab4f590
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
4 changed files with 217 additions and 0 deletions

View file

@ -21,10 +21,13 @@ use Mojo::Base 'Mojolicious';
use C4::Context;
use Koha::Logger;
use Koha::Auth::Providers;
use Mojolicious::Plugin::OAuth2;
use JSON::Validator::Schema::OpenAPIv2;
use Try::Tiny qw( catch try );
use JSON qw( decode_json );
=head1 NAME
@ -136,10 +139,20 @@ sub startup {
};
};
my $oauth_configuration = {};
my $search_options = { protocol => [ "OIDC", "OAuth" ] };
my $providers = Koha::Auth::Providers->search( $search_options );
while(my $provider = $providers->next) {
$oauth_configuration->{$provider->code} = decode_json($provider->config);
}
$self->plugin( 'Koha::REST::Plugin::Pagination' );
$self->plugin( 'Koha::REST::Plugin::Query' );
$self->plugin( 'Koha::REST::Plugin::Objects' );
$self->plugin( 'Koha::REST::Plugin::Exceptions' );
$self->plugin( 'Koha::REST::Plugin::Auth' );
$self->plugin( 'Mojolicious::Plugin::OAuth2' => $oauth_configuration );
}
1;

View file

@ -0,0 +1,135 @@
package Koha::REST::V1::OAuth::Client;
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use Koha::Auth::Client::OAuth;
use Mojo::Base 'Mojolicious::Controller';
use Mojo::URL;
use Scalar::Util qw(blessed);
use Try::Tiny;
use Koha::Logger;
use URI::Escape qw(uri_escape_utf8);
=head1 NAME
Koha::REST::V1::OAuth::Client - Controller library for handling OAuth2-related login attempts
=head1 API
=head2 Methods
=head3 login
Controller method handling login requests
=cut
sub login {
my $c = shift->openapi->valid_input or return;
my $provider = $c->validation->param('provider_code');
my $interface = $c->validation->param('interface');
my $logger = Koha::Logger->get({ interface => 'api' });
my $provider_config = $c->oauth2->providers->{$provider};
unless ( $provider_config ) {
return $c->render(
status => 404,
openapi => {
error => 'Object not found',
error_code => 'not_found',
}
);
}
unless ( $provider_config->{authorize_url} =~ /response_type=code/ ) {
my $authorize_url = Mojo::URL->new($provider_config->{authorize_url});
$authorize_url->query->append(response_type => 'code');
$provider_config->{authorize_url} = $authorize_url->to_string;
}
my $uri;
if ( $interface eq 'opac' ) {
if ( C4::Context->preference('OpacPublic') ) {
$uri = '/cgi-bin/koha/opac-user.pl';
} else {
$uri = '/cgi-bin/koha/opac-main.pl';
}
} else {
$uri = '/cgi-bin/koha/mainpage.pl';
}
return $c->oauth2->get_token_p($provider)->then(
sub {
return unless my $response = shift;
my ( $patron, $mapped_data, $domain ) = Koha::Auth::Client::OAuth->new->get_user(
{ provider => $provider,
data => $response,
interface => $interface,
config => $c->oauth2->providers->{$provider}
}
);
try {
# FIXME: We could check if the backend allows registering
if ( !$patron ) {
$patron = $c->auth->register(
{
data => $mapped_data,
domain => $domain,
interface => $interface
}
);
}
my ( $status, $cookie, $session_id ) = $c->auth->session($patron);
$c->cookie( CGISESSID => $session_id, { path => "/" } );
$c->redirect_to($uri);
} catch {
my $error = $_;
$logger->error($error);
# TODO: Review behavior
if ( blessed $error ) {
if ( $error->isa('Koha::Exceptions::Auth::Unauthorized') ) {
$error = "$error";
}
}
$error = uri_escape_utf8($error);
$c->redirect_to($uri."?auth_error=$error");
};
}
)->catch(
sub {
my $error = shift;
$logger->error($error);
$error = uri_escape_utf8($error);
$c->redirect_to($uri."?auth_error=$error");
}
)->wait;
}
1;

View file

@ -0,0 +1,67 @@
"/public/oauth/login/{provider}/{interface}":
get:
x-mojo-to: OAuth::Client#login
operationId: loginOAuthClient
tags:
- oauth
summary: Login to OAuth provider
produces:
- application/json
parameters:
- name: provider
in: path
description: Name of OAuth provider
required: true
type: string
- name: interface
in: path
description: Name of the interface this login is for
required: true
type: string
- name: code
in: query
description: Code returned from OAuth server for Authorization Code grant
required: false
type: string
- name: state
in: query
description: An opaque value used by the client to maintain state between the request and callback. This is the callback part.
required: false
type: string
- name: scope
in: query
description: Scope returned by OAuth server
type: string
- name: prompt
in: query
description: Prompt returned by OAuth server
type: string
- name: authuser
in: query
description: Auth user returned by OAuth server
type: string
- name: error
in: query
description: OAuth error code
type: string
- name: error_description
in: query
description: OAuth error description
type: string
- name: error_uri
in: query
description: Web page with user friendly description of the error
type: string
responses:
"302":
description: User authorized
schema:
type: string
"400":
description: Bad Request
schema:
$ref: "../swagger.yaml#/definitions/error"
"403":
description: Access forbidden
schema:
$ref: "../swagger.yaml#/definitions/error"

View file

@ -269,6 +269,8 @@ paths:
$ref: ./paths/libraries.yaml#/~1public~1libraries
"/public/libraries/{library_id}":
$ref: "./paths/libraries.yaml#/~1public~1libraries~1{library_id}"
"/public/oauth/login/{provider}/{interface}":
$ref: ./paths/public_oauth.yaml#/~1public~1oauth~1login~1{provider}~1{interface}
"/public/patrons/{patron_id}/article_requests/{article_request_id}":
$ref: "./paths/article_requests.yaml#/~1public~1patrons~1{patron_id}~1article_requests~1{article_request_id}"
"/public/patrons/{patron_id}/guarantors/can_see_charges":