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

(-)a/C4/Auth.pm (+7 lines)
Lines 1245-1250 sub checkauth { Link Here
1245
        );
1245
        );
1246
    }
1246
    }
1247
1247
1248
    if (C4::Context->preference('GoogleOAuth2')) {
1249
        if ($query->param("OAuth2Failed")) {
1250
            my $reason = $query->param('OAuth2Failed');
1251
            $template->param(invalidOAuth2Login => $reason);
1252
        }
1253
    }
1254
1248
    $template->param(
1255
    $template->param(
1249
        LibraryName => C4::Context->preference("LibraryName"),
1256
        LibraryName => C4::Context->preference("LibraryName"),
1250
    );
1257
    );
(-)a/installer/data/mysql/atomicupdate/googleoauth2.sql (+5 lines)
Line 0 Link Here
1
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES
2
	('GoogleOAuth2', '0', NULL, 'if ON, allows the use of Google OAuth2 for login', 'YesNo'),
3
        ('GoogleOAuth2ClientID', '', NULL, 'Client ID for the web app registered with google', 'Free'),
4
        ('GoogleOAuth2ClientSecret', '', NULL, 'Client Secret for the web app registered with google', 'Free'),
5
        ('GoogleOAuth2Domain', '', NULL, 'Restrict OAuth2 to this domain (or subdomains of this domain). Leave blank for all google domains', 'Free');
(-)a/installer/data/mysql/sysprefs.sql (+4 lines)
Lines 145-150 INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` Link Here
145
('gist','0','','Default Goods and Services tax rate NOT in %, but in numeric form (0.12 for 12%), set to 0 to disable GST','Integer'),
145
('gist','0','','Default Goods and Services tax rate NOT in %, but in numeric form (0.12 for 12%), set to 0 to disable GST','Integer'),
146
('GoogleIndicTransliteration','0','','GoogleIndicTransliteration on the OPAC.','YesNo'),
146
('GoogleIndicTransliteration','0','','GoogleIndicTransliteration on the OPAC.','YesNo'),
147
('GoogleJackets','0',NULL,'if ON, displays jacket covers from Google Books API','YesNo'),
147
('GoogleJackets','0',NULL,'if ON, displays jacket covers from Google Books API','YesNo'),
148
('GoogleOAuth2', '0', NULL, 'if ON, allows the use of Google OAuth2 for login', 'YesNo'),
149
('GoogleOAuth2ClientID', '', NULL, 'Client ID for the web app registered with google', 'Free'),
150
('GoogleOAuth2ClientSecret', '', NULL, 'Client Secret for the web app registered with google', 'Free'),
151
('GoogleOAuth2Domain', '', NULL, 'Restrict OAuth2 to this domain (or subdomains of this domain). Leave blank for all google domains', 'Free'),
148
('hidelostitems','0','','If ON, disables display of\"lost\" items in OPAC.','YesNo'),
152
('hidelostitems','0','','If ON, disables display of\"lost\" items in OPAC.','YesNo'),
149
('HidePatronName','0','','If this is switched on, patron\'s cardnumber will be shown instead of their name on the holds and catalog screens','YesNo'),
153
('HidePatronName','0','','If this is switched on, patron\'s cardnumber will be shown instead of their name on the holds and catalog screens','YesNo'),
150
('hide_marc','0',NULL,'If ON, disables display of MARC fields, subfield codes & indicators (still shows data)','YesNo'),
154
('hide_marc','0',NULL,'If ON, disables display of MARC fields, subfield codes & indicators (still shows data)','YesNo'),
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref (+18 lines)
Lines 114-119 Administration: Link Here
114
                  Common Name: the Common Name
114
                  Common Name: the Common Name
115
                  emailAddress: the emailAddress
115
                  emailAddress: the emailAddress
116
            - field for SSL client certificate authentication
116
            - field for SSL client certificate authentication
117
    Google OAuth2:
118
        -
119
            - pref: GoogleOAuth2
120
              choices:
121
                yes: Use
122
                no: "Don't Use"
123
            - Google OAuth2 login.
124
            - You will need to select OAuth2 when creating an app in the google cloud console, and set the web origin to your_opac_url and the redirect url to your_opac_url/cgi-bin/koha/svc/auth/googleoauth2 .
125
        -
126
            - Google OAuth2 Client ID
127
            - pref: GoogleOAuth2ClientID
128
        -
129
            - Google OAuth2 Client Secret
130
            - pref: GoogleOAuth2ClientSecret
131
        -
132
            - Google OAuth2 Restrict to domain (or subdomain of this domain)
133
            - pref: GoogleOAuth2Domain
134
            - . Leave blank for all google domains
117
    Mozilla Persona:
135
    Mozilla Persona:
118
        -
136
        -
119
            - pref: Persona
137
            - pref: Persona
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc (+4 lines)
Lines 59-64 Link Here
59
                                                <li role="presentation"><a href="#" tabindex="-1" class="menu-inactive" role="menuitem">No private lists</a></li>
59
                                                <li role="presentation"><a href="#" tabindex="-1" class="menu-inactive" role="menuitem">No private lists</a></li>
60
                                                <li role="presentation"><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves" tabindex="-1" role="menuitem" class="listmenulink">New list</a></li>
60
                                                <li role="presentation"><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves" tabindex="-1" role="menuitem" class="listmenulink">New list</a></li>
61
                                            [% END %]
61
                                            [% END %]
62
                                        [% ELSIF ( Koha.Preference('GoogleOAuth2') == 1 ) %]
63
                                            <li role="presentation"><a href="/cgi-bin/koha/svc/googleoauth2" tabindex="-1" class="menu-inactive" role="menuitem">Log in to create your own lists</a></li>
62
                                        [% ELSE %]
64
                                        [% ELSE %]
63
                                            <li role="presentation"><a href="/cgi-bin/koha/opac-user.pl" tabindex="-1" class="menu-inactive loginModal-trigger" role="menuitem">Log in to create your own lists</a></li>
65
                                            <li role="presentation"><a href="/cgi-bin/koha/opac-user.pl" tabindex="-1" class="menu-inactive loginModal-trigger" role="menuitem">Log in to create your own lists</a></li>
64
                                        [% END # / IF loggedinusername %]
66
                                        [% END # / IF loggedinusername %]
Lines 113-118 Link Here
113
                                        [% IF Koha.Preference('casAuthentication') %]
115
                                        [% IF Koha.Preference('casAuthentication') %]
114
                                            [%# CAS authentication is too complicated for modal window %]
116
                                            [%# CAS authentication is too complicated for modal window %]
115
                                            <li><a href="/cgi-bin/koha/opac-user.pl">Log in to your account</a></li>
117
                                            <li><a href="/cgi-bin/koha/opac-user.pl">Log in to your account</a></li>
118
                                        [% ELSIF ( Koha.Preference('GoogleOAuth2') == 1 ) %]
119
                                            <li><a href="/cgi-bin/koha/svc/googleoauth2" role="button" data-toggle="modal">Log in to your account</a></li>
116
                                        [% ELSE %]
120
                                        [% ELSE %]
117
                                            <li><a href="/cgi-bin/koha/opac-user.pl" class="loginModal-trigger" role="button" data-toggle="modal">Log in to your account</a></li>
121
                                            <li><a href="/cgi-bin/koha/opac-user.pl" class="loginModal-trigger" role="button" data-toggle="modal">Log in to your account</a></li>
118
                                        [% END %]
122
                                        [% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt (+9 lines)
Lines 138-143 Link Here
138
138
139
                            [% END # / IF casAuthentication %]
139
                            [% END # / IF casAuthentication %]
140
140
141
                            [% IF ( invalidOAuth2Login ) %]
142
                                <h4>Automatic Login</h4>
143
                                <p>Sorry, your automatic login failed. <span class="error">[% invalidOAuth2Login %]</span></p>
144
                                <p>Please note that automatic login will only work if you are using the emal address registered with this library.</p>
145
                                <p>If you want to, you can try to <a href="/cgi-bin/koha/svc/googleoauth2?reauthenticate=select_account">login using a different account</a>
146
                                <h4>Local login</h4>
147
                                <p>If you can't login automatically, you can still login manually: </p>
148
                            [% END %]
149
141
                            <form action="/cgi-bin/koha/opac-user.pl" name="auth" id="auth" method="post">
150
                            <form action="/cgi-bin/koha/opac-user.pl" name="auth" id="auth" method="post">
142
                                <input type="hidden" name="koha_login_context" value="opac" />
151
                                <input type="hidden" name="koha_login_context" value="opac" />
143
                                <fieldset class="brief">
152
                                <fieldset class="brief">
(-)a/opac/svc/auth/googleoauth2 (-1 / +169 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
# Copyright vanoudt@gmail.com 2014
3
# Based on persona code from chris@bigballofwax.co.nz 2013
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
#
21
# Basic OAuth2 authentication for google goes like this First:
22
# get your clientid, clientsecret from google. At this stage, tell
23
# google that your redirect url is /cgi-bin/koha/svc/oauthlogin
24
#
25
# The first thing that happens when this script is called is
26
# that one gets redirected to an authentication url from google
27
#
28
# If successful, that then redirects back to this script, setting
29
# a CODE parameter which we use to look up a json authentication
30
# token. This token includes an encrypted json id_token, which we
31
# round-trip back to google to decrypt. Finally, we can extract
32
# the email address from this.
33
#
34
# There is some room for improvement here.  In particular, Google
35
# recommends verifying and decrypting the id_token locally, which
36
# means caching some information and updating it daily. But that
37
# would make things a lot faster
38
39
use Modern::Perl;
40
use CGI qw ( -utf8 escape );
41
use C4::Auth;
42
use C4::Context;
43
use C4::Output;
44
45
use LWP::UserAgent;
46
use HTTP::Request::Common qw{ POST };
47
use JSON;
48
49
my $scope            = "openid email";
50
my $host             = C4::Context->preference('OPACBaseURL') // '';
51
my $restricttodomain = C4::Context->preference('GoogleOAuth2Domain') // '';
52
53
# protocol is assumed in OPACBaseURL see bug 5010.
54
my $redirecturl  = $host . '/cgi-bin/koha/svc/googleoauth2';
55
my $issuer       = 'accounts.google.com';
56
my $clientid     = C4::Context->preference('GoogleOAuth2ClientID');
57
my $clientsecret = C4::Context->preference('GoogleOAuth2ClientSecret');
58
59
my $query = new CGI;
60
61
sub loginfailed {
62
    my $query  = shift;
63
    my $reason = shift;
64
    $query->delete('code');
65
    $query->param( 'OAuth2Failed' => $reason );
66
    my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
67
        {
68
            template_name   => 'opac-user.tt',
69
            query           => $query,
70
            type            => 'opac',
71
            authnotrequired => 0,
72
            flagsrequired   => { borrow => 1 },
73
        }
74
    );
75
    $template->param( 'invalidOAuth2Login' => $reason );
76
    $template->param( 'loginprompt'        => 1 );
77
    output_html_with_http_headers $query, $cookie, $template->output;
78
}
79
80
if ( defined $query->param('error') ) {
81
    loginfailed( $query,
82
            'An authentication error occurred. (Error:'
83
          . $query->param('error')
84
          . ')' );
85
}
86
elsif ( defined $query->param('code') ) {
87
    my $code    = $query->param('code');
88
    my $ua      = LWP::UserAgent->new();
89
    my $request = POST(
90
        'https://accounts.google.com/o/oauth2/token',
91
        [
92
            code          => $code,
93
            client_id     => $clientid,
94
            client_secret => $clientsecret,
95
            redirect_uri  => $redirecturl,
96
            grant_type    => 'authorization_code',
97
            $scope        => $scope
98
        ]
99
    );
100
    my $response = $ua->request($request)->decoded_content;
101
    my $json     = decode_json($response);
102
    if ( exists( $json->{'id_token'} ) ) {
103
        $request = POST( 'https://www.googleapis.com/oauth2/v1/tokeninfo',
104
            [ id_token => $json->{'id_token'} ] );
105
        $response = $ua->request($request)->decoded_content;
106
        $json     = decode_json($response);
107
108
# Confirm (as google suggests) that the issuer and audience are what we expect them to be
109
        if (   ( $json->{'issuer'} eq $issuer )
110
            && ( $json->{'audience'} eq $clientid )
111
            && exists( $json->{'email'} ) )
112
        {
113
            my $email = $json->{'email'};
114
            my ( $userid, $cookie, $sessionID ) =
115
              checkauth( $query, 1, { borrow => 1 }, 'opac', $email );
116
            if ($userid) {    # A valid user has logged in
117
                if (   ( $restricttodomain ne '' )
118
                    && ( index( $email, $restricttodomain ) == -1 ) )
119
                {
120
                    loginfailed( $query,
121
'The email you have used is not valid for this library. Email addresses should conclude with '
122
                          . $restricttodomain
123
                          . ' .' );
124
                }
125
                else {
126
                    print $query->redirect(
127
                        -uri    => '/cgi-bin/koha/opac-user.pl',
128
                        -cookie => $cookie
129
                    );
130
                }
131
            }
132
            else {
133
                loginfailed( $query,
134
'The email address you are trying to use is not associated with a borrower in this library.'
135
                );
136
            }
137
        }
138
        else {    # something went wrong with getting appropriate credentials
139
            loginfailed( $query,
140
                'Failed to get proper credentials from google.' );
141
        }
142
    }
143
    else {        # Failed to get ID Token
144
        loginfailed( $query,
145
'An authentication error occurred. (Error: No ID Token was supplied)'
146
        );
147
    }
148
149
}
150
else {
151
    my $prompt = '';
152
    $prompt = $query->param('reauthenticate')
153
      unless not( defined $query->param('reauthenticate') );
154
155
    my $authorisationurl =
156
        'https://accounts.google.com/o/oauth2/auth?'
157
      . 'response_type=code&'
158
      . 'redirect_uri='
159
      . escape($redirecturl) . '&'
160
      . 'client_id='
161
      . escape($clientid) . '&'
162
      . 'scope='
163
      . escape($scope) . '&';
164
    if ( $query->param('reauthenticate') ) {
165
        $authorisationurl .=
166
          'prompt=' . escape( $query->param('reauthenticate') );
167
    }
168
    print $query->redirect($authorisationurl);
169
}

Return to bug 10988