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:
parent
73769c132a
commit
5c8ab4f590
4 changed files with 217 additions and 0 deletions
|
@ -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;
|
||||
|
|
135
Koha/REST/V1/OAuth/Client.pm
Normal file
135
Koha/REST/V1/OAuth/Client.pm
Normal 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;
|
67
api/v1/swagger/paths/public_oauth.yaml
Normal file
67
api/v1/swagger/paths/public_oauth.yaml
Normal 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"
|
|
@ -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":
|
||||
|
|
Loading…
Reference in a new issue