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
};
};
+ 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;
--- /dev/null
+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;
--- /dev/null
+"/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"