View | Details | Raw Unified | Return to bug 31378
Collapse All | Expand All

(-)a/Koha/REST/V1.pm (+13 lines)
Lines 21-30 use Mojo::Base 'Mojolicious'; Link Here
21
21
22
use C4::Context;
22
use C4::Context;
23
use Koha::Logger;
23
use Koha::Logger;
24
use Koha::Auth::Providers;
24
25
26
use Mojolicious::Plugin::OAuth2;
25
use JSON::Validator::Schema::OpenAPIv2;
27
use JSON::Validator::Schema::OpenAPIv2;
26
28
27
use Try::Tiny qw( catch try );
29
use Try::Tiny qw( catch try );
30
use JSON qw( decode_json );
28
31
29
=head1 NAME
32
=head1 NAME
30
33
Lines 136-145 sub startup { Link Here
136
        };
139
        };
137
    };
140
    };
138
141
142
    my $oauth_configuration = {};
143
    my $search_options = { protocol => [ "OIDC", "OAuth" ] };
144
    my $providers = Koha::Auth::Providers->search( $search_options );
145
146
    while(my $provider = $providers->next) {
147
        $oauth_configuration->{$provider->code} = decode_json($provider->config);
148
    }
149
139
    $self->plugin( 'Koha::REST::Plugin::Pagination' );
150
    $self->plugin( 'Koha::REST::Plugin::Pagination' );
140
    $self->plugin( 'Koha::REST::Plugin::Query' );
151
    $self->plugin( 'Koha::REST::Plugin::Query' );
141
    $self->plugin( 'Koha::REST::Plugin::Objects' );
152
    $self->plugin( 'Koha::REST::Plugin::Objects' );
142
    $self->plugin( 'Koha::REST::Plugin::Exceptions' );
153
    $self->plugin( 'Koha::REST::Plugin::Exceptions' );
154
    $self->plugin( 'Koha::REST::Plugin::Auth' );
155
    $self->plugin( 'Mojolicious::Plugin::OAuth2' => $oauth_configuration );
143
}
156
}
144
157
145
1;
158
1;
(-)a/Koha/REST/V1/OAuth/Client.pm (+135 lines)
Line 0 Link Here
1
package Koha::REST::V1::OAuth::Client;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# Koha is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18
use Modern::Perl;
19
20
use Koha::Auth::Client::OAuth;
21
22
use Mojo::Base 'Mojolicious::Controller';
23
use Mojo::URL;
24
use Scalar::Util qw(blessed);
25
use Try::Tiny;
26
use Koha::Logger;
27
use URI::Escape qw(uri_escape_utf8);
28
29
=head1 NAME
30
31
Koha::REST::V1::OAuth::Client - Controller library for handling OAuth2-related login attempts
32
33
=head1 API
34
35
=head2 Methods
36
37
=head3 login
38
39
Controller method handling login requests
40
41
=cut
42
43
sub login {
44
    my $c = shift->openapi->valid_input or return;
45
46
    my $provider  = $c->validation->param('provider_code');
47
    my $interface = $c->validation->param('interface');
48
49
    my $logger = Koha::Logger->get({ interface => 'api' });
50
51
    my $provider_config = $c->oauth2->providers->{$provider};
52
53
    unless ( $provider_config ) {
54
        return $c->render(
55
            status  => 404,
56
            openapi => {
57
                error      => 'Object not found',
58
                error_code => 'not_found',
59
            }
60
        );
61
    }
62
63
    unless ( $provider_config->{authorize_url} =~ /response_type=code/ ) {
64
        my $authorize_url = Mojo::URL->new($provider_config->{authorize_url});
65
        $authorize_url->query->append(response_type => 'code');
66
        $provider_config->{authorize_url} = $authorize_url->to_string;
67
    }
68
69
    my $uri;
70
71
    if ( $interface eq 'opac' ) {
72
        if ( C4::Context->preference('OpacPublic') ) {
73
            $uri = '/cgi-bin/koha/opac-user.pl';
74
        } else {
75
            $uri = '/cgi-bin/koha/opac-main.pl';
76
        }
77
    } else {
78
        $uri = '/cgi-bin/koha/mainpage.pl';
79
    }
80
81
    return $c->oauth2->get_token_p($provider)->then(
82
        sub {
83
            return unless my $response = shift;
84
85
            my ( $patron, $mapped_data, $domain ) = Koha::Auth::Client::OAuth->new->get_user(
86
                {   provider  => $provider,
87
                    data      => $response,
88
                    interface => $interface,
89
                    config    => $c->oauth2->providers->{$provider}
90
                }
91
            );
92
93
            try {
94
                # FIXME: We could check if the backend allows registering
95
                if ( !$patron ) {
96
                    $patron = $c->auth->register(
97
                        {
98
                            data      => $mapped_data,
99
                            domain    => $domain,
100
                            interface => $interface
101
                        }
102
                    );
103
                }
104
105
                my ( $status, $cookie, $session_id ) = $c->auth->session($patron);
106
107
                $c->cookie( CGISESSID => $session_id, { path => "/" } );
108
109
                $c->redirect_to($uri);
110
            } catch {
111
                my $error = $_;
112
                $logger->error($error);
113
                # TODO: Review behavior
114
                if ( blessed $error ) {
115
                    if ( $error->isa('Koha::Exceptions::Auth::Unauthorized') ) {
116
                        $error = "$error";
117
                    }
118
                }
119
120
                $error = uri_escape_utf8($error);
121
122
                $c->redirect_to($uri."?auth_error=$error");
123
            };
124
        }
125
    )->catch(
126
        sub {
127
            my $error = shift;
128
            $logger->error($error);
129
            $error = uri_escape_utf8($error);
130
            $c->redirect_to($uri."?auth_error=$error");
131
        }
132
    )->wait;
133
}
134
135
1;
(-)a/api/v1/swagger/paths/public_oauth.yaml (+67 lines)
Line 0 Link Here
1
"/public/oauth/login/{provider}/{interface}":
2
  get:
3
    x-mojo-to: OAuth::Client#login
4
    operationId: loginOAuthClient
5
    tags:
6
      - oauth
7
    summary: Login to OAuth provider
8
    produces:
9
      - application/json
10
    parameters:
11
      - name: provider
12
        in: path
13
        description: Name of OAuth provider
14
        required: true
15
        type: string
16
      - name: interface
17
        in: path
18
        description: Name of the interface this login is for
19
        required: true
20
        type: string
21
      - name: code
22
        in: query
23
        description: Code returned from OAuth server for Authorization Code grant
24
        required: false
25
        type: string
26
      - name: state
27
        in: query
28
        description: An opaque value used by the client to maintain state between the request and callback. This is the callback part.
29
        required: false
30
        type: string
31
      - name: scope
32
        in: query
33
        description: Scope returned by OAuth server
34
        type: string
35
      - name: prompt
36
        in: query
37
        description: Prompt returned by OAuth server
38
        type: string
39
      - name: authuser
40
        in: query
41
        description: Auth user returned by OAuth server
42
        type: string
43
      - name: error
44
        in: query
45
        description: OAuth error code
46
        type: string
47
      - name: error_description
48
        in: query
49
        description: OAuth error description
50
        type: string
51
      - name: error_uri
52
        in: query
53
        description: Web page with user friendly description of the error
54
        type: string
55
    responses:
56
      "302":
57
        description: User authorized
58
        schema:
59
          type: string
60
      "400":
61
        description: Bad Request
62
        schema:
63
          $ref: "../swagger.yaml#/definitions/error"
64
      "403":
65
        description: Access forbidden
66
        schema:
67
          $ref: "../swagger.yaml#/definitions/error"
(-)a/api/v1/swagger/swagger.yaml (-1 / +2 lines)
Lines 269-274 paths: Link Here
269
    $ref: ./paths/libraries.yaml#/~1public~1libraries
269
    $ref: ./paths/libraries.yaml#/~1public~1libraries
270
  "/public/libraries/{library_id}":
270
  "/public/libraries/{library_id}":
271
    $ref: "./paths/libraries.yaml#/~1public~1libraries~1{library_id}"
271
    $ref: "./paths/libraries.yaml#/~1public~1libraries~1{library_id}"
272
  "/public/oauth/login/{provider}/{interface}":
273
    $ref: ./paths/public_oauth.yaml#/~1public~1oauth~1login~1{provider}~1{interface}
272
  "/public/patrons/{patron_id}/article_requests/{article_request_id}":
274
  "/public/patrons/{patron_id}/article_requests/{article_request_id}":
273
    $ref: "./paths/article_requests.yaml#/~1public~1patrons~1{patron_id}~1article_requests~1{article_request_id}"
275
    $ref: "./paths/article_requests.yaml#/~1public~1patrons~1{patron_id}~1article_requests~1{article_request_id}"
274
  "/public/patrons/{patron_id}/guarantors/can_see_charges":
276
  "/public/patrons/{patron_id}/guarantors/can_see_charges":
275
- 

Return to bug 31378