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

(-)a/Koha/Auth/Client.pm (-10 / +12 lines)
Lines 20-26 package Koha::Auth::Client; Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Koha::Exceptions::Auth;
22
use Koha::Exceptions::Auth;
23
use Koha::Auth::Providers;
23
use Koha::Auth::Identity::Providers;
24
24
25
=head1 NAME
25
=head1 NAME
26
26
Lines 58-64 sub get_user { Link Here
58
    my $interface     = $params->{interface};
58
    my $interface     = $params->{interface};
59
    my $config        = $params->{config};
59
    my $config        = $params->{config};
60
60
61
    my $provider = Koha::Auth::Providers->search({ code => $provider_code })->next;
61
    my $provider = Koha::Auth::Identity::Providers->search({ code => $provider_code })->next;
62
62
63
    my ( $mapped_data, $patron ) = $self->_get_data_and_patron({ provider => $provider, data => $data, config => $config });
63
    my ( $mapped_data, $patron ) = $self->_get_data_and_patron({ provider => $provider, data => $data, config => $config });
64
64
Lines 68-73 sub get_user { Link Here
68
        $mapped_data->{categorycode} = $domain->default_category_id;
68
        $mapped_data->{categorycode} = $domain->default_category_id;
69
        $mapped_data->{branchcode}   = $domain->default_library_id;
69
        $mapped_data->{branchcode}   = $domain->default_library_id;
70
70
71
        $patron->set($mapped_data)->store if $patron && $domain->update_on_auth;
72
71
        return ( $patron, $mapped_data, $domain );
73
        return ( $patron, $mapped_data, $domain );
72
    }
74
    }
73
}
75
}
Lines 93-99 sub get_valid_domain_config { Link Here
93
    my $interface  = $params->{interface};
95
    my $interface  = $params->{interface};
94
96
95
    my $domains = $provider->domains;
97
    my $domains = $provider->domains;
96
    my $pattern = '@';
97
    my $allow   = "allow_$interface";
98
    my $allow   = "allow_$interface";
98
    my @subdomain_matches;
99
    my @subdomain_matches;
99
    my $default_match;
100
    my $default_match;
Lines 101-119 sub get_valid_domain_config { Link Here
101
    while ( my $domain = $domains->next ) {
102
    while ( my $domain = $domains->next ) {
102
        next unless $domain->$allow;
103
        next unless $domain->$allow;
103
104
105
        my $pattern = '@';
104
        my $domain_text = $domain->domain;
106
        my $domain_text = $domain->domain;
105
        unless ( defined $domain_text && $domain_text ne '') {
107
        unless ( defined $domain_text && $domain_text ne '') {
106
            $default_match = $domain;
108
            $default_match = $domain;
107
            next;
109
            next;
108
        }
110
        }
109
        my ( $asterisk, $domain_name ) = ( $domain_text =~ /^(\*)?(.+)$/ );
111
        my ( $asterisk, $domain_name ) = ( $domain_text =~ /^(\*)?(.+)$/ );
110
        if ( $asterisk eq '*' ) {
112
        if ( defined $asterisk && $asterisk eq '*' ) {
111
            $pattern .= '.*';
113
            $pattern .= '.*';
112
        }
114
        }
113
        $domain_name =~ s/\./\\\./g;
115
        $domain_name =~ s/\./\\\./g;
114
        $pattern .= $domain_name . '$';
116
        $pattern .= $domain_name . '$';
115
        if ( $user_email =~ /$pattern/ ) {
117
        if ( $user_email =~ /$pattern/ ) {
116
            if ( $asterisk eq '*' ) {
118
            if ( defined $asterisk && $asterisk eq '*' ) {
117
                push @subdomain_matches, { domain => $domain, match_length => length $domain_name };
119
                push @subdomain_matches, { domain => $domain, match_length => length $domain_name };
118
            } else {
120
            } else {
119
121
Lines 129-135 sub get_valid_domain_config { Link Here
129
        return $subdomain_matches[0]->{domain};
131
        return $subdomain_matches[0]->{domain};
130
    }
132
    }
131
133
132
    return $default_match || 0;
134
    return $default_match;
133
}
135
}
134
136
135
=head3 has_valid_domain_config
137
=head3 has_valid_domain_config
Lines 176-190 sub _get_data_and_patron { Link Here
176
    return {};
178
    return {};
177
}
179
}
178
180
179
=head3 _tranverse_hash
181
=head3 _traverse_hash
180
182
181
    my $value = $auth_client->_tranverse_hash( { base => $base_hash, keys => $key_string } );
183
    my $value = $auth_client->_traverse_hash( { base => $base_hash, keys => $key_string } );
182
184
183
Get deep nested value in a hash.
185
Get deep nested value in a hash.
184
186
185
=cut
187
=cut
186
188
187
sub _tranverse_hash {
189
sub _traverse_hash {
188
    my ($self, $params) = @_;
190
    my ($self, $params) = @_;
189
    my $base = $params->{base};
191
    my $base = $params->{base};
190
    my $keys = $params->{keys};
192
    my $keys = $params->{keys};
Lines 192-198 sub _tranverse_hash { Link Here
192
    return unless defined $key;
194
    return unless defined $key;
193
    my $value = ref $base eq 'HASH' ? $base->{$key} : $base->[$key];
195
    my $value = ref $base eq 'HASH' ? $base->{$key} : $base->[$key];
194
    return $value unless $rest;
196
    return $value unless $rest;
195
    return $self->_tranverse_hash({ base => $value, keys => $rest });
197
    return $self->_traverse_hash({ base => $value, keys => $rest });
196
}
198
}
197
199
198
1;
200
1;
(-)a/Koha/Auth/Client/OAuth.pm (-10 / +10 lines)
Lines 78-86 sub _get_data_and_patron { Link Here
78
        if ( defined $value and $matchpoint_rs->count ) {
78
        if ( defined $value and $matchpoint_rs->count ) {
79
            $patron = $matchpoint_rs->next;
79
            $patron = $matchpoint_rs->next;
80
        }
80
        }
81
82
        return ( $mapped_data, $patron )
83
          if $patron;
84
    }
81
    }
85
82
86
    if ( defined $config->{userinfo_url} ) {
83
    if ( defined $config->{userinfo_url} ) {
Lines 97-118 sub _get_data_and_patron { Link Here
97
94
98
        foreach my $key ( keys %$mapping ) {
95
        foreach my $key ( keys %$mapping ) {
99
            my $pkey  = $mapping->{$key};
96
            my $pkey  = $mapping->{$key};
100
            my $value = $self->_tranverse_hash( { base => $claim, keys => $pkey } );
97
            my $value = $self->_traverse_hash( { base => $claim, keys => $pkey } );
101
            $mapped_data->{$key} = $value
98
            $mapped_data->{$key} = $value
102
              if defined $value;
99
              if defined $value;
103
        }
100
        }
104
101
105
        my $value = $mapped_data->{$matchpoint};
102
        unless ($patron) {
103
            my $value = $mapped_data->{$matchpoint};
106
104
107
        my $matchpoint_rs = Koha::Patrons->search( { $matchpoint => $value } );
105
            my $matchpoint_rs = Koha::Patrons->search( { $matchpoint => $value } );
108
106
109
        if ( defined $value and $matchpoint_rs->count ) {
107
            if ( defined $value and $matchpoint_rs->count ) {
110
            $patron = $matchpoint_rs->next;
108
                $patron = $matchpoint_rs->next;
109
            }
111
        }
110
        }
112
111
113
        return ( $mapped_data, $patron )
114
          if $patron;
115
    }
112
    }
113
114
    return ( $mapped_data, $patron )
115
          if $patron;
116
}
116
}
117
117
118
1;
118
1;
(-)a/Koha/Auth/Provider.pm (-10 / +10 lines)
Lines 1-4 Link Here
1
package Koha::Auth::Provider;
1
package Koha::Auth::Identity::Provider;
2
2
3
# Copyright Theke Solutions 2022
3
# Copyright Theke Solutions 2022
4
#
4
#
Lines 24-36 use base qw(Koha::Object); Link Here
24
use JSON qw( decode_json encode_json );
24
use JSON qw( decode_json encode_json );
25
use Try::Tiny;
25
use Try::Tiny;
26
26
27
use Koha::Auth::Provider::Domains;
27
use Koha::Auth::Identity::Provider::Domains;
28
use Koha::Exceptions;
28
use Koha::Exceptions;
29
use Koha::Exceptions::Object;
29
use Koha::Exceptions::Object;
30
30
31
=head1 NAME
31
=head1 NAME
32
32
33
Koha::Auth::Provider - Koha Auth Provider Object class
33
Koha::Auth::Identity::Provider - Koha Auth Provider Object class
34
34
35
=head1 API
35
=head1 API
36
36
Lines 40-53 Koha::Auth::Provider - Koha Auth Provider Object class Link Here
40
40
41
    my $domains = $provider->domains;
41
    my $domains = $provider->domains;
42
42
43
Returns the related I<Koha::Auth::Provider::Domains> iterator.
43
Returns the related I<Koha::Auth::Identity::Provider::Domains> iterator.
44
44
45
=cut
45
=cut
46
46
47
sub domains {
47
sub domains {
48
    my ($self) = @_;
48
    my ($self) = @_;
49
49
50
    return Koha::Auth::Provider::Domains->_new_from_dbic( scalar $self->_result->domains );
50
    return Koha::Auth::Identity::Provider::Domains->_new_from_dbic( scalar $self->_result->domains );
51
}
51
}
52
52
53
=head3 get_config
53
=head3 get_config
Lines 183-189 sub upgrade_class { Link Here
183
183
184
    my $json = $provider->to_api;
184
    my $json = $provider->to_api;
185
185
186
Overloaded method that returns a JSON representation of the Koha::Auth::Provider object,
186
Overloaded method that returns a JSON representation of the Koha::Auth::Identity::Provider object,
187
suitable for API output.
187
suitable for API output.
188
188
189
=cut
189
=cut
Lines 206-217 sub to_api { Link Here
206
=cut
206
=cut
207
207
208
sub _type {
208
sub _type {
209
    return 'AuthProvider';
209
    return 'IdentityProvider';
210
}
210
}
211
211
212
=head3 protocol_to_class_mapping
212
=head3 protocol_to_class_mapping
213
213
214
    my $mapping = Koha::Auth::Provider::protocol_to_class_mapping
214
    my $mapping = Koha::Auth::Identity::Provider::protocol_to_class_mapping
215
215
216
Internal method that returns a mapping between I<protocol> codes and
216
Internal method that returns a mapping between I<protocol> codes and
217
implementing I<classes>. To be used by B<upgrade_class>.
217
implementing I<classes>. To be used by B<upgrade_class>.
Lines 220-227 implementing I<classes>. To be used by B<upgrade_class>. Link Here
220
220
221
sub protocol_to_class_mapping {
221
sub protocol_to_class_mapping {
222
    return {
222
    return {
223
        OAuth => 'Koha::Auth::Provider::OAuth',
223
        OAuth => 'Koha::Auth::Identity::Provider::OAuth',
224
        OIDC  => 'Koha::Auth::Provider::OIDC',
224
        OIDC  => 'Koha::Auth::Identity::Provider::OIDC',
225
    };
225
    };
226
}
226
}
227
227
(-)a/Koha/Auth/Provider/Domain.pm (-3 / +3 lines)
Lines 1-4 Link Here
1
package Koha::Auth::Provider::Domain;
1
package Koha::Auth::Identity::Provider::Domain;
2
2
3
# Copyright Theke Solutions 2022
3
# Copyright Theke Solutions 2022
4
#
4
#
Lines 23-29 use base qw(Koha::Object); Link Here
23
23
24
=head1 NAME
24
=head1 NAME
25
25
26
Koha::Auth::Provider::Domain - Koha Auth Provider Domain Object class
26
Koha::Auth::Identity::Provider::Domain - Koha Auth Provider Domain Object class
27
27
28
=head1 API
28
=head1 API
29
29
Lines 34-40 Koha::Auth::Provider::Domain - Koha Auth Provider Domain Object class Link Here
34
=cut
34
=cut
35
35
36
sub _type {
36
sub _type {
37
    return 'AuthProviderDomain';
37
    return 'IdentityProviderDomain';
38
}
38
}
39
39
40
1;
40
1;
(-)a/Koha/Auth/Provider/Domains.pm (-5 / +5 lines)
Lines 1-4 Link Here
1
package Koha::Auth::Provider::Domains;
1
package Koha::Auth::Identity::Provider::Domains;
2
2
3
# Copyright Theke Solutions 2022
3
# Copyright Theke Solutions 2022
4
#
4
#
Lines 20-32 package Koha::Auth::Provider::Domains; Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Koha::Database;
22
use Koha::Database;
23
use Koha::Auth::Provider::Domain;
23
use Koha::Auth::Identity::Provider::Domain;
24
24
25
use base qw(Koha::Objects);
25
use base qw(Koha::Objects);
26
26
27
=head1 NAME
27
=head1 NAME
28
28
29
Koha::Auth::Providers - Koha Auth Provider Object class
29
Koha::Auth::Identity::Providers - Koha Auth Provider Object class
30
30
31
=head1 API
31
=head1 API
32
32
Lines 39-45 Koha::Auth::Providers - Koha Auth Provider Object class Link Here
39
=cut
39
=cut
40
40
41
sub _type {
41
sub _type {
42
    return 'AuthProviderDomain';
42
    return 'IdentityProviderDomain';
43
}
43
}
44
44
45
=head3 object_class
45
=head3 object_class
Lines 47-53 sub _type { Link Here
47
=cut
47
=cut
48
48
49
sub object_class {
49
sub object_class {
50
    return 'Koha::Auth::Provider::Domain';
50
    return 'Koha::Auth::Identity::Provider::Domain';
51
}
51
}
52
52
53
1;
53
1;
(-)a/Koha/Auth/Provider/OAuth.pm (-4 / +4 lines)
Lines 1-4 Link Here
1
package Koha::Auth::Provider::OAuth;
1
package Koha::Auth::Identity::Provider::OAuth;
2
2
3
# Copyright Theke Solutions 2022
3
# Copyright Theke Solutions 2022
4
#
4
#
Lines 19-29 package Koha::Auth::Provider::OAuth; Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use base qw(Koha::Auth::Provider);
22
use base qw(Koha::Auth::Identity::Provider);
23
23
24
=head1 NAME
24
=head1 NAME
25
25
26
Koha::Auth::Provider::OAuth - Koha Auth Provider Object class
26
Koha::Auth::Identity::Provider::OAuth - Koha Auth Provider Object class
27
27
28
=head1 API
28
=head1 API
29
29
Lines 31-37 Koha::Auth::Provider::OAuth - Koha Auth Provider Object class Link Here
31
31
32
=head3 new
32
=head3 new
33
33
34
    my $oauth = Koha::Auth::Provider::OAuth->new( \%{params} );
34
    my $oauth = Koha::Auth::Identity::Provider::OAuth->new( \%{params} );
35
35
36
Overloaded class to create a new OAuth provider.
36
Overloaded class to create a new OAuth provider.
37
37
(-)a/Koha/Auth/Provider/OIDC.pm (-4 / +4 lines)
Lines 1-4 Link Here
1
package Koha::Auth::Provider::OIDC;
1
package Koha::Auth::Identity::Provider::OIDC;
2
2
3
# Copyright Theke Solutions 2022
3
# Copyright Theke Solutions 2022
4
#
4
#
Lines 19-29 package Koha::Auth::Provider::OIDC; Link Here
19
19
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use base qw(Koha::Auth::Provider);
22
use base qw(Koha::Auth::Identity::Provider);
23
23
24
=head1 NAME
24
=head1 NAME
25
25
26
Koha::Auth::Provider::OIDC - Koha Auth Provider Object class
26
Koha::Auth::Identity::Provider::OIDC - Koha Auth Provider Object class
27
27
28
=head1 API
28
=head1 API
29
29
Lines 31-37 Koha::Auth::Provider::OIDC - Koha Auth Provider Object class Link Here
31
31
32
=head3 new
32
=head3 new
33
33
34
    my $oidc = Koha::Auth::Provider::OIDC->new( \%{params} );
34
    my $oidc = Koha::Auth::Identity::Provider::OIDC->new( \%{params} );
35
35
36
Overloaded class to create a new OIDC provider.
36
Overloaded class to create a new OIDC provider.
37
37
(-)a/Koha/Auth/Providers.pm (-5 / +5 lines)
Lines 1-4 Link Here
1
package Koha::Auth::Providers;
1
package Koha::Auth::Identity::Providers;
2
2
3
# Copyright Theke Solutions 2022
3
# Copyright Theke Solutions 2022
4
#
4
#
Lines 20-32 package Koha::Auth::Providers; Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
21
22
use Koha::Database;
22
use Koha::Database;
23
use Koha::Auth::Provider;
23
use Koha::Auth::Identity::Provider;
24
24
25
use base qw(Koha::Objects);
25
use base qw(Koha::Objects);
26
26
27
=head1 NAME
27
=head1 NAME
28
28
29
Koha::Auth::Providers - Koha Auth Provider Object class
29
Koha::Auth::Identity::Providers - Koha Auth Provider Object class
30
30
31
=head1 API
31
=head1 API
32
32
Lines 39-45 Koha::Auth::Providers - Koha Auth Provider Object class Link Here
39
=cut
39
=cut
40
40
41
sub _type {
41
sub _type {
42
    return 'AuthProvider';
42
    return 'IdentityProvider';
43
}
43
}
44
44
45
=head3 object_class
45
=head3 object_class
Lines 47-53 sub _type { Link Here
47
=cut
47
=cut
48
48
49
sub object_class {
49
sub object_class {
50
    return 'Koha::Auth::Provider';
50
    return 'Koha::Auth::Identity::Provider';
51
}
51
}
52
52
53
1;
53
1;
(-)a/Koha/REST/Plugin/Auth.pm (-2 / +2 lines)
Lines 1-4 Link Here
1
package Koha::REST::Plugin::Auth;
1
package Koha::REST::Plugin::Auth::IdP;
2
2
3
# Copyright Theke Solutions 2022
3
# Copyright Theke Solutions 2022
4
#
4
#
Lines 31-37 use CGI; Link Here
31
31
32
=head1 NAME
32
=head1 NAME
33
33
34
Koha::REST::Plugin::Auth
34
Koha::REST::Plugin::Auth::IdP
35
35
36
=head1 API
36
=head1 API
37
37
(-)a/Koha/REST/V1.pm (-3 / +3 lines)
Lines 21-27 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
use Koha::Auth::Identity::Providers;
25
25
26
use Mojolicious::Plugin::OAuth2;
26
use Mojolicious::Plugin::OAuth2;
27
use JSON::Validator::Schema::OpenAPIv2;
27
use JSON::Validator::Schema::OpenAPIv2;
Lines 139-145 sub startup { Link Here
139
139
140
    my $oauth_configuration = {};
140
    my $oauth_configuration = {};
141
    my $search_options = { protocol => [ "OIDC", "OAuth" ] };
141
    my $search_options = { protocol => [ "OIDC", "OAuth" ] };
142
    my $providers = Koha::Auth::Providers->search( $search_options );
142
    my $providers = Koha::Auth::Identity::Providers->search( $search_options );
143
143
144
    while(my $provider = $providers->next) {
144
    while(my $provider = $providers->next) {
145
        $oauth_configuration->{$provider->code} = decode_json($provider->config);
145
        $oauth_configuration->{$provider->code} = decode_json($provider->config);
Lines 149-155 sub startup { Link Here
149
    $self->plugin( 'Koha::REST::Plugin::Query' );
149
    $self->plugin( 'Koha::REST::Plugin::Query' );
150
    $self->plugin( 'Koha::REST::Plugin::Objects' );
150
    $self->plugin( 'Koha::REST::Plugin::Objects' );
151
    $self->plugin( 'Koha::REST::Plugin::Exceptions' );
151
    $self->plugin( 'Koha::REST::Plugin::Exceptions' );
152
    $self->plugin( 'Koha::REST::Plugin::Auth' );
152
    $self->plugin( 'Koha::REST::Plugin::Auth::IdP' );
153
    $self->plugin( 'Mojolicious::Plugin::OAuth2' => $oauth_configuration );
153
    $self->plugin( 'Mojolicious::Plugin::OAuth2' => $oauth_configuration );
154
}
154
}
155
155
(-)a/Koha/REST/V1/Auth/Provider/Domains.pm (-20 / +21 lines)
Lines 1-4 Link Here
1
package Koha::REST::V1::Auth::Provider::Domains;
1
package Koha::REST::V1::Auth::Identity::Provider::Domains;
2
2
3
# This file is part of Koha.
3
# This file is part of Koha.
4
#
4
#
Lines 19-26 use Modern::Perl; Link Here
19
19
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
21
22
use Koha::Auth::Provider::Domains;
22
use Koha::Auth::Identity::Provider::Domains;
23
use Koha::Auth::Providers;
23
use Koha::Auth::Identity::Providers;
24
24
25
use Koha::Database;
25
use Koha::Database;
26
26
Lines 29-35 use Try::Tiny; Link Here
29
29
30
=head1 NAME
30
=head1 NAME
31
31
32
Koha::REST::V1::Auth::Provider::Domains - Controller library for handling
32
Koha::REST::V1::Auth::Identity::Provider::Domains - Controller library for handling
33
authentication provider domains routes.
33
authentication provider domains routes.
34
34
35
=head2 Operations
35
=head2 Operations
Lines 44-51 sub list { Link Here
44
    my $c = shift->openapi->valid_input or return;
44
    my $c = shift->openapi->valid_input or return;
45
45
46
    return try {
46
    return try {
47
        my $auth_provider_id = $c->validation->param('auth_provider_id');
47
        my $identity_provider_id = $c->validation->param('identity_provider_id');
48
        my $provider         = Koha::Auth::Providers->find($auth_provider_id);
48
        my $provider         = Koha::Auth::Identity::Providers->find($identity_provider_id);
49
49
50
        unless ($provider) {
50
        unless ($provider) {
51
            return $c->render(
51
            return $c->render(
Lines 78-85 sub get { Link Here
78
78
79
    return try {
79
    return try {
80
80
81
        my $auth_provider_id = $c->validation->param('auth_provider_id');
81
        my $identity_provider_id = $c->validation->param('identity_provider_id');
82
        my $provider         = Koha::Auth::Providers->find($auth_provider_id);
82
        my $provider         = Koha::Auth::Identity::Providers->find($identity_provider_id);
83
83
84
        unless ($provider) {
84
        unless ($provider) {
85
            return $c->render(
85
            return $c->render(
Lines 93-100 sub get { Link Here
93
93
94
        my $domains_rs = $provider->domains;
94
        my $domains_rs = $provider->domains;
95
95
96
        my $auth_provider_domain_id = $c->validation->param('auth_provider_domain_id');
96
        my $identity_provider_domain_id = $c->validation->param('identity_provider_domain_id');
97
        my $domain                  = $c->objects->find( $domains_rs, $auth_provider_domain_id );
97
        my $domain                  = $c->objects->find( $domains_rs, $identity_provider_domain_id );
98
98
99
        unless ($domain) {
99
        unless ($domain) {
100
            return $c->render(
100
            return $c->render(
Lines 122-131 sub add { Link Here
122
    my $c = shift->openapi->valid_input or return;
122
    my $c = shift->openapi->valid_input or return;
123
123
124
    return try {
124
    return try {
125
125
        my $params = $c->validation->param('body');
126
        $params->{identity_provider_id} = $c->validation->param('identity_provider_id');
126
        Koha::Database->new->schema->txn_do(
127
        Koha::Database->new->schema->txn_do(
127
            sub {
128
            sub {
128
                my $domain = Koha::Auth::Provider::Domain->new_from_api( $c->validation->param('body') );
129
                my $domain = Koha::Auth::Identity::Provider::Domain->new_from_api( $params );
129
                $domain->store;
130
                $domain->store;
130
131
131
                $c->res->headers->location( $c->req->url->to_string . '/' . $domain->id );
132
                $c->res->headers->location( $c->req->url->to_string . '/' . $domain->id );
Lines 159-169 Controller method for updating an authentication provider domain. Link Here
159
sub update {
160
sub update {
160
    my $c = shift->openapi->valid_input or return;
161
    my $c = shift->openapi->valid_input or return;
161
162
162
    my $auth_provider_id        = $c->validation->param('auth_provider_id');
163
    my $identity_provider_id        = $c->validation->param('identity_provider_id');
163
    my $auth_provider_domain_id = $c->validation->param('auth_provider_domain_id');
164
    my $identity_provider_domain_id = $c->validation->param('identity_provider_domain_id');
164
165
165
    my $domain = Koha::Auth::Provider::Domains->find(
166
    my $domain = Koha::Auth::Identity::Provider::Domains->find(
166
        { auth_provider_id => $auth_provider_id, auth_provider_domain_id => $auth_provider_domain_id } );
167
        { identity_provider_id => $identity_provider_id, identity_provider_domain_id => $identity_provider_domain_id } );
167
168
168
    unless ($domain) {
169
    unless ($domain) {
169
        return $c->render(
170
        return $c->render(
Lines 203-213 Controller method for deleting an authentication provider. Link Here
203
sub delete {
204
sub delete {
204
    my $c = shift->openapi->valid_input or return;
205
    my $c = shift->openapi->valid_input or return;
205
206
206
    my $auth_provider_id        = $c->validation->param('auth_provider_id');
207
    my $identity_provider_id        = $c->validation->param('identity_provider_id');
207
    my $auth_provider_domain_id = $c->validation->param('auth_provider_domain_id');
208
    my $identity_provider_domain_id = $c->validation->param('identity_provider_domain_id');
208
209
209
    my $domain = Koha::Auth::Provider::Domains->find(
210
    my $domain = Koha::Auth::Identity::Provider::Domains->find(
210
        { auth_provider_id => $auth_provider_id, auth_provider_domain_id => $auth_provider_domain_id } );
211
        { identity_provider_id => $identity_provider_id, identity_provider_domain_id => $identity_provider_domain_id } );
211
212
212
    unless ($domain) {
213
    unless ($domain) {
213
        return $c->render(
214
        return $c->render(
(-)a/Koha/REST/V1/Auth/Providers.pm (-13 / +13 lines)
Lines 1-4 Link Here
1
package Koha::REST::V1::Auth::Providers;
1
package Koha::REST::V1::Auth::Identity::Providers;
2
2
3
# This file is part of Koha.
3
# This file is part of Koha.
4
#
4
#
Lines 19-27 use Modern::Perl; Link Here
19
19
20
use Mojo::Base 'Mojolicious::Controller';
20
use Mojo::Base 'Mojolicious::Controller';
21
21
22
use Koha::Auth::Provider::OAuth;
22
use Koha::Auth::Identity::Provider::OAuth;
23
use Koha::Auth::Provider::OIDC;
23
use Koha::Auth::Identity::Provider::OIDC;
24
use Koha::Auth::Providers;
24
use Koha::Auth::Identity::Providers;
25
25
26
use Koha::Database;
26
use Koha::Database;
27
27
Lines 30-36 use Try::Tiny; Link Here
30
30
31
=head1 NAME
31
=head1 NAME
32
32
33
Koha::REST::V1::Auth::Providers - Controller library for handling
33
Koha::REST::V1::Auth::Identity::Providers - Controller library for handling
34
authentication providers routes.
34
authentication providers routes.
35
35
36
=head2 Operations
36
=head2 Operations
Lines 45-51 sub list { Link Here
45
    my $c = shift->openapi->valid_input or return;
45
    my $c = shift->openapi->valid_input or return;
46
46
47
    return try {
47
    return try {
48
        my $providers_rs = Koha::Auth::Providers->new;
48
        my $providers_rs = Koha::Auth::Identity::Providers->new;
49
        return $c->render(
49
        return $c->render(
50
            status  => 200,
50
            status  => 200,
51
            openapi => $c->objects->search($providers_rs)
51
            openapi => $c->objects->search($providers_rs)
Lines 66-73 sub get { Link Here
66
66
67
    return try {
67
    return try {
68
68
69
        my $auth_provider_id = $c->validation->param('auth_provider_id');
69
        my $identity_provider_id = $c->validation->param('identity_provider_id');
70
        my $provider = $c->objects->find( Koha::Auth::Providers->new, $auth_provider_id );
70
        my $provider = $c->objects->find( Koha::Auth::Identity::Providers->new, $identity_provider_id );
71
71
72
        unless ( $provider ) {
72
        unless ( $provider ) {
73
            return $c->render(
73
            return $c->render(
Lines 106-112 sub add { Link Here
106
                my $mapping  = delete $body->{mapping};
106
                my $mapping  = delete $body->{mapping};
107
                my $protocol = delete $body->{protocol};
107
                my $protocol = delete $body->{protocol};
108
108
109
                my $class = Koha::Auth::Provider::protocol_to_class_mapping->{$protocol};
109
                my $class = Koha::Auth::Identity::Provider::protocol_to_class_mapping->{$protocol};
110
110
111
                my $provider = $class->new_from_api( $body );
111
                my $provider = $class->new_from_api( $body );
112
                $provider->store;
112
                $provider->store;
Lines 114-120 sub add { Link Here
114
                $provider->set_config( $config );
114
                $provider->set_config( $config );
115
                $provider->set_mapping( $mapping );
115
                $provider->set_mapping( $mapping );
116
116
117
                $c->res->headers->location( $c->req->url->to_string . '/' . $provider->auth_provider_id );
117
                $c->res->headers->location( $c->req->url->to_string . '/' . $provider->identity_provider_id );
118
                return $c->render(
118
                return $c->render(
119
                    status  => 201,
119
                    status  => 201,
120
                    openapi => $provider->to_api
120
                    openapi => $provider->to_api
Lines 148-155 Controller method for updating an authentication provider. Link Here
148
sub update {
148
sub update {
149
    my $c = shift->openapi->valid_input or return;
149
    my $c = shift->openapi->valid_input or return;
150
150
151
    my $auth_provider_id = $c->validation->param('auth_provider_id');
151
    my $identity_provider_id = $c->validation->param('identity_provider_id');
152
    my $provider = Koha::Auth::Providers->find( $auth_provider_id );
152
    my $provider = Koha::Auth::Identity::Providers->find( $identity_provider_id );
153
153
154
    unless ( $provider ) {
154
    unless ( $provider ) {
155
        return $c->render(
155
        return $c->render(
Lines 211-217 Controller method for deleting an authentication provider. Link Here
211
sub delete {
211
sub delete {
212
    my $c = shift->openapi->valid_input or return;
212
    my $c = shift->openapi->valid_input or return;
213
213
214
    my $provider = Koha::Auth::Providers->find( $c->validation->param('auth_provider_id') );
214
    my $provider = Koha::Auth::Identity::Providers->find( $c->validation->param('identity_provider_id') );
215
    unless ( $provider ) {
215
    unless ( $provider ) {
216
        return $c->render(
216
        return $c->render(
217
            status  => 404,
217
            status  => 404,
(-)a/Koha/Schema/Result/Branch.pm (-17 / +17 lines)
Lines 347-367 __PACKAGE__->has_many( Link Here
347
  { cascade_copy => 0, cascade_delete => 0 },
347
  { cascade_copy => 0, cascade_delete => 0 },
348
);
348
);
349
349
350
=head2 auth_provider_domains
351
352
Type: has_many
353
354
Related object: L<Koha::Schema::Result::AuthProviderDomain>
355
356
=cut
357
358
__PACKAGE__->has_many(
359
  "auth_provider_domains",
360
  "Koha::Schema::Result::AuthProviderDomain",
361
  { "foreign.default_library_id" => "self.branchcode" },
362
  { cascade_copy => 0, cascade_delete => 0 },
363
);
364
365
=head2 authorised_values_branches
350
=head2 authorised_values_branches
366
351
367
Type: has_many
352
Type: has_many
Lines 692-697 __PACKAGE__->has_many( Link Here
692
  { cascade_copy => 0, cascade_delete => 0 },
677
  { cascade_copy => 0, cascade_delete => 0 },
693
);
678
);
694
679
680
=head2 identity_provider_domains
681
682
Type: has_many
683
684
Related object: L<Koha::Schema::Result::IdentityProviderDomain>
685
686
=cut
687
688
__PACKAGE__->has_many(
689
  "identity_provider_domains",
690
  "Koha::Schema::Result::IdentityProviderDomain",
691
  { "foreign.default_library_id" => "self.branchcode" },
692
  { cascade_copy => 0, cascade_delete => 0 },
693
);
694
695
=head2 illrequests
695
=head2 illrequests
696
696
697
Type: has_many
697
Type: has_many
Lines 918-925 __PACKAGE__->has_many( Link Here
918
);
918
);
919
919
920
920
921
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-09-23 17:26:47
921
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-10-20 15:27:55
922
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:L55G1NNTzyYIwECcFbokXw
922
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:Dlgcr2h2MywvwBhj+aOvuQ
923
923
924
__PACKAGE__->add_columns(
924
__PACKAGE__->add_columns(
925
    '+pickup_location' => { is_boolean => 1 },
925
    '+pickup_location' => { is_boolean => 1 },
(-)a/Koha/Schema/Result/Category.pm (-17 / +17 lines)
Lines 287-307 __PACKAGE__->set_primary_key("categorycode"); Link Here
287
287
288
=head1 RELATIONS
288
=head1 RELATIONS
289
289
290
=head2 auth_provider_domains
291
292
Type: has_many
293
294
Related object: L<Koha::Schema::Result::AuthProviderDomain>
295
296
=cut
297
298
__PACKAGE__->has_many(
299
  "auth_provider_domains",
300
  "Koha::Schema::Result::AuthProviderDomain",
301
  { "foreign.default_category_id" => "self.categorycode" },
302
  { cascade_copy => 0, cascade_delete => 0 },
303
);
304
305
=head2 borrower_attribute_types
290
=head2 borrower_attribute_types
306
291
307
Type: has_many
292
Type: has_many
Lines 377-385 __PACKAGE__->has_many( Link Here
377
  { cascade_copy => 0, cascade_delete => 0 },
362
  { cascade_copy => 0, cascade_delete => 0 },
378
);
363
);
379
364
365
=head2 identity_provider_domains
366
367
Type: has_many
368
369
Related object: L<Koha::Schema::Result::IdentityProviderDomain>
370
371
=cut
372
373
__PACKAGE__->has_many(
374
  "identity_provider_domains",
375
  "Koha::Schema::Result::IdentityProviderDomain",
376
  { "foreign.default_category_id" => "self.categorycode" },
377
  { cascade_copy => 0, cascade_delete => 0 },
378
);
379
380
380
381
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-08-16 23:14:56
381
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-10-20 15:27:55
382
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:OLnB+kXFSOl8HRWcY3ep3w
382
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CBVbmHl/pwgHohyiHL6qeg
383
383
384
sub koha_object_class {
384
sub koha_object_class {
385
    'Koha::Patron::Category';
385
    'Koha::Patron::Category';
(-)a/Koha/Schema/Result/AuthProvider.pm (-28 / +19 lines)
Lines 1-12 Link Here
1
use utf8;
1
use utf8;
2
package Koha::Schema::Result::AuthProvider;
2
package Koha::Schema::Result::IdentityProvider;
3
3
4
# Created by DBIx::Class::Schema::Loader
4
# Created by DBIx::Class::Schema::Loader
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
6
6
7
=head1 NAME
7
=head1 NAME
8
8
9
Koha::Schema::Result::AuthProvider
9
Koha::Schema::Result::IdentityProvider
10
10
11
=cut
11
=cut
12
12
Lines 15-29 use warnings; Link Here
15
15
16
use base 'DBIx::Class::Core';
16
use base 'DBIx::Class::Core';
17
17
18
=head1 TABLE: C<auth_providers>
18
=head1 TABLE: C<identity_providers>
19
19
20
=cut
20
=cut
21
21
22
__PACKAGE__->table("auth_providers");
22
__PACKAGE__->table("identity_providers");
23
23
24
=head1 ACCESSORS
24
=head1 ACCESSORS
25
25
26
=head2 auth_provider_id
26
=head2 identity_provider_id
27
27
28
  data_type: 'integer'
28
  data_type: 'integer'
29
  is_auto_increment: 1
29
  is_auto_increment: 1
Lines 90-96 Provider icon URL Link Here
90
=cut
90
=cut
91
91
92
__PACKAGE__->add_columns(
92
__PACKAGE__->add_columns(
93
  "auth_provider_id",
93
  "identity_provider_id",
94
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
94
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
95
  "code",
95
  "code",
96
  { data_type => "varchar", is_nullable => 0, size => 20 },
96
  { data_type => "varchar", is_nullable => 0, size => 20 },
Lines 120-132 __PACKAGE__->add_columns( Link Here
120
120
121
=over 4
121
=over 4
122
122
123
=item * L</auth_provider_id>
123
=item * L</identity_provider_id>
124
124
125
=back
125
=back
126
126
127
=cut
127
=cut
128
128
129
__PACKAGE__->set_primary_key("auth_provider_id");
129
__PACKAGE__->set_primary_key("identity_provider_id");
130
130
131
=head1 UNIQUE CONSTRAINTS
131
=head1 UNIQUE CONSTRAINTS
132
132
Lines 144-189 __PACKAGE__->add_unique_constraint("code", ["code"]); Link Here
144
144
145
=head1 RELATIONS
145
=head1 RELATIONS
146
146
147
=head2 auth_provider_domains
147
=head2 identity_provider_domains
148
148
149
Type: has_many
149
Type: has_many
150
150
151
Related object: L<Koha::Schema::Result::AuthProviderDomain>
151
Related object: L<Koha::Schema::Result::IdentityProviderDomain>
152
152
153
=cut
153
=cut
154
154
155
__PACKAGE__->has_many(
155
__PACKAGE__->has_many(
156
  "auth_provider_domains",
156
  "identity_provider_domains",
157
  "Koha::Schema::Result::AuthProviderDomain",
157
  "Koha::Schema::Result::IdentityProviderDomain",
158
  { "foreign.auth_provider_id" => "self.auth_provider_id" },
158
  { "foreign.identity_provider_id" => "self.identity_provider_id" },
159
  { cascade_copy => 0, cascade_delete => 0 },
159
  { cascade_copy => 0, cascade_delete => 0 },
160
);
160
);
161
161
162
162
163
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-09-30 19:43:00
163
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-10-20 15:27:55
164
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZqUo3by0ZXca5RI3QFNypw
164
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:jmqAwH7/6QvawJ73/0rkQg
165
166
167
=head2 domains
168
169
Type: has_many
170
171
Related object: L<Koha::Schema::Result::AuthProviderDomain>
172
173
=cut
174
165
175
__PACKAGE__->has_many(
166
__PACKAGE__->has_many(
176
  "domains",
167
  "domains",
177
  "Koha::Schema::Result::AuthProviderDomain",
168
  "Koha::Schema::Result::IdentityProviderDomain",
178
  { "foreign.auth_provider_id" => "self.auth_provider_id" },
169
  { "foreign.identity_provider_id" => "self.identity_provider_id" },
179
  { cascade_copy => 0, cascade_delete => 0 },
170
  { cascade_copy => 0, cascade_delete => 0 },
180
);
171
);
181
172
182
sub koha_object_class {
173
sub koha_object_class {
183
    'Koha::Auth::Provider';
174
    'Koha::Auth::Identity::Provider';
184
}
175
}
185
sub koha_objects_class {
176
sub koha_objects_class {
186
    'Koha::Auth::Providers';
177
    'Koha::Auth::Identity::Providers';
187
}
178
}
188
179
189
1;
180
1;
(-)a/Koha/Schema/Result/AuthProviderDomain.pm (-37 / +37 lines)
Lines 1-12 Link Here
1
use utf8;
1
use utf8;
2
package Koha::Schema::Result::AuthProviderDomain;
2
package Koha::Schema::Result::IdentityProviderDomain;
3
3
4
# Created by DBIx::Class::Schema::Loader
4
# Created by DBIx::Class::Schema::Loader
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
5
# DO NOT MODIFY THE FIRST PART OF THIS FILE
6
6
7
=head1 NAME
7
=head1 NAME
8
8
9
Koha::Schema::Result::AuthProviderDomain
9
Koha::Schema::Result::IdentityProviderDomain
10
10
11
=cut
11
=cut
12
12
Lines 15-29 use warnings; Link Here
15
15
16
use base 'DBIx::Class::Core';
16
use base 'DBIx::Class::Core';
17
17
18
=head1 TABLE: C<auth_provider_domains>
18
=head1 TABLE: C<identity_provider_domains>
19
19
20
=cut
20
=cut
21
21
22
__PACKAGE__->table("auth_provider_domains");
22
__PACKAGE__->table("identity_provider_domains");
23
23
24
=head1 ACCESSORS
24
=head1 ACCESSORS
25
25
26
=head2 auth_provider_domain_id
26
=head2 identity_provider_domain_id
27
27
28
  data_type: 'integer'
28
  data_type: 'integer'
29
  is_auto_increment: 1
29
  is_auto_increment: 1
Lines 31-37 __PACKAGE__->table("auth_provider_domains"); Link Here
31
31
32
unique key, used to identify providers domain
32
unique key, used to identify providers domain
33
33
34
=head2 auth_provider_id
34
=head2 identity_provider_id
35
35
36
  data_type: 'integer'
36
  data_type: 'integer'
37
  is_foreign_key: 1
37
  is_foreign_key: 1
Lines 100-108 Allow provider from staff interface Link Here
100
=cut
100
=cut
101
101
102
__PACKAGE__->add_columns(
102
__PACKAGE__->add_columns(
103
  "auth_provider_domain_id",
103
  "identity_provider_domain_id",
104
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
104
  { data_type => "integer", is_auto_increment => 1, is_nullable => 0 },
105
  "auth_provider_id",
105
  "identity_provider_id",
106
  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
106
  { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
107
  "domain",
107
  "domain",
108
  { data_type => "varchar", is_nullable => 1, size => 100 },
108
  { data_type => "varchar", is_nullable => 1, size => 100 },
Lines 124-144 __PACKAGE__->add_columns( Link Here
124
124
125
=over 4
125
=over 4
126
126
127
=item * L</auth_provider_domain_id>
127
=item * L</identity_provider_domain_id>
128
128
129
=back
129
=back
130
130
131
=cut
131
=cut
132
132
133
__PACKAGE__->set_primary_key("auth_provider_domain_id");
133
__PACKAGE__->set_primary_key("identity_provider_domain_id");
134
134
135
=head1 UNIQUE CONSTRAINTS
135
=head1 UNIQUE CONSTRAINTS
136
136
137
=head2 C<auth_provider_id>
137
=head2 C<identity_provider_id>
138
138
139
=over 4
139
=over 4
140
140
141
=item * L</auth_provider_id>
141
=item * L</identity_provider_id>
142
142
143
=item * L</domain>
143
=item * L</domain>
144
144
Lines 146-170 __PACKAGE__->set_primary_key("auth_provider_domain_id"); Link Here
146
146
147
=cut
147
=cut
148
148
149
__PACKAGE__->add_unique_constraint("auth_provider_id", ["auth_provider_id", "domain"]);
149
__PACKAGE__->add_unique_constraint("identity_provider_id", ["identity_provider_id", "domain"]);
150
150
151
=head1 RELATIONS
151
=head1 RELATIONS
152
152
153
=head2 auth_provider
154
155
Type: belongs_to
156
157
Related object: L<Koha::Schema::Result::AuthProvider>
158
159
=cut
160
161
__PACKAGE__->belongs_to(
162
  "auth_provider",
163
  "Koha::Schema::Result::AuthProvider",
164
  { auth_provider_id => "auth_provider_id" },
165
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "RESTRICT" },
166
);
167
168
=head2 default_category
153
=head2 default_category
169
154
170
Type: belongs_to
155
Type: belongs_to
Lines 205-226 __PACKAGE__->belongs_to( Link Here
205
  },
190
  },
206
);
191
);
207
192
193
=head2 identity_provider
208
194
209
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-08-24 15:03:07
195
Type: belongs_to
210
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:1b0q+e8Ym8icJ6bYAY/Mbw
211
196
212
sub koha_object_class {
197
Related object: L<Koha::Schema::Result::IdentityProvider>
213
    'Koha::Auth::Provider::Domain';
198
214
}
199
=cut
215
sub koha_objects_class {
200
216
    'Koha::Auth::Providers::Domains';
201
__PACKAGE__->belongs_to(
217
}
202
  "identity_provider",
203
  "Koha::Schema::Result::IdentityProvider",
204
  { identity_provider_id => "identity_provider_id" },
205
  { is_deferrable => 1, on_delete => "CASCADE", on_update => "RESTRICT" },
206
);
207
208
209
# Created by DBIx::Class::Schema::Loader v0.07049 @ 2022-10-20 15:27:55
210
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xTbkigJHktgNYDw1Xx01sw
218
211
219
__PACKAGE__->add_columns(
212
__PACKAGE__->add_columns(
220
    '+auto_register'  => { is_boolean => 1 },
213
    '+auto_register'  => { is_boolean => 1 },
221
    '+update_on_auth' => { is_boolean => 1 },
214
    '+update_on_auth' => { is_boolean => 1 },
222
    '+allow_opac'     => { is_boolean => 1 },
215
    '+allow_opac'     => { is_boolean => 1 },
223
    '+allow_staff'    => { is_boolean => 1 },
216
    '+allow_staff'    => { is_boolean => 1 }
224
);
217
);
225
218
219
sub koha_object_class {
220
    'Koha::Auth::Identity::Provider::Domain';
221
}
222
sub koha_objects_class {
223
    'Koha::Auth::Identity::Provider::Domains';
224
}
225
226
1;
226
1;
(-)a/Koha/Template/Plugin/AuthClient.pm (-2 / +2 lines)
Lines 22-28 use Modern::Perl; Link Here
22
use Template::Plugin;
22
use Template::Plugin;
23
use base qw( Template::Plugin );
23
use base qw( Template::Plugin );
24
24
25
use Koha::Auth::Providers;
25
use Koha::Auth::Identity::Providers;
26
26
27
=head1 NAME
27
=head1 NAME
28
28
Lines 49-55 sub get_providers { Link Here
49
    $interface = 'staff'
49
    $interface = 'staff'
50
      if $interface eq 'intranet';
50
      if $interface eq 'intranet';
51
51
52
    my $providers = Koha::Auth::Providers->search( { "domains.allow_$interface" => 1 }, { prefetch => 'domains' } );
52
    my $providers = Koha::Auth::Identity::Providers->search( { "domains.allow_$interface" => 1 }, { prefetch => 'domains' } );
53
    my $base_url  = ( $interface ne 'staff' ) ? "/api/v1/public/oauth/login" : "/api/v1/public/oauth/login";
53
    my $base_url  = ( $interface ne 'staff' ) ? "/api/v1/public/oauth/login" : "/api/v1/public/oauth/login";
54
54
55
    my @urls;
55
    my @urls;
(-)a/admin/authentication_providers.pl (-33 / +33 lines)
Lines 26-49 use Try::Tiny qw( catch try ); Link Here
26
use C4::Auth qw( get_template_and_user );
26
use C4::Auth qw( get_template_and_user );
27
use C4::Output qw( output_html_with_http_headers );
27
use C4::Output qw( output_html_with_http_headers );
28
28
29
use Koha::Auth::Providers;
29
use Koha::Auth::Identity::Providers;
30
30
31
my $input         = CGI->new;
31
my $input         = CGI->new;
32
my $op            = $input->param('op') || 'list';
32
my $op            = $input->param('op') || 'list';
33
my $domain_ops    = $input->param('domain_ops');
33
my $domain_ops    = $input->param('domain_ops');
34
my $auth_provider_id = $input->param('auth_provider_id');
34
my $identity_provider_id = $input->param('identity_provider_id');
35
my $auth_provider;
35
my $identity_provider;
36
36
37
$auth_provider = Koha::Auth::Providers->find($auth_provider_id)
37
$identity_provider = Koha::Auth::Identity::Providers->find($identity_provider_id)
38
    unless !$auth_provider_id;
38
    unless !$identity_provider_id;
39
39
40
my $template_name = $domain_ops ? 'admin/authentication_provider_domains.tt' : 'admin/authentication_providers.tt';
40
my $template_name = $domain_ops ? 'admin/identity_provider_domains.tt' : 'admin/identity_providers.tt';
41
41
42
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
42
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
43
    {   template_name   => $template_name,
43
    {   template_name   => $template_name,
44
        query           => $input,
44
        query           => $input,
45
        type            => "intranet",
45
        type            => "intranet",
46
        flagsrequired   => { parameters => 'manage_authentication_providers' },
46
        flagsrequired   => { parameters => 'manage_identity_providers' },
47
    }
47
    }
48
);
48
);
49
49
Lines 60-66 if ( !$domain_ops && $op eq 'add' ) { Link Here
60
    my $protocol    = $input->param('protocol');
60
    my $protocol    = $input->param('protocol');
61
61
62
    try {
62
    try {
63
        my $provider = Koha::Auth::Provider->new(
63
        my $provider = Koha::Auth::Identity::Provider->new(
64
            {   code        => $code,
64
            {   code        => $code,
65
                config      => $config,
65
                config      => $config,
66
                description => $description,
66
                description => $description,
Lines 71-79 if ( !$domain_ops && $op eq 'add' ) { Link Here
71
            }
71
            }
72
        )->store;
72
        )->store;
73
73
74
        Koha::Auth::Provider::Domain->new(
74
        Koha::Auth::Identity::Provider::Domain->new(
75
            {
75
            {
76
                auth_provider_id => $provider->auth_provider_id,
76
                identity_provider_id => $provider->identity_provider_id,
77
            }
77
            }
78
        )->store;
78
        )->store;
79
79
Lines 97-103 elsif ( $domain_ops && $op eq 'add' ) { Link Here
97
97
98
    my $allow_opac          = $input->param('allow_opac');
98
    my $allow_opac          = $input->param('allow_opac');
99
    my $allow_staff         = $input->param('allow_staff');
99
    my $allow_staff         = $input->param('allow_staff');
100
    my $auth_provider_id    = $input->param('auth_provider_id');
100
    my $identity_provider_id    = $input->param('identity_provider_id');
101
    my $auto_register       = $input->param('auto_register');
101
    my $auto_register       = $input->param('auto_register');
102
    my $default_category_id = $input->param('default_category_id');
102
    my $default_category_id = $input->param('default_category_id');
103
    my $default_library_id  = $input->param('default_library_id');
103
    my $default_library_id  = $input->param('default_library_id');
Lines 106-116 elsif ( $domain_ops && $op eq 'add' ) { Link Here
106
106
107
    try {
107
    try {
108
108
109
        Koha::Auth::Provider::Domain->new(
109
        Koha::Auth::Identity::Provider::Domain->new(
110
            {
110
            {
111
                allow_opac          => $allow_opac,
111
                allow_opac          => $allow_opac,
112
                allow_staff         => $allow_staff,
112
                allow_staff         => $allow_staff,
113
                auth_provider_id    => $auth_provider_id,
113
                identity_provider_id    => $identity_provider_id,
114
                auto_register       => $auto_register,
114
                auto_register       => $auto_register,
115
                default_category_id => $default_category_id,
115
                default_category_id => $default_category_id,
116
                default_library_id  => $default_library_id,
116
                default_library_id  => $default_library_id,
Lines 137-145 elsif ( $domain_ops && $op eq 'add' ) { Link Here
137
}
137
}
138
elsif ( !$domain_ops && $op eq 'edit_form' ) {
138
elsif ( !$domain_ops && $op eq 'edit_form' ) {
139
139
140
    if ( $auth_provider ) {
140
    if ( $identity_provider ) {
141
        $template->param(
141
        $template->param(
142
            auth_provider => $auth_provider
142
            identity_provider => $identity_provider
143
        );
143
        );
144
    }
144
    }
145
    else {
145
    else {
Lines 152-166 elsif ( !$domain_ops && $op eq 'edit_form' ) { Link Here
152
    }
152
    }
153
}
153
}
154
elsif ( $domain_ops && $op eq 'edit_form' ) {
154
elsif ( $domain_ops && $op eq 'edit_form' ) {
155
    my $auth_provider_domain_id = $input->param('auth_provider_domain_id');
155
    my $identity_provider_domain_id = $input->param('identity_provider_domain_id');
156
    my $auth_provider_domain;
156
    my $identity_provider_domain;
157
157
158
    $auth_provider_domain = Koha::Auth::Provider::Domains->find($auth_provider_domain_id)
158
    $identity_provider_domain = Koha::Auth::Identity::Provider::Domains->find($identity_provider_domain_id)
159
        unless !$auth_provider_domain_id;
159
        unless !$identity_provider_domain_id;
160
160
161
    if ( $auth_provider_domain ) {
161
    if ( $identity_provider_domain ) {
162
        $template->param(
162
        $template->param(
163
            auth_provider_domain => $auth_provider_domain
163
            identity_provider_domain => $identity_provider_domain
164
        );
164
        );
165
    }
165
    }
166
    else {
166
    else {
Lines 174-180 elsif ( $domain_ops && $op eq 'edit_form' ) { Link Here
174
}
174
}
175
elsif ( !$domain_ops && $op eq 'edit_save' ) {
175
elsif ( !$domain_ops && $op eq 'edit_save' ) {
176
176
177
    if ( $auth_provider ) {
177
    if ( $identity_provider ) {
178
178
179
        my $code        = $input->param('code');
179
        my $code        = $input->param('code');
180
        my $config      = $input->param('config');
180
        my $config      = $input->param('config');
Lines 186-192 elsif ( !$domain_ops && $op eq 'edit_save' ) { Link Here
186
186
187
        try {
187
        try {
188
188
189
            $auth_provider->set(
189
            $identity_provider->set(
190
                {   code        => $code,
190
                {   code        => $code,
191
                    config      => $config,
191
                    config      => $config,
192
                    description => $description,
192
                    description => $description,
Lines 225-239 elsif ( !$domain_ops && $op eq 'edit_save' ) { Link Here
225
}
225
}
226
elsif ( $domain_ops && $op eq 'edit_save' ) {
226
elsif ( $domain_ops && $op eq 'edit_save' ) {
227
227
228
    my $auth_provider_domain_id = $input->param('auth_provider_domain_id');
228
    my $identity_provider_domain_id = $input->param('identity_provider_domain_id');
229
    my $auth_provider_domain;
229
    my $identity_provider_domain;
230
230
231
    $auth_provider_domain = Koha::Auth::Provider::Domains->find($auth_provider_domain_id)
231
    $identity_provider_domain = Koha::Auth::Identity::Provider::Domains->find($identity_provider_domain_id)
232
        unless !$auth_provider_domain_id;
232
        unless !$identity_provider_domain_id;
233
233
234
    if ( $auth_provider_domain ) {
234
    if ( $identity_provider_domain ) {
235
235
236
        my $auth_provider_id    = $input->param('auth_provider_id');
236
        my $identity_provider_id    = $input->param('identity_provider_id');
237
        my $domain              = $input->param('domain');
237
        my $domain              = $input->param('domain');
238
        my $auto_register       = $input->param('auto_register');
238
        my $auto_register       = $input->param('auto_register');
239
        my $update_on_auth      = $input->param('update_on_auth');
239
        my $update_on_auth      = $input->param('update_on_auth');
Lines 244-252 elsif ( $domain_ops && $op eq 'edit_save' ) { Link Here
244
244
245
        try {
245
        try {
246
246
247
            $auth_provider_domain->set(
247
            $identity_provider_domain->set(
248
                {
248
                {
249
                    auth_provider_id    => $auth_provider_id,
249
                    identity_provider_id    => $identity_provider_id,
250
                    domain              => $domain,
250
                    domain              => $domain,
251
                    auto_register       => $auto_register,
251
                    auto_register       => $auto_register,
252
                    update_on_auth      => $update_on_auth,
252
                    update_on_auth      => $update_on_auth,
Lines 286-293 elsif ( $domain_ops && $op eq 'edit_save' ) { Link Here
286
286
287
if ( $domain_ops ) {
287
if ( $domain_ops ) {
288
    $template->param(
288
    $template->param(
289
        auth_provider_code => $auth_provider->code,
289
        identity_provider_code => $identity_provider->code,
290
        auth_provider_id   => $auth_provider_id,
290
        identity_provider_id   => $identity_provider_id,
291
    );
291
    );
292
}
292
}
293
293
(-)a/api/v1/swagger/definitions/auth_provider.yaml (-2 / +4 lines)
Lines 1-7 Link Here
1
---
1
---
2
type: object
2
type: object
3
properties:
3
properties:
4
  auth_provider_id:
4
  identity_provider_id:
5
    type: integer
5
    type: integer
6
    description: Internally assigned authentication provider identifier
6
    description: Internally assigned authentication provider identifier
7
    readOnly: true
7
    readOnly: true
Lines 36-42 properties: Link Here
36
    type: object
36
    type: object
37
  icon_url:
37
  icon_url:
38
    description: Icon url
38
    description: Icon url
39
    type: string
39
    type:
40
     - string
41
     - "null"
40
  domains:
42
  domains:
41
    description: Configured domains for the authentication provider
43
    description: Configured domains for the authentication provider
42
    type:
44
    type:
(-)a/api/v1/swagger/definitions/auth_provider_domain.yaml (-4 / +3 lines)
Lines 1-11 Link Here
1
---
1
---
2
type: object
2
type: object
3
properties:
3
properties:
4
  auth_provider_domain_id:
4
  identity_provider_domain_id:
5
    type: integer
5
    type: integer
6
    description: Internally assigned authentication provider domain identifier
6
    description: Internally assigned authentication provider domain identifier
7
    readOnly: true
7
    readOnly: true
8
  auth_provider_id:
8
  identity_provider_id:
9
    type: integer
9
    type: integer
10
    description: Internally assigned authentication provider identifier
10
    description: Internally assigned authentication provider identifier
11
  domain:
11
  domain:
Lines 37-44 properties: Link Here
37
    type: boolean
37
    type: boolean
38
additionalProperties: false
38
additionalProperties: false
39
required:
39
required:
40
  - auth_provider_domain_id
40
  - identity_provider_domain_id
41
  - auth_provider_id
42
  - domain
41
  - domain
43
  - auto_register
42
  - auto_register
44
  - update_on_auth
43
  - update_on_auth
(-)a/api/v1/swagger/paths/auth.yaml (-1 / +489 lines)
Lines 567-570 Link Here
567
          $ref: ../swagger.yaml#/definitions/error
567
          $ref: ../swagger.yaml#/definitions/error
568
    x-koha-authorization:
568
    x-koha-authorization:
569
      permissions:
569
      permissions:
570
        parameters: manage_authentication_providers
570
        parameters: manage_authentication_providers
571
/auth/identity_providers:
572
  get:
573
    x-mojo-to: Auth::Identity::Providers#list
574
    operationId: listIdentityProviders
575
    tags:
576
      - identity_providers
577
    summary: List configured authentication providers
578
    parameters:
579
      - $ref: ../swagger.yaml#/parameters/match
580
      - $ref: ../swagger.yaml#/parameters/order_by
581
      - $ref: ../swagger.yaml#/parameters/page
582
      - $ref: ../swagger.yaml#/parameters/per_page
583
      - $ref: ../swagger.yaml#/parameters/q_param
584
      - $ref: ../swagger.yaml#/parameters/q_body
585
      - $ref: ../swagger.yaml#/parameters/q_header
586
      - $ref: ../swagger.yaml#/parameters/request_id_header
587
      - name: x-koha-embed
588
        in: header
589
        required: false
590
        description: Embed list sent as a request header
591
        type: array
592
        items:
593
          type: string
594
          enum:
595
            - domains
596
        collectionFormat: csv
597
    produces:
598
      - application/json
599
    responses:
600
      "200":
601
        description: A list of authentication providers
602
        schema:
603
          type: array
604
          items:
605
            $ref: ../swagger.yaml#/definitions/identity_provider
606
      "400":
607
        description: Bad Request
608
        schema:
609
          $ref: ../swagger.yaml#/definitions/error
610
      "403":
611
        description: Access forbidden
612
        schema:
613
          $ref: ../swagger.yaml#/definitions/error
614
      "500":
615
        description: |
616
          Internal server error. Possible `error_code` attribute values:
617
618
          * `internal_server_error`
619
        schema:
620
          $ref: ../swagger.yaml#/definitions/error
621
      "503":
622
        description: Under maintenance
623
        schema:
624
          $ref: ../swagger.yaml#/definitions/error
625
    x-koha-authorization:
626
      permissions:
627
        parameters: manage_identity_providers
628
  post:
629
    x-mojo-to: Auth::Identity::Providers#add
630
    operationId: addIdentityProvider
631
    tags:
632
      - identity_providers
633
    summary: Add a new authentication provider
634
    parameters:
635
      - name: body
636
        in: body
637
        description: |
638
          A JSON object containing OAuth provider parameters.
639
640
          The `config` object required attributes depends on the chosen `protocol`
641
642
          ## OAuth
643
644
          Requires:
645
646
          * key
647
          * secret
648
          * authorize_url
649
          * token_url
650
651
          ## OIDC
652
653
          Requires:
654
655
          * key
656
          * secret
657
          * well_known_url
658
        required: true
659
        schema:
660
          $ref: ../swagger.yaml#/definitions/identity_provider
661
    produces:
662
      - application/json
663
    responses:
664
      "201":
665
        description: The generated authentication provider
666
        schema:
667
          $ref: ../swagger.yaml#/definitions/identity_provider
668
      "400":
669
        description: Bad Request
670
        schema:
671
          $ref: ../swagger.yaml#/definitions/error
672
      "403":
673
        description: Access forbidden
674
        schema:
675
          $ref: ../swagger.yaml#/definitions/error
676
      "500":
677
        description: |
678
          Internal server error. Possible `error_code` attribute values:
679
680
          * `internal_server_error`
681
        schema:
682
          $ref: ../swagger.yaml#/definitions/error
683
      "503":
684
        description: Under maintenance
685
        schema:
686
          $ref: ../swagger.yaml#/definitions/error
687
    x-koha-authorization:
688
      permissions:
689
        parameters: manage_identity_providers
690
"/auth/identity_providers/{identity_provider_id}":
691
  get:
692
    x-mojo-to: Auth::Identity::Providers#get
693
    operationId: getIdentityProvider
694
    tags:
695
      - identity_providers
696
    summary: Get authentication provider
697
    parameters:
698
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
699
      - name: x-koha-embed
700
        in: header
701
        required: false
702
        description: Embed list sent as a request header
703
        type: array
704
        items:
705
          type: string
706
          enum:
707
            - domains
708
        collectionFormat: csv
709
    produces:
710
      - application/json
711
    responses:
712
      "200":
713
        description: An authentication provider
714
        schema:
715
          $ref: ../swagger.yaml#/definitions/identity_provider
716
      "404":
717
        description: Object not found
718
        schema:
719
          $ref: ../swagger.yaml#/definitions/error
720
      "500":
721
        description: |
722
          Internal server error. Possible `error_code` attribute values:
723
724
          * `internal_server_error`
725
        schema:
726
          $ref: ../swagger.yaml#/definitions/error
727
      "503":
728
        description: Under maintenance
729
        schema:
730
          $ref: ../swagger.yaml#/definitions/error
731
    x-koha-authorization:
732
      permissions:
733
        parameters: manage_identity_providers
734
  put:
735
    x-mojo-to: Auth::Identity::Providers#update
736
    operationId: updateIdentityProvider
737
    tags:
738
      - identity_providers
739
    summary: Update an authentication provider
740
    parameters:
741
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
742
      - name: body
743
        in: body
744
        description: |
745
          A JSON object containing OAuth provider parameters.
746
747
          The `config` object required attributes depends on the chosen `protocol`
748
749
          ## OAuth
750
751
          Requires:
752
753
          * key
754
          * secret
755
          * authorize_url
756
          * token_url
757
758
          ## OIDC
759
760
          Requires:
761
762
          * key
763
          * secret
764
          * well_known_url
765
        required: true
766
        schema:
767
          $ref: ../swagger.yaml#/definitions/identity_provider
768
    produces:
769
      - application/json
770
    responses:
771
      "200":
772
        description: Updated authentication provider
773
        schema:
774
          $ref: ../swagger.yaml#/definitions/identity_provider
775
      "400":
776
        description: Bad Request
777
        schema:
778
          $ref: ../swagger.yaml#/definitions/error
779
      "403":
780
        description: Access forbidden
781
        schema:
782
          $ref: ../swagger.yaml#/definitions/error
783
      "404":
784
        description: Object not found
785
        schema:
786
          $ref: ../swagger.yaml#/definitions/error
787
      "500":
788
        description: |
789
          Internal server error. Possible `error_code` attribute values:
790
791
          * `internal_server_error`
792
        schema:
793
          $ref: ../swagger.yaml#/definitions/error
794
      "503":
795
        description: Under maintenance
796
        schema:
797
          $ref: ../swagger.yaml#/definitions/error
798
    x-koha-authorization:
799
      permissions:
800
        parameters: manage_identity_providers
801
  delete:
802
    x-mojo-to: Auth::Identity::Providers#delete
803
    operationId: delIdentityProvider
804
    tags:
805
      - identity_providers
806
    summary: Delete authentication provider
807
    parameters:
808
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
809
    produces:
810
      - application/json
811
    responses:
812
      "204":
813
        description: Authentication provider deleted
814
      "401":
815
        description: Authentication required
816
        schema:
817
          $ref: ../swagger.yaml#/definitions/error
818
      "403":
819
        description: Access forbidden
820
        schema:
821
          $ref: ../swagger.yaml#/definitions/error
822
      "404":
823
        description: City not found
824
        schema:
825
          $ref: ../swagger.yaml#/definitions/error
826
      "500":
827
        description: |
828
          Internal server error. Possible `error_code` attribute values:
829
830
          * `internal_server_error`
831
      "503":
832
        description: Under maintenance
833
        schema:
834
          $ref: ../swagger.yaml#/definitions/error
835
    x-koha-authorization:
836
      permissions:
837
        parameters: manage_identity_providers
838
"/auth/identity_providers/{identity_provider_id}/domains":
839
  get:
840
    x-mojo-to: Auth::Identity::Provider::Domains#list
841
    operationId: listIdentityProviderDomains
842
    tags:
843
      - identity_providers
844
    summary: Get authentication provider configured domains
845
    parameters:
846
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
847
      - $ref: ../swagger.yaml#/parameters/match
848
      - $ref: ../swagger.yaml#/parameters/order_by
849
      - $ref: ../swagger.yaml#/parameters/page
850
      - $ref: ../swagger.yaml#/parameters/per_page
851
      - $ref: ../swagger.yaml#/parameters/q_param
852
      - $ref: ../swagger.yaml#/parameters/q_body
853
      - $ref: ../swagger.yaml#/parameters/q_header
854
      - $ref: ../swagger.yaml#/parameters/request_id_header
855
      - name: x-koha-embed
856
        in: header
857
        required: false
858
        description: Embed list sent as a request header
859
        type: array
860
        items:
861
          type: string
862
          enum:
863
            - domains
864
        collectionFormat: csv
865
    produces:
866
      - application/json
867
    responses:
868
      "200":
869
        description: An authentication provider
870
        schema:
871
          items:
872
            $ref: ../swagger.yaml#/definitions/identity_provider_domain
873
      "404":
874
        description: Object not found
875
        schema:
876
          $ref: ../swagger.yaml#/definitions/error
877
      "500":
878
        description: |
879
          Internal server error. Possible `error_code` attribute values:
880
881
          * `internal_server_error`
882
        schema:
883
          $ref: ../swagger.yaml#/definitions/error
884
      "503":
885
        description: Under maintenance
886
        schema:
887
          $ref: ../swagger.yaml#/definitions/error
888
    x-koha-authorization:
889
      permissions:
890
        parameters: manage_identity_providers
891
  post:
892
    x-mojo-to: Auth::Identity::Provider::Domains#add
893
    operationId: addIdentityProviderDomain
894
    tags:
895
      - identity_providers
896
    summary: Add an authentication provider domain
897
    parameters:
898
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
899
      - name: body
900
        in: body
901
        description: An authentication provider domain object
902
        required: true
903
        schema:
904
          $ref: ../swagger.yaml#/definitions/identity_provider_domain
905
    produces:
906
      - application/json
907
    responses:
908
      "201":
909
        description: Updated authentication provider domain
910
        schema:
911
          $ref: ../swagger.yaml#/definitions/identity_provider_domain
912
      "400":
913
        description: Bad Request
914
        schema:
915
          $ref: ../swagger.yaml#/definitions/error
916
      "403":
917
        description: Access forbidden
918
        schema:
919
          $ref: ../swagger.yaml#/definitions/error
920
      "404":
921
        description: Object not found
922
        schema:
923
          $ref: ../swagger.yaml#/definitions/error
924
      "500":
925
        description: |
926
          Internal server error. Possible `error_code` attribute values:
927
928
          * `internal_server_error`
929
        schema:
930
          $ref: ../swagger.yaml#/definitions/error
931
      "503":
932
        description: Under maintenance
933
        schema:
934
          $ref: ../swagger.yaml#/definitions/error
935
    x-koha-authorization:
936
      permissions:
937
        parameters: manage_identity_providers
938
"/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}":
939
  get:
940
    x-mojo-to: Auth::Identity::Provider::Domains#get
941
    operationId: getIdentityProviderDomain
942
    tags:
943
      - identity_providers
944
    summary: Get authentication provider domain
945
    parameters:
946
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
947
      - $ref: ../swagger.yaml#/parameters/identity_provider_domain_id_pp
948
    produces:
949
      - application/json
950
    responses:
951
      "200":
952
        description: An authentication provider
953
        schema:
954
          $ref: ../swagger.yaml#/definitions/identity_provider_domain
955
      "404":
956
        description: Object not found
957
        schema:
958
          $ref: ../swagger.yaml#/definitions/error
959
      "500":
960
        description: |
961
          Internal server error. Possible `error_code` attribute values:
962
963
          * `internal_server_error`
964
        schema:
965
          $ref: ../swagger.yaml#/definitions/error
966
      "503":
967
        description: Under maintenance
968
        schema:
969
          $ref: ../swagger.yaml#/definitions/error
970
    x-koha-authorization:
971
      permissions:
972
        parameters: manage_identity_providers
973
  put:
974
    x-mojo-to: Auth::Identity::Provider::Domains#update
975
    operationId: updateIdentityProviderDomain
976
    tags:
977
      - identity_providers
978
    summary: Update an authentication provider domain
979
    parameters:
980
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
981
      - $ref: ../swagger.yaml#/parameters/identity_provider_domain_id_pp
982
      - name: body
983
        in: body
984
        description: An authentication provider domain object
985
        required: true
986
        schema:
987
          $ref: ../swagger.yaml#/definitions/identity_provider_domain
988
    produces:
989
      - application/json
990
    responses:
991
      "200":
992
        description: Updated authentication provider domain
993
        schema:
994
          $ref: ../swagger.yaml#/definitions/identity_provider_domain
995
      "400":
996
        description: Bad Request
997
        schema:
998
          $ref: ../swagger.yaml#/definitions/error
999
      "403":
1000
        description: Access forbidden
1001
        schema:
1002
          $ref: ../swagger.yaml#/definitions/error
1003
      "404":
1004
        description: Object not found
1005
        schema:
1006
          $ref: ../swagger.yaml#/definitions/error
1007
      "500":
1008
        description: |
1009
          Internal server error. Possible `error_code` attribute values:
1010
1011
          * `internal_server_error`
1012
        schema:
1013
          $ref: ../swagger.yaml#/definitions/error
1014
      "503":
1015
        description: Under maintenance
1016
        schema:
1017
          $ref: ../swagger.yaml#/definitions/error
1018
    x-koha-authorization:
1019
      permissions:
1020
        parameters: manage_identity_providers
1021
  delete:
1022
    x-mojo-to: Auth::Identity::Provider::Domains#delete
1023
    operationId: delIdentityProviderDomain
1024
    tags:
1025
      - identity_providers
1026
    summary: Delete authentication provider
1027
    parameters:
1028
      - $ref: ../swagger.yaml#/parameters/identity_provider_id_pp
1029
      - $ref: ../swagger.yaml#/parameters/identity_provider_domain_id_pp
1030
    produces:
1031
      - application/json
1032
    responses:
1033
      "204":
1034
        description: Authentication provider deleted
1035
      "401":
1036
        description: Authentication required
1037
        schema:
1038
          $ref: ../swagger.yaml#/definitions/error
1039
      "403":
1040
        description: Access forbidden
1041
        schema:
1042
          $ref: ../swagger.yaml#/definitions/error
1043
      "404":
1044
        description: City not found
1045
        schema:
1046
          $ref: ../swagger.yaml#/definitions/error
1047
      "500":
1048
        description: |
1049
          Internal server error. Possible `error_code` attribute values:
1050
1051
          * `internal_server_error`
1052
      "503":
1053
        description: Under maintenance
1054
        schema:
1055
          $ref: ../swagger.yaml#/definitions/error
1056
    x-koha-authorization:
1057
      permissions:
1058
        parameters: manage_identity_providers
(-)a/api/v1/swagger/swagger.yaml (-19 / +19 lines)
Lines 8-17 definitions: Link Here
8
    $ref: ./definitions/advancededitormacro.yaml
8
    $ref: ./definitions/advancededitormacro.yaml
9
  allows_renewal:
9
  allows_renewal:
10
    $ref: ./definitions/allows_renewal.yaml
10
    $ref: ./definitions/allows_renewal.yaml
11
  auth_provider:
11
  identity_provider:
12
    "$ref": ./definitions/auth_provider.yaml
12
    "$ref": ./definitions/identity_provider.yaml
13
  auth_provider_domain:
13
  identity_provider_domain:
14
    "$ref": ./definitions/auth_provider_domain.yaml
14
    "$ref": ./definitions/identity_provider_domain.yaml
15
  basket:
15
  basket:
16
    $ref: ./definitions/basket.yaml
16
    $ref: ./definitions/basket.yaml
17
  bundle_link:
17
  bundle_link:
Lines 119-132 paths: Link Here
119
    $ref: paths/auth.yaml#/~1auth~1two-factor~1registration
119
    $ref: paths/auth.yaml#/~1auth~1two-factor~1registration
120
  /auth/two-factor/registration/verification:
120
  /auth/two-factor/registration/verification:
121
    $ref: paths/auth.yaml#/~1auth~1two-factor~1registration~1verification
121
    $ref: paths/auth.yaml#/~1auth~1two-factor~1registration~1verification
122
  /auth/providers:
122
  /auth/identity_providers:
123
    $ref: paths/auth.yaml#/~1auth~1providers
123
    $ref: paths/auth.yaml#/~1auth~1identity_providers
124
  "/auth/providers/{auth_provider_id}":
124
  "/auth/identity_providers/{identity_provider_id}":
125
    $ref: paths/auth.yaml#/~1auth~1providers~1{auth_provider_id}
125
    $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}
126
  "/auth/providers/{auth_provider_id}/domains":
126
  "/auth/identity_providers/{identity_provider_id}/domains":
127
    $ref: paths/auth.yaml#/~1auth~1providers~1{auth_provider_id}~1domains
127
    $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains
128
  "/auth/providers/{auth_provider_id}/domains/{auth_provider_domain_id}":
128
  "/auth/identity_providers/{identity_provider_id}/domains/{identity_provider_domain_id}":
129
    $ref: paths/auth.yaml#/~1auth~1providers~1{auth_provider_id}~1domains~1{auth_provider_domain_id}
129
    $ref: paths/auth.yaml#/~1auth~1identity_providers~1{identity_provider_id}~1domains~1{identity_provider_domain_id}
130
  "/biblios/{biblio_id}":
130
  "/biblios/{biblio_id}":
131
    $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}"
131
    $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}"
132
  "/biblios/{biblio_id}/checkouts":
132
  "/biblios/{biblio_id}/checkouts":
Lines 284-299 parameters: Link Here
284
    name: advancededitormacro_id
284
    name: advancededitormacro_id
285
    required: true
285
    required: true
286
    type: integer
286
    type: integer
287
  auth_provider_id_pp:
287
  identity_provider_id_pp:
288
    description: Authentication provider internal identifier
288
    description: Authentication provider internal identifier
289
    in: path
289
    in: path
290
    name: auth_provider_id
290
    name: identity_provider_id
291
    required: true
291
    required: true
292
    type: integer
292
    type: integer
293
  auth_provider_domain_id_pp:
293
  identity_provider_domain_id_pp:
294
    description: Authentication provider domain internal identifier
294
    description: Authentication provider domain internal identifier
295
    in: path
295
    in: path
296
    name: auth_provider_domain_id
296
    name: identity_provider_domain_id
297
    required: true
297
    required: true
298
    type: integer
298
    type: integer
299
  biblio_id_pp:
299
  biblio_id_pp:
Lines 604-612 tags: Link Here
604
  - description: "Manage article requests\n"
604
  - description: "Manage article requests\n"
605
    name: article_requests
605
    name: article_requests
606
    x-displayName: Article requests
606
    x-displayName: Article requests
607
  - description: "Manage authentication providers\n"
607
  - description: "Manage identity providers\n"
608
    name: auth_providers
608
    name: identity_providers
609
    x-displayName: Authentication providers
609
    x-displayName: Identity providers
610
  - description: "Manage baskets for the acquisitions module\n"
610
  - description: "Manage baskets for the acquisitions module\n"
611
    name: baskets
611
    name: baskets
612
    x-displayName: Baskets
612
    x-displayName: Baskets
(-)a/installer/data/mysql/atomicupdate/bug_31378.pl (-20 / +20 lines)
Lines 3-9 use C4::Context; Link Here
3
3
4
return {
4
return {
5
    bug_number  => "31378",
5
    bug_number  => "31378",
6
    description => "Add auth_provider and auth_provider_domains configuration tables",
6
    description => "Add identity_provider and identity_provider_domains configuration tables",
7
    up => sub {
7
    up => sub {
8
        my ($args) = @_;
8
        my ($args) = @_;
9
        my ($dbh, $out) = @$args{qw(dbh out)};
9
        my ($dbh, $out) = @$args{qw(dbh out)};
Lines 12-26 return { Link Here
12
        $dbh->do(qq{
12
        $dbh->do(qq{
13
            INSERT IGNORE permissions (module_bit, code, description)
13
            INSERT IGNORE permissions (module_bit, code, description)
14
            VALUES
14
            VALUES
15
            ( 3, 'manage_authentication_providers', 'Manage authentication providers')
15
            ( 3, 'manage_identity_providers', 'Manage authentication providers')
16
        });
16
        });
17
17
18
        say $out "manage_authentication_providers permission added";
18
        say $out "manage_identity_providers permission added";
19
19
20
        unless (TableExists('auth_providers')) {
20
        unless (TableExists('identity_providers')) {
21
            $dbh->do(q{
21
            $dbh->do(q{
22
                CREATE TABLE `auth_providers` (
22
                CREATE TABLE `identity_providers` (
23
                `auth_provider_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the provider',
23
                `identity_provider_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the provider',
24
                `code` varchar(20) NOT NULL COMMENT 'Provider code',
24
                `code` varchar(20) NOT NULL COMMENT 'Provider code',
25
                `description` varchar(255) NOT NULL COMMENT 'Description for the provider',
25
                `description` varchar(255) NOT NULL COMMENT 'Description for the provider',
26
                `protocol` enum('OAuth', 'OIDC', 'LDAP', 'CAS') COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Protocol provider speaks',
26
                `protocol` enum('OAuth', 'OIDC', 'LDAP', 'CAS') COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Protocol provider speaks',
Lines 28-60 return { Link Here
28
                `mapping` longtext NOT NULL DEFAULT '{}' COMMENT 'Configuration to map provider data to Koha user',
28
                `mapping` longtext NOT NULL DEFAULT '{}' COMMENT 'Configuration to map provider data to Koha user',
29
                `matchpoint` enum('email','userid','cardnumber') NOT NULL COMMENT 'The patron attribute to be used as matchpoint',
29
                `matchpoint` enum('email','userid','cardnumber') NOT NULL COMMENT 'The patron attribute to be used as matchpoint',
30
                `icon_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Provider icon URL',
30
                `icon_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Provider icon URL',
31
                PRIMARY KEY (`auth_provider_id`),
31
                PRIMARY KEY (`identity_provider_id`),
32
                UNIQUE KEY (`code`),
32
                UNIQUE KEY (`code`),
33
                KEY `protocol` (`protocol`)
33
                KEY `protocol` (`protocol`)
34
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
34
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
35
            });
35
            });
36
        }
36
        }
37
37
38
        unless (TableExists('auth_provider_domains')) {
38
        unless (TableExists('identity_provider_domains')) {
39
            $dbh->do(q{
39
            $dbh->do(q{
40
                CREATE TABLE `auth_provider_domains` (
40
                CREATE TABLE `identity_provider_domains` (
41
                    `auth_provider_domain_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify providers domain',
41
                    `identity_provider_domain_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify providers domain',
42
                    `auth_provider_id` int(11) NOT NULL COMMENT 'Reference to provider',
42
                    `identity_provider_id` int(11) NOT NULL COMMENT 'Reference to provider',
43
                    `domain` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Domain name. If null means all domains',
43
                    `domain` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Domain name. If null means all domains',
44
                    `auto_register` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register',
44
                    `auto_register` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register',
45
                    `update_on_auth` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Update user data on auth login',
45
                    `update_on_auth` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Update user data on auth login',
46
                    `default_library_id` varchar(10) DEFAULT NULL COMMENT 'Default library to create user if auto register is enabled',
46
                    `default_library_id` varchar(10) DEFAULT NULL COMMENT 'Default library to create user if auto register is enabled',
47
                    `default_category_id` varchar(10) DEFAULT NULL COMMENT 'Default category to create user if auto register is enabled',
47
                    `default_category_id` varchar(10) DEFAULT NULL COMMENT 'Default category to create user if auto register is enabled',
48
                    `allow_opac` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Allow provider from opac interface',
48
                    `allow_opac` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Allow provider from opac interface',
49
                    `allow_staff` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Allow provider from staff interface',
49
                    `allow_staff` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow provider from staff interface',
50
                    PRIMARY KEY (`auth_provider_domain_id`),
50
                    PRIMARY KEY (`identity_provider_domain_id`),
51
                    UNIQUE KEY (`auth_provider_id`, `domain`),
51
                    UNIQUE KEY (`identity_provider_id`, `domain`),
52
                    KEY `domain` (`domain`),
52
                    KEY `domain` (`domain`),
53
                    KEY `allow_opac` (`allow_opac`),
53
                    KEY `allow_opac` (`allow_opac`),
54
                    KEY `allow_staff` (`allow_staff`),
54
                    KEY `allow_staff` (`allow_staff`),
55
                    CONSTRAINT `auth_provider_domain_ibfk_1` FOREIGN KEY (`auth_provider_id`) REFERENCES `auth_providers` (`auth_provider_id`) ON DELETE CASCADE,
55
                    CONSTRAINT `identity_provider_domain_ibfk_1` FOREIGN KEY (`identity_provider_id`) REFERENCES `identity_providers` (`identity_provider_id`) ON DELETE CASCADE,
56
                    CONSTRAINT `auth_provider_domain_ibfk_2` FOREIGN KEY (`default_library_id`) REFERENCES `branches` (`branchcode`) ON DELETE CASCADE,
56
                    CONSTRAINT `identity_provider_domain_ibfk_2` FOREIGN KEY (`default_library_id`) REFERENCES `branches` (`branchcode`) ON DELETE CASCADE,
57
                    CONSTRAINT `auth_provider_domain_ibfk_3` FOREIGN KEY (`default_category_id`) REFERENCES `categories` (`categorycode`) ON DELETE CASCADE
57
                    CONSTRAINT `identity_provider_domain_ibfk_3` FOREIGN KEY (`default_category_id`) REFERENCES `categories` (`categorycode`) ON DELETE CASCADE
58
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
58
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
59
            });
59
            });
60
        }
60
        }
Lines 63-69 return { Link Here
63
            # Print useful stuff here
63
            # Print useful stuff here
64
            say $out "Setting google provider";
64
            say $out "Setting google provider";
65
            $dbh->do(q{
65
            $dbh->do(q{
66
                INSERT INTO `auth_providers` (name, protocol, config, mapping), auto_register, registration_config, interface)
66
                INSERT INTO `identity_providers` (name, protocol, config, mapping), auto_register, registration_config, interface)
67
                SELECT  'google' as name,
67
                SELECT  'google' as name,
68
                        'OIDC' as protocol,
68
                        'OIDC' as protocol,
69
                        JSON_OBJECT("key", k.value, "secret", s.value, "well_known_url", "https://accounts.google.com/.well-known/openid-configuration", "scope", "openid email profile") as config,
69
                        JSON_OBJECT("key", k.value, "secret", s.value, "well_known_url", "https://accounts.google.com/.well-known/openid-configuration", "scope", "openid email profile") as config,
Lines 75-81 return { Link Here
75
            });
75
            });
76
76
77
            $dbh->do(q{
77
            $dbh->do(q{
78
                INSERT INTO `auth_provider_domains` (auth_provider_id, domain, auto_register, update_on_auth, default_library_id, default_category_id, allow_opac, allow_staff)
78
                INSERT INTO `identity_provider_domains` (identity_provider_id, domain, auto_register, update_on_auth, default_library_id, default_category_id, allow_opac, allow_staff)
79
                        p.id as provider_id,
79
                        p.id as provider_id,
80
                        d.value as domain,
80
                        d.value as domain,
81
                        r.value as auto_register,
81
                        r.value as auto_register,
Lines 85-91 return { Link Here
85
                        1 as allow_opac,
85
                        1 as allow_opac,
86
                        0 as allow_interface
86
                        0 as allow_interface
87
                FROM
87
                FROM
88
                    (SELECT id FROM `auth_provider` WHERE name = 'google') p
88
                    (SELECT id FROM `identity_provider` WHERE name = 'google') p
89
                JOIN
89
                JOIN
90
                    (SELECT CASE WHEN value = '' OR value IS NULL THEN NULL ELSE value END as value FROM `systempreferences` where variable = 'GoogleOpenIDConnectDomain') d
90
                    (SELECT CASE WHEN value = '' OR value IS NULL THEN NULL ELSE value END as value FROM `systempreferences` where variable = 'GoogleOpenIDConnectDomain') d
91
                JOIN
91
                JOIN
(-)a/installer/data/mysql/kohastructure.sql (-16 / +16 lines)
Lines 850-863 CREATE TABLE `auth_header` ( Link Here
850
/*!40101 SET character_set_client = @saved_cs_client */;
850
/*!40101 SET character_set_client = @saved_cs_client */;
851
851
852
--
852
--
853
-- Table structure for table `auth_provider`
853
-- Table structure for table `identity_provider`
854
--
854
--
855
855
856
DROP TABLE IF EXISTS `auth_providers`;
856
DROP TABLE IF EXISTS `identity_providers`;
857
/*!40101 SET @saved_cs_client     = @@character_set_client */;
857
/*!40101 SET @saved_cs_client     = @@character_set_client */;
858
/*!40101 SET character_set_client = utf8 */;
858
/*!40101 SET character_set_client = utf8 */;
859
CREATE TABLE `auth_providers` (
859
CREATE TABLE `identity_providers` (
860
  `auth_provider_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the provider',
860
  `identity_provider_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify the provider',
861
  `code` varchar(20) NOT NULL COMMENT 'Provider code',
861
  `code` varchar(20) NOT NULL COMMENT 'Provider code',
862
  `description` varchar(255) NOT NULL COMMENT 'Description for the provider',
862
  `description` varchar(255) NOT NULL COMMENT 'Description for the provider',
863
  `protocol` enum('OAuth', 'OIDC', 'LDAP', 'CAS') COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Protocol provider speaks',
863
  `protocol` enum('OAuth', 'OIDC', 'LDAP', 'CAS') COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Protocol provider speaks',
Lines 865-901 CREATE TABLE `auth_providers` ( Link Here
865
  `mapping` longtext NOT NULL DEFAULT '{}' COMMENT 'Configuration to map provider data to Koha user',
865
  `mapping` longtext NOT NULL DEFAULT '{}' COMMENT 'Configuration to map provider data to Koha user',
866
  `matchpoint` enum('email','userid','cardnumber') NOT NULL COMMENT 'The patron attribute to be used as matchpoint',
866
  `matchpoint` enum('email','userid','cardnumber') NOT NULL COMMENT 'The patron attribute to be used as matchpoint',
867
  `icon_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Provider icon URL',
867
  `icon_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Provider icon URL',
868
  PRIMARY KEY (`auth_provider_id`),
868
  PRIMARY KEY (`identity_provider_id`),
869
  UNIQUE KEY (`code`),
869
  UNIQUE KEY (`code`),
870
  KEY `protocol` (`protocol`)
870
  KEY `protocol` (`protocol`)
871
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
871
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
872
/*!40101 SET character_set_client = @saved_cs_client */;
872
/*!40101 SET character_set_client = @saved_cs_client */;
873
873
874
--
874
--
875
-- Table structure for table `auth_provider`
875
-- Table structure for table `identity_provider`
876
--
876
--
877
877
878
DROP TABLE IF EXISTS `auth_provider_domains`;
878
DROP TABLE IF EXISTS `identity_provider_domains`;
879
/*!40101 SET @saved_cs_client     = @@character_set_client */;
879
/*!40101 SET @saved_cs_client     = @@character_set_client */;
880
/*!40101 SET character_set_client = utf8 */;
880
/*!40101 SET character_set_client = utf8 */;
881
CREATE TABLE `auth_provider_domains` (
881
CREATE TABLE `identity_provider_domains` (
882
  `auth_provider_domain_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify providers domain',
882
  `identity_provider_domain_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'unique key, used to identify providers domain',
883
  `auth_provider_id` int(11) NOT NULL COMMENT 'Reference to provider',
883
  `identity_provider_id` int(11) NOT NULL COMMENT 'Reference to provider',
884
  `domain` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Domain name. If null means all domains',
884
  `domain` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'Domain name. If null means all domains',
885
  `auto_register` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register',
885
  `auto_register` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow user auto register',
886
  `update_on_auth` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Update user data on auth login',
886
  `update_on_auth` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Update user data on auth login',
887
  `default_library_id` varchar(10) DEFAULT NULL COMMENT 'Default library to create user if auto register is enabled',
887
  `default_library_id` varchar(10) DEFAULT NULL COMMENT 'Default library to create user if auto register is enabled',
888
  `default_category_id` varchar(10) DEFAULT NULL COMMENT 'Default category to create user if auto register is enabled',
888
  `default_category_id` varchar(10) DEFAULT NULL COMMENT 'Default category to create user if auto register is enabled',
889
  `allow_opac` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Allow provider from opac interface',
889
  `allow_opac` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Allow provider from opac interface',
890
  `allow_staff` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Allow provider from staff interface',
890
  `allow_staff` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Allow provider from staff interface',
891
  PRIMARY KEY (`auth_provider_domain_id`),
891
  PRIMARY KEY (`identity_provider_domain_id`),
892
  UNIQUE KEY (`auth_provider_id`, `domain`),
892
  UNIQUE KEY (`identity_provider_id`, `domain`),
893
  KEY `domain` (`domain`),
893
  KEY `domain` (`domain`),
894
  KEY `allow_opac` (`allow_opac`),
894
  KEY `allow_opac` (`allow_opac`),
895
  KEY `allow_staff` (`allow_staff`),
895
  KEY `allow_staff` (`allow_staff`),
896
  CONSTRAINT `auth_provider_domain_ibfk_1` FOREIGN KEY (`auth_provider_id`) REFERENCES `auth_providers` (`auth_provider_id`) ON DELETE CASCADE,
896
  CONSTRAINT `identity_provider_domain_ibfk_1` FOREIGN KEY (`identity_provider_id`) REFERENCES `identity_providers` (`identity_provider_id`) ON DELETE CASCADE,
897
  CONSTRAINT `auth_provider_domain_ibfk_2` FOREIGN KEY (`default_library_id`) REFERENCES `branches` (`branchcode`) ON DELETE CASCADE,
897
  CONSTRAINT `identity_provider_domain_ibfk_2` FOREIGN KEY (`default_library_id`) REFERENCES `branches` (`branchcode`) ON DELETE CASCADE,
898
  CONSTRAINT `auth_provider_domain_ibfk_3` FOREIGN KEY (`default_category_id`) REFERENCES `categories` (`categorycode`) ON DELETE CASCADE
898
  CONSTRAINT `identity_provider_domain_ibfk_3` FOREIGN KEY (`default_category_id`) REFERENCES `categories` (`categorycode`) ON DELETE CASCADE
899
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
899
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
900
900
901
--
901
--
(-)a/installer/data/mysql/mandatory/userpermissions.sql (-1 / +1 lines)
Lines 41-47 INSERT INTO permissions (module_bit, code, description) VALUES Link Here
41
   ( 3, 'manage_background_jobs', 'Manage background jobs'),
41
   ( 3, 'manage_background_jobs', 'Manage background jobs'),
42
   ( 3, 'manage_curbside_pickups', 'Manage curbside pickups'),
42
   ( 3, 'manage_curbside_pickups', 'Manage curbside pickups'),
43
   ( 3, 'manage_search_filters', 'Manage custom search filters'),
43
   ( 3, 'manage_search_filters', 'Manage custom search filters'),
44
   ( 3, 'manage_authentication_providers', 'Manage authentication providers'),
44
   ( 3, 'manage_identity_providers', 'Manage authentication providers'),
45
   ( 4, 'delete_borrowers', 'Delete patrons'),
45
   ( 4, 'delete_borrowers', 'Delete patrons'),
46
   ( 4, 'edit_borrowers', 'Add, modify and view patron information'),
46
   ( 4, 'edit_borrowers', 'Add, modify and view patron information'),
47
   ( 4, 'view_borrower_infos_from_any_libraries', 'View patron infos from any libraries'),
47
   ( 4, 'view_borrower_infos_from_any_libraries', 'View patron infos from any libraries'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/admin-menu.inc (-3 / +3 lines)
Lines 141-151 Link Here
141
        </ul>
141
        </ul>
142
    [% END %]
142
    [% END %]
143
143
144
    [% IF ( CAN_user_parameters_manage_authentication_providers || CAN_user_parameters_manage_smtp_servers || CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || ( CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats || CAN_user_parameters_manage_additional_fields || ( Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_parameters_manage_keyboard_shortcuts ) ) %]
144
    [% IF ( CAN_user_parameters_manage_identity_providers || CAN_user_parameters_manage_smtp_servers || CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || ( CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats || CAN_user_parameters_manage_additional_fields || ( Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_parameters_manage_keyboard_shortcuts ) ) %]
145
        <h5>Additional parameters</h5>
145
        <h5>Additional parameters</h5>
146
        <ul>
146
        <ul>
147
            [% IF ( CAN_user_parameters_manage_authentication_providers) %]
147
            [% IF ( CAN_user_parameters_manage_identity_providers) %]
148
                <li><a href="/cgi-bin/koha/admin/authentication_providers.pl">Authentication providers</a></li>
148
                <li><a href="/cgi-bin/koha/admin/identity_providers.pl">Authentication providers</a></li>
149
            [% END %]
149
            [% END %]
150
            [% IF ( CAN_user_parameters_manage_search_targets ) %]
150
            [% IF ( CAN_user_parameters_manage_search_targets ) %]
151
                <li><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></li>
151
                <li><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></li>
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/permissions.inc (-3 / +3 lines)
Lines 827-835 Link Here
827
            Manage recalls for patrons
827
            Manage recalls for patrons
828
        </span>
828
        </span>
829
        <span class="permissioncode">([% name | html %])</span>
829
        <span class="permissioncode">([% name | html %])</span>
830
  [%# authentication_providers %]
830
  [%# identity_providers %]
831
    [%- CASE 'manage_authentication_providers' -%]
831
    [%- CASE 'manage_identity_providers' -%]
832
        <span class="sub_permission manage_authentication_providers_subpermission">
832
        <span class="sub_permission manage_identity_providers_subpermission">
833
            Manage authentication providers
833
            Manage authentication providers
834
        </span>
834
        </span>
835
        <span class="permissioncode">([% name | html %])</span>
835
        <span class="permissioncode">([% name | html %])</span>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt (-4 / +4 lines)
Lines 238-251 Link Here
238
                </dl>
238
                </dl>
239
            [% END %]
239
            [% END %]
240
240
241
            [% IF ( ( CAN_user_parameters_manage_authentication_providers || CAN_user_parameters_manage_smtp_servers || CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats || CAN_user_parameters_manage_additional_fields || CAN_user_parameters_manage_mana || (Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_parameters_manage_keyboard_shortcuts) ) %]
241
            [% IF ( ( CAN_user_parameters_manage_identity_providers || CAN_user_parameters_manage_smtp_servers || CAN_user_parameters_manage_search_targets || CAN_user_parameters_manage_didyoumean || CAN_user_parameters_manage_column_config || CAN_user_parameters_manage_audio_alerts || CAN_user_parameters_manage_sms_providers && Koha.Preference('SMSSendDriver') == 'Email' ) || CAN_user_parameters_manage_usage_stats || CAN_user_parameters_manage_additional_fields || CAN_user_parameters_manage_mana || (Koha.Preference('EnableAdvancedCatalogingEditor') && CAN_user_parameters_manage_keyboard_shortcuts) ) %]
242
                <h3>Additional parameters</h3>
242
                <h3>Additional parameters</h3>
243
                <dl>
243
                <dl>
244
                        <!-- <dt><a href="/cgi-bin/koha/admin/printers.pl">Network Printers</a></dt>
244
                        <!-- <dt><a href="/cgi-bin/koha/admin/printers.pl">Network Printers</a></dt>
245
                        <dd>Printers (UNIX paths).</dd> -->
245
                        <dd>Printers (UNIX paths).</dd> -->
246
                    [% IF ( CAN_user_parameters_manage_authentication_providers) %]
246
                    [% IF ( CAN_user_parameters_manage_identity_providers) %]
247
                        <dt><a href="/cgi-bin/koha/admin/authentication_providers.pl">Authentication providers</a></dt>
247
                        <dt><a href="/cgi-bin/koha/admin/identity_providers.pl">Identity providers</a></dt>
248
                        <dd>Define which external authentication providers to use</dd>
248
                        <dd>Define which external identity providers to use</dd>
249
                    [% END %]
249
                    [% END %]
250
                    [% IF ( CAN_user_parameters_manage_search_targets ) %]
250
                    [% IF ( CAN_user_parameters_manage_search_targets ) %]
251
                        <dt><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></dt>
251
                        <dt><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50/SRU servers</a></dt>
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authentication_provider_domains.tt (-56 / +56 lines)
Lines 6-20 Link Here
6
[% INCLUDE 'doc-head-open.inc' %]
6
[% INCLUDE 'doc-head-open.inc' %]
7
<title>
7
<title>
8
    [% IF op == 'add_form' %]
8
    [% IF op == 'add_form' %]
9
        New authentication provider domain &rsaquo; [% ELSIF op == 'edit_form' %]
9
        New identity provider domain &rsaquo; [% ELSIF op == 'edit_form' %]
10
        Edit authentication provider domain &rsaquo; [% END %]
10
        Edit identity provider domain &rsaquo; [% END %]
11
11
12
    Authentication providers &rsaquo; Administration &rsaquo; Koha
12
    Identity providers &rsaquo; Administration &rsaquo; Koha
13
</title>
13
</title>
14
[% INCLUDE 'doc-head-close.inc' %]
14
[% INCLUDE 'doc-head-close.inc' %]
15
</head>
15
</head>
16
16
17
<body id="admin_auth_provider_domains" class="admin">
17
<body id="admin_identity_provider_domains" class="admin">
18
[% INCLUDE 'header.inc' %]
18
[% INCLUDE 'header.inc' %]
19
[% INCLUDE 'prefs-admin-search.inc' %]
19
[% INCLUDE 'prefs-admin-search.inc' %]
20
20
Lines 28-39 Link Here
28
        </li>
28
        </li>
29
29
30
        <li>
30
        <li>
31
            <a href="/cgi-bin/koha/admin/authentication_providers.pl">Authentication providers</a>
31
            <a href="/cgi-bin/koha/admin/identity_providers.pl">Identity providers</a>
32
        </li>
32
        </li>
33
33
34
        [% IF op == 'add_form' %]
34
        [% IF op == 'add_form' %]
35
            <li>
35
            <li>
36
                <a href="/cgi-bin/koha/admin/authentication_providers.pl?domain_ops=1&amp;auth_provider_id=[%- auth_provider_id | uri -%]">Domains for [%- auth_provider_name | html -%]</a>
36
                <a href="/cgi-bin/koha/admin/identity_providers.pl?domain_ops=1&amp;identity_provider_id=[%- identity_provider_id | uri -%]">Domains for [%- identity_provider_name | html -%]</a>
37
            </li>
37
            </li>
38
            <li>
38
            <li>
39
                <a href="#" aria-current="page">
39
                <a href="#" aria-current="page">
Lines 43-49 Link Here
43
43
44
        [% ELSIF op == 'edit_form' %]
44
        [% ELSIF op == 'edit_form' %]
45
            <li>
45
            <li>
46
                <a href="/cgi-bin/koha/admin/authentication_providers.pl?domain_ops=1&amp;auth_provider_id=[%- auth_provider_id | uri -%]">Domains for [%- auth_provider_name | html -%]</a>
46
                <a href="/cgi-bin/koha/admin/identity_providers.pl?domain_ops=1&amp;identity_provider_id=[%- identity_provider_id | uri -%]">Domains for [%- identity_provider_name | html -%]</a>
47
            </li>
47
            </li>
48
            <li>
48
            <li>
49
                <a href="#" aria-current="page">
49
                <a href="#" aria-current="page">
Lines 54-60 Link Here
54
        [% ELSE %]
54
        [% ELSE %]
55
            <li>
55
            <li>
56
                <a href="#" aria-current="page">
56
                <a href="#" aria-current="page">
57
                    Domains for [%- auth_provider_code | html -%]
57
                    Domains for [%- identity_provider_code | html -%]
58
                </a>
58
                </a>
59
            </li>
59
            </li>
60
        [% END %]
60
        [% END %]
Lines 67-97 Link Here
67
            <main>
67
            <main>
68
68
69
[% FOREACH m IN messages %]
69
[% FOREACH m IN messages %]
70
    <div class="dialog [% m.type | html %]" id="auth_provider_domain_action_result_dialog">
70
    <div class="dialog [% m.type | html %]" id="identity_provider_domain_action_result_dialog">
71
        [% SWITCH m.code %]
71
        [% SWITCH m.code %]
72
        [% CASE 'error_on_update' %]
72
        [% CASE 'error_on_update' %]
73
            <span>An error occurred trying to open the authentication provider domain for editing. The passed id is invalid.</span>
73
            <span>An error occurred trying to open the identity provider domain for editing. The passed id is invalid.</span>
74
        [% CASE 'error_on_insert' %]
74
        [% CASE 'error_on_insert' %]
75
            <span>An error occurred when adding a new authentication provider domain.</span>
75
            <span>An error occurred when adding a new identity provider domain.</span>
76
        [% CASE 'success_on_update' %]
76
        [% CASE 'success_on_update' %]
77
            <span>Authentication provider domain updated successfully.</span>
77
            <span>Identity provider domain updated successfully.</span>
78
        [% CASE 'success_on_insert' %]
78
        [% CASE 'success_on_insert' %]
79
            <span>Authentication provider domain added successfully.</span>
79
            <span>Identity provider domain added successfully.</span>
80
        [% CASE %]
80
        [% CASE %]
81
            <span>[% m.code | html %]</span>
81
            <span>[% m.code | html %]</span>
82
        [% END %]
82
        [% END %]
83
    </div>
83
    </div>
84
[% END %]
84
[% END %]
85
85
86
    <div class="dialog message" id="auth_provider_domain_delete_success" style="display: none;"></div>
86
    <div class="dialog message" id="identity_provider_domain_delete_success" style="display: none;"></div>
87
    <div class="dialog alert"   id="auth_provider_domain_delete_error"   style="display: none;"></div>
87
    <div class="dialog alert"   id="identity_provider_domain_delete_error"   style="display: none;"></div>
88
88
89
[% IF op == 'add_form' %]
89
[% IF op == 'add_form' %]
90
    <h1>New authentication provider domain</h1>
90
    <h1>New identity provider domain</h1>
91
    <form action="/cgi-bin/koha/admin/authentication_providers.pl" id="add" name="add" class="validated" method="post">
91
    <form action="/cgi-bin/koha/admin/identity_providers.pl" id="add" name="add" class="validated" method="post">
92
        <input type="hidden" name="op" value="add" />
92
        <input type="hidden" name="op" value="add" />
93
        <input type="hidden" name="domain_ops" value="1" />
93
        <input type="hidden" name="domain_ops" value="1" />
94
        <input type="hidden" name="auth_provider_id" value="[%- auth_provider_id | html -%]" />
94
        <input type="hidden" name="identity_provider_id" value="[%- identity_provider_id | html -%]" />
95
        <fieldset class="rows">
95
        <fieldset class="rows">
96
            <ol>
96
            <ol>
97
                <li>
97
                <li>
Lines 140-146 Link Here
140
                        <option value="1" selected="selected">Allow</option>
140
                        <option value="1" selected="selected">Allow</option>
141
                        <option value="0">Don't allow</option>
141
                        <option value="0">Don't allow</option>
142
                    </select>
142
                    </select>
143
                    <span>opac users of this domain to login with this authentication provider</span>
143
                    <span>opac users of this domain to login with this identity provider</span>
144
                </li>
144
                </li>
145
                <li>
145
                <li>
146
                    <label for="allow_opac">Allow staff: </label>
146
                    <label for="allow_opac">Allow staff: </label>
Lines 154-176 Link Here
154
        </fieldset>
154
        </fieldset>
155
        <fieldset class="action">
155
        <fieldset class="action">
156
            <input type="submit" value="Submit" />
156
            <input type="submit" value="Submit" />
157
            <a class="cancel" href="/cgi-bin/koha/admin/authentication_providers.pl?domain_ops=1&amp;auth_provider_id=[%- auth_provider_id | html -%]">Cancel</a>
157
            <a class="cancel" href="/cgi-bin/koha/admin/identity_providers.pl?domain_ops=1&amp;identity_provider_id=[%- identity_provider_id | html -%]">Cancel</a>
158
        </fieldset>
158
        </fieldset>
159
    </form>
159
    </form>
160
[% END %]
160
[% END %]
161
161
162
[% IF op == 'edit_form' %]
162
[% IF op == 'edit_form' %]
163
    <h1>Edit authentication provider domain</h1>
163
    <h1>Edit identity provider domain</h1>
164
    <form action="/cgi-bin/koha/admin/authentication_providers.pl" id="edit_save" name="edit_save" class="validated" method="post">
164
    <form action="/cgi-bin/koha/admin/identity_providers.pl" id="edit_save" name="edit_save" class="validated" method="post">
165
        <input type="hidden" name="op" value="edit_save" />
165
        <input type="hidden" name="op" value="edit_save" />
166
        <input type="hidden" name="domain_ops" value="1" />
166
        <input type="hidden" name="domain_ops" value="1" />
167
        <input type="hidden" name="auth_provider_id" value="[%- auth_provider_id | html -%]" />
167
        <input type="hidden" name="identity_provider_id" value="[%- identity_provider_id | html -%]" />
168
        <input type="hidden" name="auth_provider_domain_id" value="[%- auth_provider_domain.auth_provider_domain_id | html -%]" />
168
        <input type="hidden" name="identity_provider_domain_id" value="[%- identity_provider_domain.identity_provider_domain_id | html -%]" />
169
        <fieldset class="rows">
169
        <fieldset class="rows">
170
            <ol>
170
            <ol>
171
                <li>
171
                <li>
172
                    <label for="domain">Domain: </label>
172
                    <label for="domain">Domain: </label>
173
                    <input type="text" name="domain" id="domain" size="60" value="[%- auth_provider_domain.domain | html -%]"/>
173
                    <input type="text" name="domain" id="domain" size="60" value="[%- identity_provider_domain.domain | html -%]"/>
174
                </li>
174
                </li>
175
            </ol>
175
            </ol>
176
        </fieldset>
176
        </fieldset>
Lines 180-186 Link Here
180
                <li>
180
                <li>
181
                    <label for="update_on_auth">Update on login: </label>
181
                    <label for="update_on_auth">Update on login: </label>
182
                    <select name="update_on_auth" id="update_on_auth">
182
                    <select name="update_on_auth" id="update_on_auth">
183
                    [% IF auth_provider_domain.update_on_auth == "1" %]
183
                    [% IF identity_provider_domain.update_on_auth == "1" %]
184
                        <option value="1" selected="selected">Update</option>
184
                        <option value="1" selected="selected">Update</option>
185
                        <option value="0">Don't update</option>
185
                        <option value="0">Don't update</option>
186
                    [% ELSE %]
186
                    [% ELSE %]
Lines 193-199 Link Here
193
                <li>
193
                <li>
194
                    <label for="auto_register">Auto register: </label>
194
                    <label for="auto_register">Auto register: </label>
195
                    <select name="auto_register" id="auto_register">
195
                    <select name="auto_register" id="auto_register">
196
                    [% IF auth_provider_domain.auto_register == "1" %]
196
                    [% IF identity_provider_domain.auto_register == "1" %]
197
                        <option value="1" selected="selected">Allow</option>
197
                        <option value="1" selected="selected">Allow</option>
198
                        <option value="0">Don't allow</option>
198
                        <option value="0">Don't allow</option>
199
                    [% ELSE %]
199
                    [% ELSE %]
Lines 206-212 Link Here
206
                <li>
206
                <li>
207
                    <label for="default_library_id">Default library: </label>
207
                    <label for="default_library_id">Default library: </label>
208
                    <select id="default_library_id" name="default_library_id">
208
                    <select id="default_library_id" name="default_library_id">
209
                        [% PROCESS options_for_libraries libraries => Branches.all( selected => auth_provider_domain.default_library_id, unfiltered => 1, do_not_select_my_library => 1 ) %]
209
                        [% PROCESS options_for_libraries libraries => Branches.all( selected => identity_provider_domain.default_library_id, unfiltered => 1, do_not_select_my_library => 1 ) %]
210
                    </select>
210
                    </select>
211
                </li>
211
                </li>
212
                <li>
212
                <li>
Lines 214-220 Link Here
214
                    [% SET categories = Categories.all() %]
214
                    [% SET categories = Categories.all() %]
215
                    <select name="default_category_id" id="default_category_id">
215
                    <select name="default_category_id" id="default_category_id">
216
                        [% FOREACH category IN categories %]
216
                        [% FOREACH category IN categories %]
217
                            [% IF category.categorycode == auth_provider_domain.default_category_id %]
217
                            [% IF category.categorycode == identity_provider_domain.default_category_id %]
218
                                <option value="[% category.categorycode | html %]" selected="selected">[% category.description | html %]</option>
218
                                <option value="[% category.categorycode | html %]" selected="selected">[% category.description | html %]</option>
219
                            [% ELSE %]
219
                            [% ELSE %]
220
                                <option value="[% category.categorycode | html %]">[% category.description | html %]</option>
220
                                <option value="[% category.categorycode | html %]">[% category.description | html %]</option>
Lines 225-231 Link Here
225
                <li>
225
                <li>
226
                    <label for="allow_opac">Allow opac: </label>
226
                    <label for="allow_opac">Allow opac: </label>
227
                    <select name="allow_opac" id="allow_opac">
227
                    <select name="allow_opac" id="allow_opac">
228
                    [% IF auth_provider_domain.allow_opac == "1" %]
228
                    [% IF identity_provider_domain.allow_opac == "1" %]
229
                        <option value="1" selected="selected">Allow</option>
229
                        <option value="1" selected="selected">Allow</option>
230
                        <option value="0">Don't allow</option>
230
                        <option value="0">Don't allow</option>
231
                    [% ELSE %]
231
                    [% ELSE %]
Lines 233-244 Link Here
233
                        <option value="0" selected="selected">Don't allow</option>
233
                        <option value="0" selected="selected">Don't allow</option>
234
                    [% END %]
234
                    [% END %]
235
                    </select>
235
                    </select>
236
                    <span>opac users of this domain to login with this authentication provider</span>
236
                    <span>opac users of this domain to login with this identity provider</span>
237
                </li>
237
                </li>
238
                <li>
238
                <li>
239
                    <label for="allow_opac">Allow staff: </label>
239
                    <label for="allow_opac">Allow staff: </label>
240
                    <select name="allow_staff" id="allow_staff">
240
                    <select name="allow_staff" id="allow_staff">
241
                    [% IF auth_provider_domain.allow_staff == "1" %]
241
                    [% IF identity_provider_domain.allow_staff == "1" %]
242
                        <option value="1" selected="selected">Allow</option>
242
                        <option value="1" selected="selected">Allow</option>
243
                        <option value="0">Don't allow</option>
243
                        <option value="0">Don't allow</option>
244
                    [% ELSE %]
244
                    [% ELSE %]
Lines 246-258 Link Here
246
                        <option value="0" selected="selected">Don't allow</option>
246
                        <option value="0" selected="selected">Don't allow</option>
247
                    [% END %]
247
                    [% END %]
248
                    </select>
248
                    </select>
249
                    <span>staff users of this domain to login with this authentication provider</span>
249
                    <span>staff users of this domain to login with this identity provider</span>
250
                </li>
250
                </li>
251
            </ol>
251
            </ol>
252
        </fieldset>
252
        </fieldset>
253
        <fieldset class="action">
253
        <fieldset class="action">
254
            <input type="submit" value="Submit" />
254
            <input type="submit" value="Submit" />
255
            <a class="cancel" href="/cgi-bin/koha/admin/authentication_providers.pl?domain_ops=1&amp;auth_provider_id=[%- auth_provider_id | html -%]">Cancel</a>
255
            <a class="cancel" href="/cgi-bin/koha/admin/identity_providers.pl?domain_ops=1&amp;identity_provider_id=[%- identity_provider_id | html -%]">Cancel</a>
256
        </fieldset>
256
        </fieldset>
257
    </form>
257
    </form>
258
[% END %]
258
[% END %]
Lines 260-271 Link Here
260
[% IF op == 'list' %]
260
[% IF op == 'list' %]
261
261
262
    <div id="toolbar" class="btn-toolbar">
262
    <div id="toolbar" class="btn-toolbar">
263
        <a class="btn btn-default" id="new_auth_provider_domain" href="/cgi-bin/koha/admin/authentication_providers.pl?domain_ops=1&amp;auth_provider_id=[%- auth_provider_id | html -%]&amp;op=add_form"><i class="fa fa-plus"></i> New authentication provider domain</a>
263
        <a class="btn btn-default" id="new_identity_provider_domain" href="/cgi-bin/koha/admin/identity_providers.pl?domain_ops=1&amp;identity_provider_id=[%- identity_provider_id | html -%]&amp;op=add_form"><i class="fa fa-plus"></i> New identity provider domain</a>
264
    </div>
264
    </div>
265
265
266
    <h1>Authentication provider domains</h1>
266
    <h1>Identity provider domains</h1>
267
267
268
    <table id="auth_provider_domains">
268
    <table id="identity_provider_domains">
269
        <thead>
269
        <thead>
270
            <tr>
270
            <tr>
271
                <th>Domain</th>
271
                <th>Domain</th>
Lines 286-292 Link Here
286
                    <div class="modal-content">
286
                    <div class="modal-content">
287
                        <div class="modal-header">
287
                        <div class="modal-header">
288
                            <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">Ă—</button>
288
                            <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">Ă—</button>
289
                            <h3 id="delete_confirm_modal_label">Delete authentication provider domain</h3>
289
                            <h3 id="delete_confirm_modal_label">Delete identity provider domain</h3>
290
                        </div>
290
                        </div>
291
                        <div class="modal-body">
291
                        <div class="modal-body">
292
                            <div id="delete_confirm_dialog"></div>
292
                            <div id="delete_confirm_dialog"></div>
Lines 316-322 Link Here
316
    <script>
316
    <script>
317
        $(document).ready(function() {
317
        $(document).ready(function() {
318
318
319
            var auth_provider_domains_url = '/api/v1/auth/providers/[%- auth_provider_id | html -%]/domains';
319
            var identity_provider_domains_url = '/api/v1/auth/identity_providers/[%- identity_provider_id | html -%]/domains';
320
            [% SET categories = Categories.all() %]
320
            [% SET categories = Categories.all() %]
321
            var categories = {
321
            var categories = {
322
            [% FOREACH category IN categories %]
322
            [% FOREACH category IN categories %]
Lines 329-340 Link Here
329
                "[% library.branchcode | html %]": "[% library.branchname | html %]",
329
                "[% library.branchcode | html %]": "[% library.branchname | html %]",
330
            [% END %]
330
            [% END %]
331
            };
331
            };
332
            window.auth_provider_domains = $("#auth_provider_domains").kohaTable({
332
            window.identity_provider_domains = $("#identity_provider_domains").kohaTable({
333
                "ajax": {
333
                "ajax": {
334
                    "url": auth_provider_domains_url
334
                    "url": identity_provider_domains_url
335
                },
335
                },
336
                'language': {
336
                'language': {
337
                    'emptyTable': '<div class="dialog message">'+_("There are no authentication provider domains defined.")+'</div>'
337
                    'emptyTable': '<div class="dialog message">'+_("There are no identity provider domains defined.")+'</div>'
338
                },
338
                },
339
                "columnDefs": [ {
339
                "columnDefs": [ {
340
                    "targets": [1],
340
                    "targets": [1],
Lines 424-431 Link Here
424
                    },
424
                    },
425
                    {
425
                    {
426
                        "data": function( row, type, val, meta ) {
426
                        "data": function( row, type, val, meta ) {
427
                            var result = '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/admin/authentication_providers.pl?domain_ops=1&amp;auth_provider_id=[%- auth_provider_id | html -%]&amp;op=edit_form&amp;auth_provider_domain_id='+ encodeURIComponent(row.auth_provider_domain_id) +'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</a>'+"\n";
427
                            var result = '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/admin/identity_providers.pl?domain_ops=1&amp;identity_provider_id=[%- identity_provider_id | html -%]&amp;op=edit_form&amp;identity_provider_domain_id='+ encodeURIComponent(row.identity_provider_domain_id) +'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</a>'+"\n";
428
                            result += '<a class="btn btn-default btn-xs delete_auth_provider_domain" role="button" href="#" data-toggle="modal" data-target="#delete_confirm_modal" data-auth-provider-domain-id="'+ encodeURIComponent(row.auth_provider_domain_id) +'" data-auth-provider-domain="'+ encodeURIComponent((row.domain || '').escapeHtml()) +'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Delete")+'</a>';
428
                            result += '<a class="btn btn-default btn-xs delete_identity_provider_domain" role="button" href="#" data-toggle="modal" data-target="#delete_confirm_modal" data-auth-provider-domain-id="'+ encodeURIComponent(row.identity_provider_domain_id) +'" data-auth-provider-domain="'+ encodeURIComponent((row.domain || '').escapeHtml()) +'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Delete")+'</a>';
429
                            return result;
429
                            return result;
430
                        },
430
                        },
431
                        "searchable": false,
431
                        "searchable": false,
Lines 439-470 Link Here
439
                },
439
                },
440
            });
440
            });
441
441
442
            $('#auth_provider_domains').on( "click", '.delete_auth_provider_domain', function () {
442
            $('#identity_provider_domains').on( "click", '.delete_identity_provider_domain', function () {
443
                var auth_provider_domain_id   = $(this).data('auth-provider-domain-id');
443
                var identity_provider_domain_id   = $(this).data('auth-provider-domain-id');
444
                var auth_provider_domain = decodeURIComponent($(this).data('auth-provider-domain'));
444
                var identity_provider_domain = decodeURIComponent($(this).data('auth-provider-domain'));
445
445
446
                $("#delete_confirm_dialog").html(
446
                $("#delete_confirm_dialog").html(
447
                    _("You are about to delete the '%s' authentication provider domain.").format(auth_provider_domain)
447
                    _("You are about to delete the '%s' identity provider domain.").format(identity_provider_domain)
448
                );
448
                );
449
                $("#delete_confirm_modal_button").data('auth-provider-domain-id', auth_provider_domain_id);
449
                $("#delete_confirm_modal_button").data('auth-provider-domain-id', identity_provider_domain_id);
450
                $("#delete_confirm_modal_button").data('auth-provider-domain', auth_provider_domain);
450
                $("#delete_confirm_modal_button").data('auth-provider-domain', identity_provider_domain);
451
            });
451
            });
452
452
453
            $("#delete_confirm_modal_button").on( "click", function () {
453
            $("#delete_confirm_modal_button").on( "click", function () {
454
454
455
                var auth_provider_domain_id   = $(this).data('auth-provider-domain-id');
455
                var identity_provider_domain_id   = $(this).data('auth-provider-domain-id');
456
                var auth_provider_domain = $(this).data('auth-provider-domain');
456
                var identity_provider_domain = $(this).data('auth-provider-domain');
457
457
458
                $.ajax({
458
                $.ajax({
459
                    method: "DELETE",
459
                    method: "DELETE",
460
                    url: auth_provider_domains_url+"/"+auth_provider_domain_id
460
                    url: identity_provider_domains_url+"/"+identity_provider_domain_id
461
                }).success(function() {
461
                }).success(function() {
462
                    window.auth_provider_domains.api().ajax.reload(function (data) {
462
                    window.identity_provider_domains.api().ajax.reload(function (data) {
463
                        $("#smtp_action_result_dialog").hide();
463
                        $("#smtp_action_result_dialog").hide();
464
                        $("#smtp_delete_success").html(_("Server '%s' deleted successfully.").format(auth_provider_domain)).show();
464
                        $("#smtp_delete_success").html(_("Server '%s' deleted successfully.").format(identity_provider_domain)).show();
465
                    });
465
                    });
466
                }).fail(function () {
466
                }).fail(function () {
467
                    $("#smtp_delete_error").html(_("Error deleting server '%s'. Check the logs.").format(auth_provider_domain)).show();
467
                    $("#smtp_delete_error").html(_("Error deleting server '%s'. Check the logs.").format(identity_provider_domain)).show();
468
                }).done(function () {
468
                }).done(function () {
469
                    $("#delete_confirm_modal").modal('hide');
469
                    $("#delete_confirm_modal").modal('hide');
470
                });
470
                });
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/authentication_providers.tt (-58 / +58 lines)
Lines 4-18 Link Here
4
[% INCLUDE 'doc-head-open.inc' %]
4
[% INCLUDE 'doc-head-open.inc' %]
5
<title>
5
<title>
6
    [% IF op == 'add_form' %]
6
    [% IF op == 'add_form' %]
7
        New authentication provider &rsaquo; [% ELSIF op == 'edit_form' %]
7
        New identity provider &rsaquo; [% ELSIF op == 'edit_form' %]
8
        Edit authentication provider &rsaquo; [% END %]
8
        Edit identity provider &rsaquo; [% END %]
9
9
10
    Authentication providers &rsaquo; Administration &rsaquo; Koha
10
    Identity providers &rsaquo; Administration &rsaquo; Koha
11
</title>
11
</title>
12
[% INCLUDE 'doc-head-close.inc' %]
12
[% INCLUDE 'doc-head-close.inc' %]
13
</head>
13
</head>
14
14
15
<body id="admin_auth_providers" class="admin">
15
<body id="admin_identity_providers" class="admin">
16
[% INCLUDE 'header.inc' %]
16
[% INCLUDE 'header.inc' %]
17
[% INCLUDE 'prefs-admin-search.inc' %]
17
[% INCLUDE 'prefs-admin-search.inc' %]
18
18
Lines 27-33 Link Here
27
27
28
        [% IF op == 'add_form' %]
28
        [% IF op == 'add_form' %]
29
            <li>
29
            <li>
30
                <a href="/cgi-bin/koha/admin/authentication_providers.pl">Authentication providers</a>
30
                <a href="/cgi-bin/koha/admin/identity_providers.pl">Identity providers</a>
31
            </li>
31
            </li>
32
            <li>
32
            <li>
33
                <a href="#" aria-current="page">
33
                <a href="#" aria-current="page">
Lines 37-43 Link Here
37
37
38
        [% ELSIF op == 'edit_form' %]
38
        [% ELSIF op == 'edit_form' %]
39
            <li>
39
            <li>
40
                <a href="/cgi-bin/koha/admin/authentication_providers.pl">Authentication providers</a>
40
                <a href="/cgi-bin/koha/admin/identity_providers.pl">Identity providers</a>
41
            </li>
41
            </li>
42
            <li>
42
            <li>
43
                <a href="#" aria-current="page">
43
                <a href="#" aria-current="page">
Lines 48-54 Link Here
48
        [% ELSE %]
48
        [% ELSE %]
49
            <li>
49
            <li>
50
                <a href="#" aria-current="page">
50
                <a href="#" aria-current="page">
51
                    Authentication providers
51
                    Identity providers
52
                </a>
52
                </a>
53
            </li>
53
            </li>
54
        [% END %]
54
        [% END %]
Lines 61-88 Link Here
61
            <main>
61
            <main>
62
62
63
[% FOREACH m IN messages %]
63
[% FOREACH m IN messages %]
64
    <div class="dialog [% m.type | html %]" id="auth_provider_action_result_dialog">
64
    <div class="dialog [% m.type | html %]" id="identity_provider_action_result_dialog">
65
        [% SWITCH m.code %]
65
        [% SWITCH m.code %]
66
        [% CASE 'error_on_update' %]
66
        [% CASE 'error_on_update' %]
67
            <span>An error occurred trying to open the authentication provider for editing. The passed id is invalid.</span>
67
            <span>An error occurred trying to open the identity provider for editing. The passed id is invalid.</span>
68
        [% CASE 'error_on_insert' %]
68
        [% CASE 'error_on_insert' %]
69
            <span>An error occurred when adding a new authentication provider.</span>
69
            <span>An error occurred when adding a new identity provider.</span>
70
        [% CASE 'success_on_update' %]
70
        [% CASE 'success_on_update' %]
71
            <span>Authentication provider updated successfully.</span>
71
            <span>Identity provider updated successfully.</span>
72
        [% CASE 'success_on_insert' %]
72
        [% CASE 'success_on_insert' %]
73
            <span>Authentication provider added successfully.</span>
73
            <span>Identity provider added successfully.</span>
74
        [% CASE %]
74
        [% CASE %]
75
            <span>[% m.code | html %]</span>
75
            <span>[% m.code | html %]</span>
76
        [% END %]
76
        [% END %]
77
    </div>
77
    </div>
78
[% END %]
78
[% END %]
79
79
80
    <div class="dialog message" id="auth_provider_delete_success" style="display: none;"></div>
80
    <div class="dialog message" id="identity_provider_delete_success" style="display: none;"></div>
81
    <div class="dialog alert"   id="auth_provider_delete_error"   style="display: none;"></div>
81
    <div class="dialog alert"   id="identity_provider_delete_error"   style="display: none;"></div>
82
82
83
[% IF op == 'add_form' %]
83
[% IF op == 'add_form' %]
84
    <h1>New authentication provider</h1>
84
    <h1>New identity provider</h1>
85
    <form action="/cgi-bin/koha/admin/authentication_providers.pl" id="add" name="add" class="validated" method="post">
85
    <form action="/cgi-bin/koha/admin/identity_providers.pl" id="add" name="add" class="validated" method="post">
86
        <input type="hidden" name="op" value="add" />
86
        <input type="hidden" name="op" value="add" />
87
        <fieldset class="rows">
87
        <fieldset class="rows">
88
            <ol>
88
            <ol>
Lines 151-182 Link Here
151
        </fieldset>
151
        </fieldset>
152
        <fieldset class="action">
152
        <fieldset class="action">
153
            <input type="submit" value="Submit" />
153
            <input type="submit" value="Submit" />
154
            <a class="cancel" href="/cgi-bin/koha/admin/authentication_providers.pl">Cancel</a>
154
            <a class="cancel" href="/cgi-bin/koha/admin/identity_providers.pl">Cancel</a>
155
        </fieldset>
155
        </fieldset>
156
    </form>
156
    </form>
157
[% END %]
157
[% END %]
158
158
159
[% IF op == 'edit_form' %]
159
[% IF op == 'edit_form' %]
160
    <h1>Edit authentication provider</h1>
160
    <h1>Edit identity provider</h1>
161
    <form action="/cgi-bin/koha/admin/authentication_providers.pl" id="edit_save" name="edit_save" class="validated" method="post">
161
    <form action="/cgi-bin/koha/admin/identity_providers.pl" id="edit_save" name="edit_save" class="validated" method="post">
162
        <input type="hidden" name="op" value="edit_save" />
162
        <input type="hidden" name="op" value="edit_save" />
163
        <input type="hidden" name="auth_provider_id" value="[%- auth_provider.auth_provider_id | html -%]" />
163
        <input type="hidden" name="identity_provider_id" value="[%- identity_provider.identity_provider_id | html -%]" />
164
        <fieldset class="rows">
164
        <fieldset class="rows">
165
            <ol>
165
            <ol>
166
                <li>
166
                <li>
167
                    <label for="code" class="required">Code: </label>
167
                    <label for="code" class="required">Code: </label>
168
                    <input type="text" name="code" id="code" size="60" class="required" required="required" value="[%- auth_provider.code | html -%]"/>
168
                    <input type="text" name="code" id="code" size="60" class="required" required="required" value="[%- identity_provider.code | html -%]"/>
169
                    <span class="required">Required</span>
169
                    <span class="required">Required</span>
170
                </li>
170
                </li>
171
                <li>
171
                <li>
172
                    <label for="description" class="required">Description: </label>
172
                    <label for="description" class="required">Description: </label>
173
                    <input type="text" name="description" id="description" size="60" class="required" required="required" value="[%- auth_provider.description | html -%]"/>
173
                    <input type="text" name="description" id="description" size="60" class="required" required="required" value="[%- identity_provider.description | html -%]"/>
174
                    <span class="required">Required</span>
174
                    <span class="required">Required</span>
175
                </li>
175
                </li>
176
                <li>
176
                <li>
177
                    <label for="protocol">Protocol: </label>
177
                    <label for="protocol">Protocol: </label>
178
                    <select name="protocol" id="protocol">
178
                    <select name="protocol" id="protocol">
179
                    [% IF auth_provider.protocol == 'OAuth' %]
179
                    [% IF identity_provider.protocol == 'OAuth' %]
180
                        <option value="OAuth" selected="selected">OAuth</option>
180
                        <option value="OAuth" selected="selected">OAuth</option>
181
                        <option value="OIDC">OIDC</option>
181
                        <option value="OIDC">OIDC</option>
182
                        <!-- Not implemented yet
182
                        <!-- Not implemented yet
Lines 201-239 Link Here
201
                <li>
201
                <li>
202
                    <div>
202
                    <div>
203
                        <label for="config" class="required json">Configuration: </label>
203
                        <label for="config" class="required json">Configuration: </label>
204
                        <textarea name="config" id="config" class="required">[%- auth_provider.config | html -%]</textarea>
204
                        <textarea name="config" id="config" class="required">[%- identity_provider.config | html -%]</textarea>
205
                        <span class="required">Required</span>
205
                        <span class="required">Required</span>
206
                    </div>
206
                    </div>
207
                    <div>
207
                    <div>
208
                        <label></label>
208
                        <label></label>
209
                        <button class="btn btn-ligth defaults" data-default-target="config" id="default-config">Add default [%- auth_provider.protocol | html -%] configuration</button>
209
                        <button class="btn btn-ligth defaults" data-default-target="config" id="default-config">Add default [%- identity_provider.protocol | html -%] configuration</button>
210
                    </div>
210
                    </div>
211
                </li>
211
                </li>
212
                <li>
212
                <li>
213
                    <div>
213
                    <div>
214
                        <label for="mapping" class="required json">Mapping: </label>
214
                        <label for="mapping" class="required json">Mapping: </label>
215
                        <textarea name="mapping" id="mapping" class="required">[%- auth_provider.mapping | html -%]</textarea>
215
                        <textarea name="mapping" id="mapping" class="required">[%- identity_provider.mapping | html -%]</textarea>
216
                        <span class="required">Required</span>
216
                        <span class="required">Required</span>
217
                    </div>
217
                    </div>
218
                    <div>
218
                    <div>
219
                        <label></label>
219
                        <label></label>
220
                        <button class="btn btn-ligth defaults" data-default-target="mapping" id="default-mapping">Add default [%- auth_provider.protocol | html -%] mapping</button>
220
                        <button class="btn btn-ligth defaults" data-default-target="mapping" id="default-mapping">Add default [%- identity_provider.protocol | html -%] mapping</button>
221
                    </div>
221
                    </div>
222
                </li>
222
                </li>
223
                <li>
223
                <li>
224
                    <label for="matchpoint" class="required">matchpoint: </label>
224
                    <label for="matchpoint" class="required">matchpoint: </label>
225
                    <select name="matchpoint" id="matchpoint" class="required">
225
                    <select name="matchpoint" id="matchpoint" class="required">
226
                        [%- IF auth_provider.matchpoint == 'email'      -%]
226
                        [%- IF identity_provider.matchpoint == 'email'      -%]
227
                            <option value="email" selected="selected">Email</option>
227
                            <option value="email" selected="selected">Email</option>
228
                        [%- ELSE -%]
228
                        [%- ELSE -%]
229
                            <option value="email">Email</option>
229
                            <option value="email">Email</option>
230
                        [%- END -%]
230
                        [%- END -%]
231
                        [%- IF auth_provider.matchpoint == 'userid'     -%]
231
                        [%- IF identity_provider.matchpoint == 'userid'     -%]
232
                            <option value="userid" selected="selected">User id</option>
232
                            <option value="userid" selected="selected">User id</option>
233
                        [%- ELSE -%]
233
                        [%- ELSE -%]
234
                            <option value="userid">User id</option>
234
                            <option value="userid">User id</option>
235
                        [%- END -%]
235
                        [%- END -%]
236
                        [%- IF auth_provider.matchpoint == 'cardnumber' -%]
236
                        [%- IF identity_provider.matchpoint == 'cardnumber' -%]
237
                            <option value="cardnumber" selected="selected">Card number</option>
237
                            <option value="cardnumber" selected="selected">Card number</option>
238
                        [%- ELSE -%]
238
                        [%- ELSE -%]
239
                            <option value="cardnumber">Card number</option>
239
                            <option value="cardnumber">Card number</option>
Lines 243-255 Link Here
243
                </li>
243
                </li>
244
                <li>
244
                <li>
245
                    <label for="icon_url">Icon URL: </label>
245
                    <label for="icon_url">Icon URL: </label>
246
                    <input type="text" name="icon_url" id="icon_url" size="60"  value="[%- auth_provider.icon_url | html -%]"/>
246
                    <input type="text" name="icon_url" id="icon_url" size="60"  value="[%- identity_provider.icon_url | html -%]"/>
247
                </li>
247
                </li>
248
            </ol>
248
            </ol>
249
        </fieldset>
249
        </fieldset>
250
        <fieldset class="action">
250
        <fieldset class="action">
251
            <input type="submit" value="Submit" />
251
            <input type="submit" value="Submit" />
252
            <a class="cancel" href="/cgi-bin/koha/admin/authentication_providers.pl">Cancel</a>
252
            <a class="cancel" href="/cgi-bin/koha/admin/identity_providers.pl">Cancel</a>
253
        </fieldset>
253
        </fieldset>
254
    </form>
254
    </form>
255
[% END %]
255
[% END %]
Lines 257-268 Link Here
257
[% IF op == 'list' %]
257
[% IF op == 'list' %]
258
258
259
    <div id="toolbar" class="btn-toolbar">
259
    <div id="toolbar" class="btn-toolbar">
260
        <a class="btn btn-default" id="new_auth_provider" href="/cgi-bin/koha/admin/authentication_providers.pl?op=add_form"><i class="fa fa-plus"></i> New authentication provider</a>
260
        <a class="btn btn-default" id="new_identity_provider" href="/cgi-bin/koha/admin/identity_providers.pl?op=add_form"><i class="fa fa-plus"></i> New identity provider</a>
261
    </div>
261
    </div>
262
262
263
    <h1>Authentication providers</h1>
263
    <h1>Identity providers</h1>
264
264
265
    <table id="auth_providers">
265
    <table id="identity_providers">
266
        <thead>
266
        <thead>
267
            <tr>
267
            <tr>
268
                <th>Code</th>
268
                <th>Code</th>
Lines 279-285 Link Here
279
                    <div class="modal-content">
279
                    <div class="modal-content">
280
                        <div class="modal-header">
280
                        <div class="modal-header">
281
                            <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">Ă—</button>
281
                            <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">Ă—</button>
282
                            <h3 id="delete_confirm_modal_label">Delete authentication provider</h3>
282
                            <h3 id="delete_confirm_modal_label">Delete identity provider</h3>
283
                        </div>
283
                        </div>
284
                        <div class="modal-body">
284
                        <div class="modal-body">
285
                            <div id="delete_confirm_dialog"></div>
285
                            <div id="delete_confirm_dialog"></div>
Lines 309-321 Link Here
309
    <script>
309
    <script>
310
        $(document).ready(function() {
310
        $(document).ready(function() {
311
311
312
            var auth_providers_url = '/api/v1/auth/providers';
312
            var identity_providers_url = '/api/v1/auth/identity_providers';
313
            window.auth_providers = $("#auth_providers").kohaTable({
313
            window.identity_providers = $("#identity_providers").kohaTable({
314
                "ajax": {
314
                "ajax": {
315
                    "url": auth_providers_url
315
                    "url": identity_providers_url
316
                },
316
                },
317
                'language': {
317
                'language': {
318
                    'emptyTable': '<div class="dialog message">'+_("There are no authentication providers defined.")+'</div>'
318
                    'emptyTable': '<div class="dialog message">'+_("There are no identity providers defined.")+'</div>'
319
                },
319
                },
320
                "columnDefs": [ {
320
                "columnDefs": [ {
321
                    "targets": [0,1,2],
321
                    "targets": [0,1,2],
Lines 349-357 Link Here
349
                    },
349
                    },
350
                    {
350
                    {
351
                        "data": function( row, type, val, meta ) {
351
                        "data": function( row, type, val, meta ) {
352
                            var result = '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/admin/authentication_providers.pl?op=edit_form&amp;auth_provider_id='+ encodeURIComponent(row.auth_provider_id) +'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</a>'+"\n";
352
                            var result = '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/admin/identity_providers.pl?op=edit_form&amp;identity_provider_id='+ encodeURIComponent(row.identity_provider_id) +'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</a>'+"\n";
353
                            result += '<a class="btn btn-default btn-xs delete_auth_provider" role="button" href="#" data-toggle="modal" data-target="#delete_confirm_modal" data-auth-provider-id="'+ encodeURIComponent(row.auth_provider_id) +'" data-auth-provider-code="'+ encodeURIComponent(row.code.escapeHtml()) +'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Delete")+'</a>'+"\n";
353
                            result += '<a class="btn btn-default btn-xs delete_identity_provider" role="button" href="#" data-toggle="modal" data-target="#delete_confirm_modal" data-auth-provider-id="'+ encodeURIComponent(row.identity_provider_id) +'" data-auth-provider-code="'+ encodeURIComponent(row.code.escapeHtml()) +'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Delete")+'</a>'+"\n";
354
                            result += '<a class="btn btn-default btn-xs edit_domains" role="button" href="/cgi-bin/koha/admin/authentication_providers.pl?domain_ops=1&amp;auth_provider_id='+ encodeURIComponent(row.auth_provider_id) +'"><i class="fa fa-cog" aria-hidden="true"></i> '+_("Manage Domains")+'</a>';
354
                            result += '<a class="btn btn-default btn-xs edit_domains" role="button" href="/cgi-bin/koha/admin/identity_providers.pl?domain_ops=1&amp;identity_provider_id='+ encodeURIComponent(row.identity_provider_id) +'"><i class="fa fa-cog" aria-hidden="true"></i> '+_("Manage Domains")+'</a>';
355
                            return result;
355
                            return result;
356
                        },
356
                        },
357
                        "searchable": false,
357
                        "searchable": false,
Lines 365-396 Link Here
365
                },
365
                },
366
            });
366
            });
367
367
368
            $('#auth_providers').on( "click", '.delete_auth_provider', function () {
368
            $('#identity_providers').on( "click", '.delete_identity_provider', function () {
369
                var auth_provider_id   = $(this).data('auth-provider-id');
369
                var identity_provider_id   = $(this).data('auth-provider-id');
370
                var auth_provider_code = decodeURIComponent($(this).data('auth-provider-code'));
370
                var identity_provider_code = decodeURIComponent($(this).data('auth-provider-code'));
371
371
372
                $("#delete_confirm_dialog").html(
372
                $("#delete_confirm_dialog").html(
373
                    _("You are about to delete the '%s' authentication provider.").format(auth_provider_code)
373
                    _("You are about to delete the '%s' identity provider.").format(identity_provider_code)
374
                );
374
                );
375
                $("#delete_confirm_modal_button").data('auth-provider-id', auth_provider_id);
375
                $("#delete_confirm_modal_button").data('auth-provider-id', identity_provider_id);
376
                $("#delete_confirm_modal_button").data('auth-provider-code', auth_provider_code);
376
                $("#delete_confirm_modal_button").data('auth-provider-code', identity_provider_code);
377
            });
377
            });
378
378
379
            $("#delete_confirm_modal_button").on( "click", function () {
379
            $("#delete_confirm_modal_button").on( "click", function () {
380
380
381
                var auth_provider_id   = $(this).data('auth-provider-id');
381
                var identity_provider_id   = $(this).data('auth-provider-id');
382
                var auth_provider_code = $(this).data('auth-provider-code');
382
                var identity_provider_code = $(this).data('auth-provider-code');
383
383
384
                $.ajax({
384
                $.ajax({
385
                    method: "DELETE",
385
                    method: "DELETE",
386
                    url: auth_providers_url+"/"+auth_provider_id
386
                    url: identity_providers_url+"/"+identity_provider_id
387
                }).success(function() {
387
                }).success(function() {
388
                    window.auth_providers.api().ajax.reload(function (data) {
388
                    window.identity_providers.api().ajax.reload(function (data) {
389
                        $("#auth_provider_action_result_dialog").hide();
389
                        $("#identity_provider_action_result_dialog").hide();
390
                        $("#auth_provider_delete_success").html(_("Server '%s' deleted successfully.").format(auth_provider_code)).show();
390
                        $("#identity_provider_delete_success").html(_("Server '%s' deleted successfully.").format(identity_provider_code)).show();
391
                    });
391
                    });
392
                }).fail(function () {
392
                }).fail(function () {
393
                    $("#auth_provider_delete_error").html(_("Error deleting server '%s'. Check the logs.").format(auth_provider_code)).show();
393
                    $("#identity_provider_delete_error").html(_("Error deleting server '%s'. Check the logs.").format(identity_provider_code)).show();
394
                }).done(function () {
394
                }).done(function () {
395
                    $("#delete_confirm_modal").modal('hide');
395
                    $("#delete_confirm_modal").modal('hide');
396
                });
396
                });
Lines 438-445 Link Here
438
                    },
438
                    },
439
                    mapping: {
439
                    mapping: {
440
                        email: "email",
440
                        email: "email",
441
                        given_name: "firstname",
441
                        firstname: "given_name",
442
	                    family_name: "surname"
442
	                    surname: "family_name"
443
                    }
443
                    }
444
                }
444
                }
445
            };
445
            };
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt (-4 / +4 lines)
Lines 84-92 Link Here
84
84
85
[% IF !TwoFA_prompt && !TwoFA_setup && !Koha.Preference('staffShibOnly') %]
85
[% IF !TwoFA_prompt && !TwoFA_setup && !Koha.Preference('staffShibOnly') %]
86
    <!-- login prompt time-->
86
    <!-- login prompt time-->
87
    [% SET auth_providers = AuthClient.get_providers('staff') %]
87
    [% SET identity_providers = AuthClient.get_providers('staff') %]
88
    [% IF ( ! auth_providers.empty ) %]
88
    [% IF ( ! identity_providers.empty ) %]
89
        [% FOREACH provider IN auth_providers %]
89
        [% FOREACH provider IN identity_providers %]
90
            <p class="clearfix">
90
            <p class="clearfix">
91
                <a href="[% provider.url | url %]" class="btn btn-light col-xs-12" id="provider_[% provider.code | html %]">
91
                <a href="[% provider.url | url %]" class="btn btn-light col-xs-12" id="provider_[% provider.code | html %]">
92
                    [% IF provider.icon_url %]
92
                    [% IF provider.icon_url %]
Lines 100-106 Link Here
100
        [% END %]
100
        [% END %]
101
        <hr/>
101
        <hr/>
102
        <p>If you do not have an external account, but do have a local account, you can still log in: </p>
102
        <p>If you do not have an external account, but do have a local account, you can still log in: </p>
103
    [% END # /IF  auth_providers.size %]
103
    [% END # /IF  identity_providers.size %]
104
104
105
    <form action="[% script_name | html %]" method="post" name="loginform" id="loginform">
105
    <form action="[% script_name | html %]" method="post" name="loginform" id="loginform">
106
        <input type="hidden" name="koha_login_context" value="intranet" />
106
        <input type="hidden" name="koha_login_context" value="intranet" />
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc (-4 / +4 lines)
Lines 384-392 Link Here
384
                            [% END %]
384
                            [% END %]
385
                        [% END %]
385
                        [% END %]
386
                        [% UNLESS Koha.Preference('opacShibOnly') %]
386
                        [% UNLESS Koha.Preference('opacShibOnly') %]
387
                            [% SET auth_providers = AuthClient.get_providers('opac') %]
387
                            [% SET identity_providers = AuthClient.get_providers('opac') %]
388
                            [% IF ( ! auth_providers.empty ) %]
388
                            [% IF ( ! identity_providers.empty ) %]
389
                                [% FOREACH provider IN auth_providers %]
389
                                [% FOREACH provider IN identity_providers %]
390
                                    <p class="clearfix">
390
                                    <p class="clearfix">
391
                                        <a href="[% provider.url | url %]" class="btn btn-light col-md-12" id="provider_[% provider.code | html %]">
391
                                        <a href="[% provider.url | url %]" class="btn btn-light col-md-12" id="provider_[% provider.code | html %]">
392
                                            [% IF provider.icon_url %]
392
                                            [% IF provider.icon_url %]
Lines 400-406 Link Here
400
                                [% END %]
400
                                [% END %]
401
                                <hr/>
401
                                <hr/>
402
                                <p>If you do not have an external account, but do have a local account, you can still log in: </p>
402
                                <p>If you do not have an external account, but do have a local account, you can still log in: </p>
403
                            [% END # /IF  auth_providers.size %]
403
                            [% END # /IF  identity_providers.size %]
404
                            <input type="hidden" name="koha_login_context" value="opac" />
404
                            <input type="hidden" name="koha_login_context" value="opac" />
405
                            <fieldset class="brief">
405
                            <fieldset class="brief">
406
                                <div class="local-login">
406
                                <div class="local-login">
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt (-4 / +4 lines)
Lines 163-171 Link Here
163
163
164
                            [% END # / IF casAuthentication %]
164
                            [% END # / IF casAuthentication %]
165
165
166
                            [% SET auth_providers = AuthClient.get_providers('opac') %]
166
                            [% SET identity_providers = AuthClient.get_providers('opac') %]
167
                            [% IF ( ! auth_providers.empty ) %]
167
                            [% IF ( ! identity_providers.empty ) %]
168
                                [% FOREACH provider IN auth_providers %]
168
                                [% FOREACH provider IN identity_providers %]
169
                                    <p class="clearfix">
169
                                    <p class="clearfix">
170
                                        <a href="[% provider.url | url %]" class="btn btn-light col-md-12" id="provider_[% provider.code | html %]">
170
                                        <a href="[% provider.url | url %]" class="btn btn-light col-md-12" id="provider_[% provider.code | html %]">
171
                                            [% IF provider.icon_url %]
171
                                            [% IF provider.icon_url %]
Lines 179-185 Link Here
179
                                [% END %]
179
                                [% END %]
180
                                <hr/>
180
                                <hr/>
181
                                <p>If you do not have an external account, but do have a local account, you can still log in: </p>
181
                                <p>If you do not have an external account, but do have a local account, you can still log in: </p>
182
                            [% END # /IF  auth_providers %]
182
                            [% END # /IF  identity_providers %]
183
183
184
                            [% IF ( Koha.Preference('GoogleOpenIDConnect') == 1 ) %]
184
                            [% IF ( Koha.Preference('GoogleOpenIDConnect') == 1 ) %]
185
                                [% IF ( invalidGoogleOpenIDConnectLogin ) %]
185
                                [% IF ( invalidGoogleOpenIDConnectLogin ) %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt (-4 / +4 lines)
Lines 192-200 Link Here
192
                                            <a href="/cgi-bin/koha/svc/auth/googleopenidconnect" class="btn btn-light" id="openid_connect"><i class="fa fa-google" aria-hidden="true"></i> Log in with Google</a>
192
                                            <a href="/cgi-bin/koha/svc/auth/googleopenidconnect" class="btn btn-light" id="openid_connect"><i class="fa fa-google" aria-hidden="true"></i> Log in with Google</a>
193
                                            <p>If you do not have a Google account, but do have a local account, you can still log in: </p>
193
                                            <p>If you do not have a Google account, but do have a local account, you can still log in: </p>
194
                                        [% END # /IF GoogleOpenIDConnect %]
194
                                        [% END # /IF GoogleOpenIDConnect %]
195
                                        [% SET auth_providers = AuthClient.get_providers('opac') %]
195
                                        [% SET identity_providers = AuthClient.get_providers('opac') %]
196
                                        [% IF ( ! auth_providers.empty ) %]
196
                                        [% IF ( ! identity_providers.empty ) %]
197
                                            [% FOREACH provider IN auth_providers %]
197
                                            [% FOREACH provider IN identity_providers %]
198
                                                <p class="clearfix">
198
                                                <p class="clearfix">
199
                                                    <a href="[% provider.url | url %]" class="btn btn-light col-md-12" id="provider_[% provider.code | html %]">
199
                                                    <a href="[% provider.url | url %]" class="btn btn-light col-md-12" id="provider_[% provider.code | html %]">
200
                                                        [% IF provider.icon_url %]
200
                                                        [% IF provider.icon_url %]
Lines 208-214 Link Here
208
                                            [% END %]
208
                                            [% END %]
209
                                            <hr/>
209
                                            <hr/>
210
                                            <p>If you do not have an external account, but do have a local account, you can still log in: </p>
210
                                            <p>If you do not have an external account, but do have a local account, you can still log in: </p>
211
                                        [% END # /IF  auth_providers.size %]
211
                                        [% END # /IF  identity_providers.size %]
212
                                        <div class="local-login">
212
                                        <div class="local-login">
213
                                            <label for="userid">Login:</label>
213
                                            <label for="userid">Login:</label>
214
                                            <input class="form-control" type="text" id="userid" name="userid" autocomplete="off" />
214
                                            <input class="form-control" type="text" id="userid" name="userid" autocomplete="off" />
(-)a/t/db_dependent/Koha/Auth/Client.t (+179 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2022 Theke Solutions
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 4;
23
24
use Test::MockModule;
25
use Test::Exception;
26
27
use JSON qw(encode_json);
28
use MIME::Base64 qw{ encode_base64url };
29
30
use Koha::Auth::Client;
31
use Koha::Auth::Client::OAuth;
32
use Koha::Patrons;
33
34
use t::lib::TestBuilder;
35
use t::lib::Mocks;
36
37
my $schema  = Koha::Database->new->schema;
38
my $builder = t::lib::TestBuilder->new;
39
40
subtest 'get_user() tests' => sub {
41
  plan tests => 4;
42
43
  $schema->storage->txn_begin;
44
45
  my $client   = Koha::Auth::Client::OAuth->new;
46
  my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { matchpoint => 'email' } } );
47
  my $domain   = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => '', allow_opac => 1, allow_staff => 0 } } );
48
  my $patron   = $builder->build_object( { class => 'Koha::Patrons', value => { email => 'patron@test.com' } } );
49
  my $mapping = {
50
    email     => 'electronic_mail',
51
    firstname => 'given_name',
52
	  surname   => 'family_name'
53
  };
54
  $provider->set_mapping($mapping)->store;
55
56
  my $id_token = 'header.'.encode_base64url(encode_json({
57
    electronic_mail => 'patron@test.com',
58
    given_name => 'test name'
59
  })).'.footer';
60
61
  my $data = {
62
    id_token => $id_token
63
  };
64
65
  my ($resolved_patron, $mapped_data, $resolved_domain) = $client->get_user({ provider => $provider->code, data => $data, interface => 'opac' });
66
  is_deeply( $resolved_patron->to_api, $patron->to_api, 'Patron correctly retrieved' );
67
  is( $mapped_data->{firstname}, 'test name', 'Data mapped correctly' );
68
  is( $mapped_data->{surname}, undef, 'No surname mapped');
69
  is( $domain->identity_provider_domain_id, $resolved_domain->identity_provider_domain_id, 'Is the same domain');
70
71
  $schema->storage->txn_rollback;
72
73
};
74
75
subtest 'get_valid_domain_config() tests' => sub {
76
  plan tests => 10;
77
78
  $schema->storage->txn_begin;
79
80
  my $client   = Koha::Auth::Client->new;
81
  my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { matchpoint => 'email' } } );
82
  my $domain1  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => '', allow_opac => 0, allow_staff => 0 } } );
83
  my $domain2  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => '*library.com', allow_opac => 1, allow_staff => 0 } } );
84
  my $domain3  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => '*.library.com', allow_opac => 1, allow_staff => 0 } } );
85
  my $domain4  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => 'student.library.com', allow_opac => 1, allow_staff => 0 } } );
86
  my $domain5  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => 'staff.library.com', allow_opac => 1, allow_staff => 1 } } );
87
88
  my $retrieved_domain;
89
90
  # Test @gmail.com
91
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@gmail.com', interface => 'opac'});
92
  is($retrieved_domain, undef, 'gmail user cannot enter opac');
93
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@gmail.com', interface => 'staff'});
94
  is($retrieved_domain, undef, 'gmail user cannot enter staff');
95
96
  # Test @otherlibrary.com
97
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@otherlibrary.com', interface => 'opac'});
98
  is($retrieved_domain->identity_provider_domain_id, $domain2->identity_provider_domain_id, 'otherlibaray user can enter opac with domain2');
99
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@otherlibrary.com', interface => 'staff'});
100
  is($retrieved_domain, undef, 'otherlibrary user cannot enter staff');
101
102
  # Test @provider.library.com
103
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@provider.library.com', interface => 'opac'});
104
  is($retrieved_domain->identity_provider_domain_id, $domain3->identity_provider_domain_id, 'provider.library user can enter opac with domain3');
105
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@provider.library.com', interface => 'staff'});
106
  is($retrieved_domain, undef, 'provider.library user cannot enter staff');
107
108
  # Test @student.library.com
109
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@student.library.com', interface => 'opac'});
110
  is($retrieved_domain->identity_provider_domain_id, $domain4->identity_provider_domain_id, 'student.library user can enter opac with domain4');
111
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@student.library.com', interface => 'staff'});
112
  is($retrieved_domain, undef, 'student.library user cannot enter staff');
113
114
  # Test @staff.library.com
115
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@staff.library.com', interface => 'opac'});
116
  is($retrieved_domain->identity_provider_domain_id, $domain5->identity_provider_domain_id, 'staff.library user can enter opac with domain5');
117
  $retrieved_domain = $client->get_valid_domain_config({ provider => $provider, email => 'user@staff.library.com', interface => 'staff'});
118
  is($retrieved_domain->identity_provider_domain_id, $domain5->identity_provider_domain_id, 'staff.library user can enter staff with domain5');
119
120
  $schema->storage->txn_rollback;
121
};
122
123
subtest 'has_valid_domain_config() tests' => sub {
124
  plan tests => 2;
125
  $schema->storage->txn_begin;
126
127
  my $client   = Koha::Auth::Client->new;
128
  my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { matchpoint => 'email' } } );
129
  my $domain1  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => '', allow_opac => 1, allow_staff => 0 } } );
130
131
  # Test @gmail.com
132
  my $retrieved_domain = $client->has_valid_domain_config({ provider => $provider, email => 'user@gmail.com', interface => 'opac'});
133
  is($retrieved_domain->identity_provider_domain_id, $domain1->identity_provider_domain_id, 'gmail user can enter opac with domain1');
134
  throws_ok { $client->has_valid_domain_config({ provider => $provider, email => 'user@gmail.com', interface => 'staff'}) } 'Koha::Exceptions::Auth::NoValidDomain', 'gmail user cannot enter staff';
135
136
  $schema->storage->txn_rollback;
137
};
138
139
subtest '_traverse_hash() tests' => sub {
140
  plan tests => 3;
141
142
  my $client   = Koha::Auth::Client->new;
143
144
  my $hash = {
145
    a => {
146
      hash => {
147
        with => 'complicated structure'
148
      }
149
    },
150
    an => {
151
      array => [
152
        {
153
          inside => 'a hash'
154
        },
155
        {
156
          inside => 'second element'
157
        }
158
      ]
159
    }
160
  };
161
162
  my $first_result = $client->_traverse_hash({
163
    base => $hash,
164
    keys => 'a.hash.with'
165
  });
166
  is($first_result, 'complicated structure', 'get the value whithin a hash structure');
167
168
  my $second_result = $client->_traverse_hash({
169
    base => $hash,
170
    keys => 'an.array.0.inside'
171
  });
172
  is($second_result, 'a hash', 'get the value of the first element of an array within a hash structure');
173
174
  my $third_result = $client->_traverse_hash({
175
    base => $hash,
176
    keys => 'an.array.1.inside'
177
  });
178
  is($third_result, 'second element', 'get the value of the second element of an array within a hash structure');
179
};
(-)a/t/db_dependent/Koha/Auth/Provider.t (-17 / +17 lines)
Lines 26-32 use Test::Exception; Link Here
26
26
27
use JSON qw(encode_json);
27
use JSON qw(encode_json);
28
28
29
use Koha::Auth::Providers;
29
use Koha::Auth::Identity::Providers;
30
30
31
use t::lib::TestBuilder;
31
use t::lib::TestBuilder;
32
use t::lib::Mocks;
32
use t::lib::Mocks;
Lines 40-53 subtest 'domains() tests' => sub { Link Here
40
40
41
    $schema->storage->txn_begin;
41
    $schema->storage->txn_begin;
42
42
43
    my $provider = $builder->build_object( { class => 'Koha::Auth::Providers' } );
43
    my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers' } );
44
    my $domains  = $provider->domains;
44
    my $domains  = $provider->domains;
45
45
46
    is( ref($domains),   'Koha::Auth::Provider::Domains', 'Type is correct' );
46
    is( ref($domains),   'Koha::Auth::Identity::Provider::Domains', 'Type is correct' );
47
    is( $domains->count, 0,                               'No domains defined' );
47
    is( $domains->count, 0,                               'No domains defined' );
48
48
49
    $builder->build_object( { class => 'Koha::Auth::Provider::Domains', value => { auth_provider_id => $provider->id } } );
49
    $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id } } );
50
    $builder->build_object( { class => 'Koha::Auth::Provider::Domains', value => { auth_provider_id => $provider->id } } );
50
    $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id } } );
51
51
52
    is( $provider->domains->count, 2, 'The provider has 2 domains defined' );
52
    is( $provider->domains->count, 2, 'The provider has 2 domains defined' );
53
53
Lines 60-66 subtest 'get_config() tests' => sub { Link Here
60
60
61
    $schema->storage->txn_begin;
61
    $schema->storage->txn_begin;
62
62
63
    my $provider = $builder->build_object( { class => 'Koha::Auth::Providers', value => { config => '{' } } );
63
    my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { config => '{' } } );
64
64
65
    throws_ok { $provider->get_config() }
65
    throws_ok { $provider->get_config() }
66
    'Koha::Exceptions::Object::BadValue', 'Expected exception thrown on bad JSON';
66
    'Koha::Exceptions::Object::BadValue', 'Expected exception thrown on bad JSON';
Lines 83-89 subtest 'set_config() tests' => sub { Link Here
83
83
84
        plan tests => 4;
84
        plan tests => 4;
85
85
86
        my $provider = $builder->build_object( { class => 'Koha::Auth::Providers', value => { protocol => 'OIDC' } } );
86
        my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { protocol => 'OIDC' } } );
87
        $provider = $provider->upgrade_class;
87
        $provider = $provider->upgrade_class;
88
88
89
        my $config = {
89
        my $config = {
Lines 99-105 subtest 'set_config() tests' => sub { Link Here
99
        $config->{well_known_url} = 'https://koha-community.org/auth';
99
        $config->{well_known_url} = 'https://koha-community.org/auth';
100
100
101
        my $return = $provider->set_config($config);
101
        my $return = $provider->set_config($config);
102
        is( ref($return), 'Koha::Auth::Provider::OIDC', 'Return type is correct' );
102
        is( ref($return), 'Koha::Auth::Identity::Provider::OIDC', 'Return type is correct' );
103
103
104
        is_deeply( $provider->get_config, $config, 'Configuration stored correctly' );
104
        is_deeply( $provider->get_config, $config, 'Configuration stored correctly' );
105
    };
105
    };
Lines 108-114 subtest 'set_config() tests' => sub { Link Here
108
108
109
        plan tests => 4;
109
        plan tests => 4;
110
110
111
        my $provider = $builder->build_object( { class => 'Koha::Auth::Providers', value => { protocol => 'OAuth' } } );
111
        my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { protocol => 'OAuth' } } );
112
        $provider = $provider->upgrade_class;
112
        $provider = $provider->upgrade_class;
113
113
114
        my $config = {
114
        my $config = {
Lines 125-131 subtest 'set_config() tests' => sub { Link Here
125
        $config->{authorize_url} = 'https://koha-community.org/auth/authorize';
125
        $config->{authorize_url} = 'https://koha-community.org/auth/authorize';
126
126
127
        my $return = $provider->set_config($config);
127
        my $return = $provider->set_config($config);
128
        is( ref($return), 'Koha::Auth::Provider::OAuth', 'Return type is correct' );
128
        is( ref($return), 'Koha::Auth::Identity::Provider::OAuth', 'Return type is correct' );
129
129
130
        is_deeply( $provider->get_config, $config, 'Configuration stored correctly' );
130
        is_deeply( $provider->get_config, $config, 'Configuration stored correctly' );
131
    };
131
    };
Lines 134-140 subtest 'set_config() tests' => sub { Link Here
134
134
135
        plan tests => 2;
135
        plan tests => 2;
136
136
137
        my $provider = $builder->build_object( { class => 'Koha::Auth::Providers', value => { protocol => 'CAS' } } );
137
        my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { protocol => 'CAS' } } );
138
138
139
        throws_ok { $provider->set_config() }
139
        throws_ok { $provider->set_config() }
140
        'Koha::Exception', 'Exception thrown on unsupported protocol';
140
        'Koha::Exception', 'Exception thrown on unsupported protocol';
Lines 151-157 subtest 'get_mapping() tests' => sub { Link Here
151
151
152
    $schema->storage->txn_begin;
152
    $schema->storage->txn_begin;
153
153
154
    my $provider = $builder->build_object( { class => 'Koha::Auth::Providers', value => { config => '{' } } );
154
    my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { config => '{' } } );
155
155
156
    throws_ok { $provider->get_mapping() }
156
    throws_ok { $provider->get_mapping() }
157
    'Koha::Exceptions::Object::BadValue', 'Expected exception thrown on bad JSON';
157
    'Koha::Exceptions::Object::BadValue', 'Expected exception thrown on bad JSON';
Lines 170-176 subtest 'set_mapping() tests' => sub { Link Here
170
170
171
    $schema->storage->txn_begin;
171
    $schema->storage->txn_begin;
172
172
173
    my $provider = $builder->build_object( { class => 'Koha::Auth::Providers' } );
173
    my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers' } );
174
174
175
    my $mapping = { some => 'value', and => 'another' };
175
    my $mapping = { some => 'value', and => 'another' };
176
    $provider->set_mapping($mapping)->store;
176
    $provider->set_mapping($mapping)->store;
Lines 186-210 subtest 'upgrade_class() tests' => sub { Link Here
186
186
187
    $schema->storage->txn_begin;
187
    $schema->storage->txn_begin;
188
188
189
    my $mapping   = Koha::Auth::Provider::protocol_to_class_mapping;
189
    my $mapping   = Koha::Auth::Identity::Provider::protocol_to_class_mapping;
190
    my @protocols = keys %{ $mapping };
190
    my @protocols = keys %{ $mapping };
191
191
192
    foreach my $protocol (@protocols) {
192
    foreach my $protocol (@protocols) {
193
193
194
        my $provider = $builder->build_object(
194
        my $provider = $builder->build_object(
195
            {
195
            {
196
                class => 'Koha::Auth::Providers',
196
                class => 'Koha::Auth::Identity::Providers',
197
                value => { protocol => $protocol },
197
                value => { protocol => $protocol },
198
            }
198
            }
199
        );
199
        );
200
200
201
        is( ref($provider), 'Koha::Auth::Provider', "Base class used for $protocol" );
201
        is( ref($provider), 'Koha::Auth::Identity::Provider', "Base class used for $protocol" );
202
        # upgrade
202
        # upgrade
203
        $provider = $provider->upgrade_class;
203
        $provider = $provider->upgrade_class;
204
        is( ref($provider), $mapping->{$protocol}, "Class upgraded to " . $mapping->{$protocol} . "for protocol $protocol" );
204
        is( ref($provider), $mapping->{$protocol}, "Class upgraded to " . $mapping->{$protocol} . "for protocol $protocol" );
205
    }
205
    }
206
206
207
    my $provider = Koha::Auth::Provider->new({ protocol => 'Invalid' });
207
    my $provider = Koha::Auth::Identity::Provider->new({ protocol => 'Invalid' });
208
    throws_ok
208
    throws_ok
209
      { $provider->upgrade }
209
      { $provider->upgrade }
210
      'Koha::Exception',
210
      'Koha::Exception',
(-)a/t/db_dependent/Koha/REST/Plugin/Auth/IdP.t (+133 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2022 Theke Solutions
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Koha::Patrons;
23
use Koha::Auth::Identity::Provider::Domains;
24
use Koha::Patrons;
25
use Try::Tiny;
26
27
# Dummy app for testing the plugin
28
use Mojolicious::Lite;
29
30
plugin 'Koha::REST::Plugin::Auth::IdP';
31
32
post '/register_user' => sub {
33
  my $c = shift;
34
  my $params = $c->req->json;
35
  try {
36
    my $domain = Koha::Auth::Identity::Provider::Domains->find($params->{domain_id});
37
    my $patron = $c->auth->register({
38
      data => $params->{data},
39
      domain => $domain,
40
      interface => $params->{interface}
41
    });
42
    $c->render(status => 200, json => $patron->to_api);
43
  } catch {
44
    if ( ref($_) eq 'Koha::Exceptions::Auth::Unauthorized' ) {
45
      $c->render(status => 401, json => {message => 'unauthorized'});
46
    } else {
47
      $c->render(status => 500, json => {message => 'other error'});
48
    }
49
  }
50
};
51
52
post '/start_session' => sub {
53
  my $c = shift;
54
  my $userid = my $params = $c->req->json->{userid};
55
56
  try {
57
    my $patron = Koha::Patrons->search({userid => $userid});
58
    my ($status, $cookie, $session_id) = $c->auth->session($patron->next);
59
    $c->render(status => 200, json => {status => $status});
60
  } catch {
61
    if ( ref($_) eq 'Koha::Exceptions::Auth::CannotCreateSession' ) {
62
      $c->render(status => 401, json => {message => 'unauthorized'});
63
    } else {
64
      $c->render(status => 500, json => {message => 'other error'});
65
    }
66
  }
67
};
68
69
use Test::More tests => 2;
70
use Test::Mojo;
71
72
use t::lib::Mocks;
73
use t::lib::TestBuilder;
74
use Koha::Database;
75
76
my $schema  = Koha::Database->new()->schema();
77
my $builder = t::lib::TestBuilder->new;
78
79
# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling
80
# this affects the other REST api tests
81
t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' );
82
83
subtest 'auth.register helper' => sub {
84
  plan tests => 6;
85
86
  $schema->storage->txn_begin;
87
88
  # Remove existing patrons
89
  Koha::Patrons->delete;
90
  my $provider = $builder->build_object( { class => 'Koha::Auth::Identity::Providers', value => { matchpoint => 'email' } } );
91
  my $domain_with_register  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => 'domain1.com', auto_register => 1 } } );
92
  my $domain_without_register  = $builder->build_object( { class => 'Koha::Auth::Identity::Provider::Domains', value => { identity_provider_id => $provider->id, domain => 'domain2.com', auto_register => 0 } } );
93
  my $library = $builder->build_object({ class => 'Koha::Libraries'});
94
  my $category = $builder->build_object( {class => 'Koha::Patron::Categories'});
95
  my $user_data = {
96
    firstname => 'test',
97
    surname => 'test',
98
    userid => 'id1',
99
    branchcode => $library->branchcode,
100
    categorycode => $category->categorycode
101
  };
102
103
  my $t = Test::Mojo->new;
104
105
  $t->post_ok('/register_user' => json => {data => $user_data, domain_id => $domain_with_register->identity_provider_domain_id, interface => 'opac'})
106
    ->status_is(200)
107
    ->json_has('/firstname', 'test');
108
109
  $t->post_ok('/register_user' => json => {data => $user_data, domain_id => $domain_without_register->identity_provider_domain_id, interface => 'opac'})
110
    ->status_is(401)
111
    ->json_has('/message', 'unauthorized');
112
  $schema->storage->txn_rollback;
113
};
114
115
subtest 'auth.session helper' => sub {
116
  plan tests => 3;
117
118
  $schema->storage->txn_begin;
119
120
  # Remove existing patrons
121
  Koha::Patrons->delete;
122
  my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
123
124
125
  my $t = Test::Mojo->new;
126
  $t->post_ok('/start_session' => json => {userid => $patron->userid})
127
    ->status_is(200)
128
    ->json_has('/status', 'ok');
129
130
  $schema->storage->txn_rollback;
131
};
132
133
1;
(-)a/t/db_dependent/api/v1/idp.t (+341 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright 2022 Theke Solutions
4
#
5
# This file is part of Koha
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use Test::More tests => 3;
23
use Test::Mojo;
24
use Test::Warn;
25
use Mojo::JWT;
26
use Crypt::OpenSSL::RSA;
27
28
use t::lib::TestBuilder;
29
use t::lib::Mocks;
30
31
use Koha::Database;
32
use C4::Auth;
33
use Koha::Auth::Identity::Providers;
34
use Koha::Auth::Identity::Provider::Domains;
35
36
my $schema  = Koha::Database->new->schema;
37
my $builder = t::lib::TestBuilder->new;
38
39
# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling
40
# this affects the other REST api tests
41
t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' );
42
43
my $remote_address = '127.0.0.1';
44
45
use t::lib::IdP::ExternalIdP;
46
47
my $idp_port = t::lib::IdP::ExternalIdP->start;
48
49
50
my $oauth_provider_data = {
51
  code        => 'oauth_test',
52
  description => 'OAuth provider',
53
  protocol    => 'OAuth',
54
  mapping     => {
55
        email     => 'users.0.email',
56
        firstname => 'users.0.custom_name',
57
        surname   => 'users.0.custom_surname',
58
        userid    => 'users.0.id'
59
  },
60
  matchpoint  => 'email',
61
  config      => {
62
    authorize_url => "http://localhost:$idp_port/idp/test/authorization_endpoint",
63
    token_url     => "http://localhost:$idp_port/idp/test/token_endpoint/without_id_token",
64
    userinfo_url  => "http://localhost:$idp_port/idp/test/userinfo_endpoint",
65
    key           => "client_id",
66
    secret        => "client_secret"
67
  }
68
};
69
70
my $oidc_with_email_provider_data = {
71
  code => 'oidc_email',
72
  description => 'OIDC wiht email provider',
73
  protocol => 'OIDC',
74
  mapping => {
75
    email     => 'email',
76
    firstname => 'given_name',
77
    surname   => 'family_name',
78
    userid    => 'sub'
79
  },
80
  matchpoint => 'email',
81
  config => {
82
    authorize_url  => "http://localhost:$idp_port/idp/test/authorization_endpoint",
83
    well_known_url => "http://localhost:$idp_port/idp/test/with_email/.well_known",
84
    key            => "client_id",
85
    secret         => "client_secret"
86
  }
87
};
88
89
my $oidc_without_email_provider_data = {
90
  code => 'oidc_no_email',
91
  description => 'OIDC wihtout email provider',
92
  protocol => 'OIDC',
93
  mapping => {
94
    email     => 'users.0.email',
95
    firstname => 'given_name',
96
    surname   => 'family_name',
97
    userid    => 'sub'
98
  },
99
  matchpoint => 'email',
100
  config => {
101
    authorize_url  => "http://localhost:$idp_port/idp/test/authorization_endpoint",
102
    well_known_url => "http://localhost:$idp_port/idp/test/without_email/.well_known",
103
    key            => "client_id",
104
    secret         => "client_secret"
105
  }
106
};
107
108
my $domain_not_matching = {
109
  domain => 'gmail.com',
110
  auto_register => 0,
111
  update_on_auth => 0,
112
  default_library_id => undef,
113
  default_category_id => undef,
114
  allow_opac => 1,
115
  allow_staff => 0
116
};
117
118
my $domain_no_register = {
119
  domain => 'some.library.com',
120
  auto_register => 0,
121
  update_on_auth => 0,
122
  default_library_id => undef,
123
  default_category_id => undef,
124
  allow_opac => 1,
125
  allow_staff => 0
126
};
127
128
my $library = $builder->build_object({class => 'Koha::Libraries'});
129
my $category = $builder->build_object({class => 'Koha::Patron::Categories'});
130
131
my $domain_register = {
132
  domain => 'some.library.com',
133
  auto_register => 1,
134
  update_on_auth => 0,
135
  default_library_id => $library->branchcode,
136
  default_category_id => $category->categorycode,
137
  allow_opac => 1,
138
  allow_staff => 1
139
};
140
141
my $domain_register_update = {
142
  domain => 'some.library.com',
143
  auto_register => 1,
144
  update_on_auth => 1,
145
  default_library_id => $library->branchcode,
146
  default_category_id => $category->categorycode,
147
  allow_opac => 1,
148
  allow_staff => 0
149
};
150
151
subtest 'provider endpoint tests' => sub {
152
  plan tests => 12;
153
154
  $schema->storage->txn_begin;
155
156
  Koha::Auth::Identity::Provider::Domains->delete;
157
  Koha::Auth::Identity::Providers->delete;
158
159
  my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
160
161
  my $t = Test::Mojo->new('Koha::REST::V1');
162
163
  my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers", json => $oauth_provider_data );
164
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
165
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
166
167
  $t->request_ok($tx)
168
    ->status_is(201);
169
170
  my $provider = Koha::Auth::Identity::Providers->search({code => 'oauth_test'})->next;
171
  is ($provider->code, 'oauth_test', 'Provider was created');
172
173
  $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers" );
174
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
175
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
176
177
  $t->request_ok($tx)
178
    ->json_has('/0/code', 'oauth_test');
179
180
  my %modified_provider_data_hash = %{$oauth_provider_data};
181
  my $modified_provider_data = \%modified_provider_data_hash;
182
  $modified_provider_data->{code} = 'some_code';
183
184
  $tx = $t->ua->build_tx( PUT => "/api/v1/auth/identity_providers/".$provider->identity_provider_id, json => $modified_provider_data);
185
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
186
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
187
188
  $t->request_ok($tx)
189
    ->status_is(200);
190
191
  $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/".$provider->identity_provider_id);
192
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
193
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
194
195
  $t->request_ok($tx)
196
    ->json_has('/code', 'some_code');
197
198
  $tx = $t->ua->build_tx( DELETE => "/api/v1/auth/identity_providers/".$provider->identity_provider_id);
199
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
200
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
201
202
  $t->request_ok($tx)
203
    ->status_is(204);
204
  # p $t->tx->res;
205
206
  $provider = Koha::Auth::Identity::Providers->search->next;
207
  is ($provider, undef, 'All providers deleted');
208
209
  $schema->storage->txn_rollback;
210
};
211
212
subtest 'domain endpoint tests' => sub {
213
  plan tests => 12;
214
215
  $schema->storage->txn_begin;
216
217
  Koha::Auth::Identity::Provider::Domains->delete;
218
  Koha::Auth::Identity::Providers->delete;
219
220
  my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
221
222
  my $t = Test::Mojo->new('Koha::REST::V1');
223
224
  my $provider = $builder->build_object({class => 'Koha::Auth::Identity::Providers'});
225
226
  my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains", json => $domain_not_matching );
227
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
228
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
229
230
  $t->request_ok($tx)
231
    ->status_is(201);
232
233
  my $domain = Koha::Auth::Identity::Provider::Domains->search({domain => 'gmail.com'})->next;
234
  is ($domain->domain, 'gmail.com', 'Provider was created');
235
236
  $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains" );
237
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
238
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
239
240
  $t->request_ok($tx)
241
    ->json_has('/0/domain', 'gmail.com');
242
243
  my %modified_domain_data_hash = %{$domain_not_matching};
244
  my $modified_domain_data = \%modified_domain_data_hash;
245
  $modified_domain_data->{domain} = 'some.domain.com';
246
247
  $tx = $t->ua->build_tx( PUT => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains/".$domain->identity_provider_domain_id, json => $modified_domain_data);
248
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
249
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
250
251
  $t->request_ok($tx)
252
    ->status_is(200);
253
254
  $tx = $t->ua->build_tx( GET => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains/".$domain->identity_provider_domain_id);
255
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
256
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
257
258
  $t->request_ok($tx)
259
    ->json_has('/domain', 'some.domain.com');
260
261
  $tx = $t->ua->build_tx( DELETE => "/api/v1/auth/identity_providers/".$provider->identity_provider_id."/domains/".$domain->identity_provider_domain_id);
262
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
263
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
264
265
  $t->request_ok($tx)
266
    ->status_is(204);
267
  # p $t->tx->res;
268
269
  $domain = Koha::Auth::Identity::Provider::Domains->search->next;
270
  is ($domain, undef, 'All domains deleted');
271
272
  $schema->storage->txn_rollback;
273
};
274
275
subtest 'oauth login tests' => sub {
276
  plan tests => 4;
277
278
  $schema->storage->txn_begin;
279
280
  Koha::Auth::Identity::Provider::Domains->delete;
281
  Koha::Auth::Identity::Providers->delete;
282
283
  my ( $borrowernumber, $session_id ) = create_user_and_session({ authorized => 1 });
284
285
  my $t = Test::Mojo->new('Koha::REST::V1');
286
287
  # Build provider
288
  my $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers", json => $oauth_provider_data );
289
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
290
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
291
292
  $t->request_ok($tx);
293
  my $provider_id = $t->tx->res->json->{identity_provider_id};
294
295
  # Build domain
296
  $tx = $t->ua->build_tx( POST => "/api/v1/auth/identity_providers/$provider_id/domains", json => $domain_not_matching );
297
  $tx->req->cookies( { name => 'CGISESSID', value => $session_id } );
298
  $tx->req->env( { REMOTE_ADDR => $remote_address } );
299
300
  $t->request_ok($tx);
301
302
  t::lib::Mocks::mock_preference( 'RESTPublicAPI', 1 );
303
304
  # Simulate server restart
305
  $t = Test::Mojo->new('Koha::REST::V1');
306
307
  #$t->ua->max_redirects(10);
308
  $t->get_ok("/api/v1/public/oauth/login/oauth_test/opac")
309
    ->status_is(302);
310
  use Data::Printer colored => 1;
311
  p $t->tx->res;
312
313
  $schema->storage->txn_rollback;
314
};
315
316
sub create_user_and_session {
317
318
    my $args  = shift;
319
    my $flags = ( $args->{authorized} ) ? 1 : 0;
320
321
    my $user = $builder->build(
322
        {
323
            source => 'Borrower',
324
            value  => {
325
                flags => $flags
326
            }
327
        }
328
    );
329
330
    # Create a session for the authorized user
331
    my $session = C4::Auth::get_session('');
332
    $session->param( 'number',   $user->{borrowernumber} );
333
    $session->param( 'id',       $user->{userid} );
334
    $session->param( 'ip',       $remote_address );
335
    $session->param( 'lasttime', time() );
336
    $session->flush;
337
338
    return ( $user->{borrowernumber}, $session->id );
339
}
340
341
1;
(-)a/t/lib/IdP/ExternalIdP.pm (-1 / +166 lines)
Line 0 Link Here
0
- 
1
package t::lib::IdP::ExternalIdP;
2
3
use Mojolicious::Lite;
4
use Mojo::IOLoop;
5
use Mojo::IOLoop::Server;
6
use Mojo::Server::Daemon;
7
8
print "Configure idp routes\n";
9
10
any '/idp/test/authorization_endpoint' => sub {
11
  my $c = shift;
12
  print "pasa por acá\n";
13
  return $c->render(json => {error => 'invalid_request'}, status => 500)
14
    unless (3 == grep { $c->param($_) } qw(response_type redirect_uri client_id))
15
      && $c->param('response_type') eq 'code';
16
17
  my $url = Mojo::URL->new($c->param('redirect_uri'));
18
  $url->query({code => 'authorize-code', state => $c->param('state')});
19
  return $c->redirect_to($url);
20
};
21
22
any '/idp/test/token_endpoint/with_id_token/with_email' => sub {
23
  my $c = shift;
24
  return $c->render(json => {error => 'invalid_request'}, status => 500)
25
    unless (4 == grep { $c->param($_) } qw(client_id client_secret redirect_uri code))
26
      && $c->param('code') eq 'authorize-code';
27
28
  my $claims = {
29
    aud                => $c->param('client_id'),
30
    email              => 'test.user@some.library.com',
31
    iss                => $c->url_for('/idp/test')->to_abs,
32
    given_name         => 'test',
33
    family_name        => 'user',
34
    preferred_username => 'test.user@some.library.com',
35
    sub                => 'test.user'
36
  };
37
38
  my $rsa = Crypt::OpenSSL::RSA->generate_key(2048);
39
40
  my $id_token = Mojo::JWT->new(
41
    algorithm => 'RS256',
42
    secret    => $rsa->get_private_key_string,
43
    set_iat   => 1,
44
    claims    => $claims,
45
    header    => {kid => 'TEST_SIGNING_KEY'}
46
  );
47
48
  $c->render(status => 200, json => {
49
  access_token => 'access',
50
  expires_in => 3599,
51
  ext_expires_in => 3599,
52
  id_token => $id_token,
53
  refresh_token => 'refresh-token',
54
  scope => 'openid',
55
  token_type => 'Bearer'
56
  });
57
};
58
59
any '/idp/test/token_endpoint/with_id_token/without_email' => sub {
60
  my $c = shift;
61
  return $c->render(json => {error => 'invalid_request'}, status => 500)
62
    unless (4 == grep { $c->param($_) } qw(client_id client_secret redirect_uri code))
63
      && $c->param('code') eq 'authorize-code';
64
65
  my $claims = {
66
    aud                => $c->param('client_id'),
67
    iss                => $c->url_for('/idp/test')->to_abs,
68
    given_name         => 'test',
69
    family_name        => 'user',
70
    preferred_username => 'test.user',
71
    sub                => 'test.user'
72
  };
73
74
  my $rsa = Crypt::OpenSSL::RSA->generate_key(2048);
75
76
  my $id_token = Mojo::JWT->new(
77
    algorithm => 'RS256',
78
    secret    => $rsa->get_private_key_string,
79
    set_iat   => 1,
80
    claims    => $claims,
81
    header    => {kid => 'TEST_SIGNING_KEY'}
82
  );
83
84
  $c->render(status => 200, json => {
85
  access_token => 'access',
86
  expires_in => 3599,
87
  ext_expires_in => 3599,
88
  id_token => $id_token,
89
  refresh_token => 'refresh-token',
90
  scope => 'openid',
91
  token_type => 'Bearer'
92
  });
93
};
94
95
any '/idp/test/token_endpoint/without_id_token' => sub {
96
  my $c = shift;
97
  return $c->render(json => {error => 'invalid_request'}, status => 500)
98
    unless (4 == grep { $c->param($_) } qw(client_id client_secret redirect_uri code))
99
      && $c->param('code') eq 'authorize-code';
100
101
  $c->render(status => 200, json => {
102
  access_token => 'access',
103
  expires_in => 3599,
104
  ext_expires_in => 3599,
105
  refresh_token => 'refresh-token',
106
  scope => 'some list of scopes',
107
  token_type => 'Bearer'
108
  });
109
};
110
111
any '/idp/test/userinfo_endpoint' => sub {
112
  my $c = shift;
113
  return $c->render(text => 'Unauthorized', status => 401)
114
    unless $c->req->headers->authorization eq 'Bearer access';
115
116
  $c->render(status => 200, json => {
117
    users => [
118
      {
119
        email          => 'test.user@some.library.com',
120
        custom_name    => 'test',
121
        custom_surname => 'user',
122
        id             => 'test.user',
123
        last_login     => 'a long time ago'
124
      }
125
    ]
126
  });
127
};
128
129
any '/idp/test/with_email/.well_known' => sub {
130
  my $c = shift;
131
132
  $c->render(status => 200, json => {
133
    authorization_endpoint => $c->url_for('/idp/test/authorization_endpoint')->to_abs,
134
    token_endpoint => $c->url_for('/idp/test/token_endpoint/with_id_token/with_email')->to_abs,
135
    userinfo_endpoint => $c->url_for('/idp/test/userinfo_endpoint')->to_abs,
136
  });
137
};
138
139
any '/idp/test/without_email/.well_known' => sub {
140
  my $c = shift;
141
142
  $c->render(status => 200, json => {
143
    authorization_endpoint => $c->url_for('/idp/test/authorization_endpoint')->to_abs,
144
    token_endpoint => $c->url_for('/idp/test/token_endpoint/with_id_token/without_email')->to_abs,
145
    userinfo_endpoint => $c->url_for('/idp/test/userinfo_endpoint')->to_abs,
146
  });
147
};
148
149
my $port   = Mojo::IOLoop::Server->generate_port;
150
my $daemon = Mojo::Server::Daemon->new(
151
  app    => app,
152
  listen => ["http://*:$port"]
153
);
154
155
sub start {
156
  print "Run daemon\n";
157
  $daemon->start;
158
  Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
159
  return $port;
160
}
161
162
sub stop {
163
  $daemon->stop;
164
}
165
166
1;

Return to bug 31378