Bugzilla – Attachment 40979 Details for
Bug 10988
Allow login via Google OAuth2 (OpenID Connect)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 10988: Allow login via Google OAuth2
Bug 10988 - Allow login via Google OAuth2.patch (text/plain), 17.19 KB, created by
Nicholas van Oudtshoorn
on 2015-07-14 05:12:53 UTC
(
hide
)
Description:
Bug 10988: Allow login via Google OAuth2
Filename:
MIME Type:
Creator:
Nicholas van Oudtshoorn
Created:
2015-07-14 05:12:53 UTC
Size:
17.19 KB
patch
obsolete
>From 785e4e1aec37cf16076076b6c544c14dc67f0c75 Mon Sep 17 00:00:00 2001 >From: Nicholas van Oudtshoorn <vanoudt@gmail.com> >Date: Tue, 14 Jul 2015 13:10:33 +0800 >Subject: [PATCH] [PATCH] Bug 10988: Allow login via Google OAuth2 > >Adds googleoauth2 login to koha. Adds applicable system >preferences Modifies templates to support oauth2 login >failures changes the login links to use googleoauth2 when >oauth2 is enabled. > >Updated patch to address the concerns in Comment 36. > >Test Plan: > 0) Back up your database > 1) Apply this patch > 2) In your mysql client use your Koha database and execute: > > DELETE FROM systempreferences; > > SOURCE ~/kohaclone/installer/data/mysql/sysprefs.sql; > -- Should be no errors. > > SELECT * FROM systempreferences LIKE 'GoogleOAuth%'; > -- Should see 4 entries. > > QUIT; > 3) Restore your database > 4) Run ./installer/data/mysql/updatedatabase.pl; > 5) In your mysql client use your Koha database and execute: > > SELECT * FROM systempreferences LIKE 'GoogleOAuth%'; > -- Should see the same 4 entries. > 6) Log into the staff client > 7) Home -> Koha administration -> Global system preferences > 8) -> OPAC > -- make sure your OPACBaseURL is set (e.g. https://opac.koha.ca) > 9) -> Administration > -- There should be a 'Google OAuth2' section with the ability > to set those 4 system preferences. >10) In a new tab, go to https://console.developers.google.com/project >11) Click 'Create Project' >12) Type in a project name that won't freak users out, like your > library name (e.g. South Pole Library). >13) Click the 'Create' button. >14) Click the 'APIs & auth' in the left frame. >15) Click 'Credentials' >16) Click 'Create new Client ID' >17) Select 'Web application' and click 'Configure consent screen'. >18) Select the Email Address. >19) Put it a meaningful string into the Product Name > (e.g. South Pole Library Authentication) >20) Fill in the other fields as desired (or not) >21) Click 'Save' >22) Change the 'AUTHORIZED JAVASCRIPT ORIGINS' to your OPACBaseURL. > (http://library.yourDNS.org) >23) Change the 'AUTHORIZED REDIRECT URIS' to point to the new > googleoauth2 script > (http://library.yourDNS.org/cgi-bin/koha/svc/auth/googleoauth2) >24) Click 'Create Client ID' >25) Copy and paste the 'CLIENT ID' into the GoogleOAuth2ClientID > system preference. >26) Copy and paste the 'CLIENT SECRET' into the GoogleOAuth2ClientSecret > system preference. >27) Change the GoogleOAuth2 preference to 'Use'. >28) Click 'Save all Administration preferences' >29) In the OPAC, click 'Log in to your account'. > -- You should get a confirmation request, if you are > already logged in, OR a login screen if you are not. > -- You need to have the primary email address set to one > authenticated by Google in order to log in. >30) Run koha qa test tools >--- > C4/Auth.pm | 7 + > installer/data/mysql/atomicupdate/googleoauth2.sql | 5 + > installer/data/mysql/sysprefs.sql | 4 + > .../prog/en/modules/admin/preferences/admin.pref | 18 +++ > .../opac-tmpl/bootstrap/en/includes/masthead.inc | 4 + > .../opac-tmpl/bootstrap/en/modules/opac-auth.tt | 9 ++ > opac/svc/auth/googleoauth2 | 169 +++++++++++++++++++++ > 7 files changed, 216 insertions(+) > create mode 100644 installer/data/mysql/atomicupdate/googleoauth2.sql > create mode 100755 opac/svc/auth/googleoauth2 > >diff --git a/C4/Auth.pm b/C4/Auth.pm >index 268ef35..4b6cd25 100644 >--- a/C4/Auth.pm >+++ b/C4/Auth.pm >@@ -1247,6 +1247,13 @@ sub checkauth { > ); > } > >+ if (C4::Context->preference('GoogleOAuth2')) { >+ if ($query->param("OAuth2Failed")) { >+ my $reason = $query->param('OAuth2Failed'); >+ $template->param(invalidOAuth2Login => $reason); >+ } >+ } >+ > my $self_url = $query->url( -absolute => 1 ); > $template->param( > url => $self_url, >diff --git a/installer/data/mysql/atomicupdate/googleoauth2.sql b/installer/data/mysql/atomicupdate/googleoauth2.sql >new file mode 100644 >index 0000000..9096d24 >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/googleoauth2.sql >@@ -0,0 +1,5 @@ >+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES >+ ('GoogleOAuth2', '0', NULL, 'if ON, allows the use of Google OAuth2 for login', 'YesNo'), >+ ('GoogleOAuth2ClientID', '', NULL, 'Client ID for the web app registered with google', 'Free'), >+ ('GoogleOAuth2ClientSecret', '', NULL, 'Client Secret for the web app registered with google', 'Free'), >+ ('GoogleOAuth2Domain', '', NULL, 'Restrict OAuth2 to this domain (or subdomains of this domain). Leave blank for all google domains', 'Free'); >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index a343571..cfeba69 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -138,6 +138,10 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` > ('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'), > ('GoogleIndicTransliteration','0','','GoogleIndicTransliteration on the OPAC.','YesNo'), > ('GoogleJackets','0',NULL,'if ON, displays jacket covers from Google Books API','YesNo'), >+('GoogleOAuth2', '0', NULL, 'if ON, allows the use of Google OAuth2 for login', 'YesNo'), >+('GoogleOAuth2ClientID', '', NULL, 'Client ID for the web app registered with google', 'Free'), >+('GoogleOAuth2ClientSecret', '', NULL, 'Client Secret for the web app registered with google', 'Free'), >+('GoogleOAuth2Domain', '', NULL, 'Restrict OAuth2 to this domain (or subdomains of this domain). Leave blank for all google domains', 'Free'), > ('hidelostitems','0','','If ON, disables display of\"lost\" items in OPAC.','YesNo'), > ('HidePatronName','0','','If this is switched on, patron\'s cardnumber will be shown instead of their name on the holds and catalog screens','YesNo'), > ('hide_marc','0',NULL,'If ON, disables display of MARC fields, subfield codes & indicators (still shows data)','YesNo'), >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref >index 4ec683f..8ed2841 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref >@@ -114,6 +114,24 @@ Administration: > Common Name: the Common Name > emailAddress: the emailAddress > - field for SSL client certificate authentication >+ Google OAuth2: >+ - >+ - pref: GoogleOAuth2 >+ choices: >+ yes: Use >+ no: "Don't Use" >+ - Google OAuth2 login. >+ - 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 . >+ - >+ - Google OAuth2 Client ID >+ - pref: GoogleOAuth2ClientID >+ - >+ - Google OAuth2 Client Secret >+ - pref: GoogleOAuth2ClientSecret >+ - >+ - Google OAuth2 Restrict to domain (or subdomain of this domain) >+ - pref: GoogleOAuth2Domain >+ - . Leave blank for all google domains > Mozilla Persona: > - > - pref: Persona >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc >index 1ccd2be..37fc757 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc >@@ -59,6 +59,8 @@ > <li role="presentation"><a href="#" tabindex="-1" class="menu-inactive" role="menuitem">No private lists</a></li> > <li role="presentation"><a href="/cgi-bin/koha/opac-shelves.pl?display=privateshelves" tabindex="-1" role="menuitem" class="listmenulink">New list</a></li> > [% END %] >+ [% ELSIF ( Koha.Preference('GoogleOAuth2') == 1 ) %] >+ <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> > [% ELSE %] > <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> > [% END # / IF loggedinusername %] >@@ -113,6 +115,8 @@ > [% IF Koha.Preference('casAuthentication') %] > [%# CAS authentication is too complicated for modal window %] > <li><a href="/cgi-bin/koha/opac-user.pl">Log in to your account</a></li> >+ [% ELSIF ( Koha.Preference('GoogleOAuth2') == 1 ) %] >+ <li><a href="/cgi-bin/koha/svc/googleoauth2" role="button" data-toggle="modal">Log in to your account</a></li> > [% ELSE %] > <li><a href="/cgi-bin/koha/opac-user.pl" class="loginModal-trigger" role="button" data-toggle="modal">Log in to your account</a></li> > [% END %] >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt >index c474791..28e206d 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt >@@ -138,6 +138,15 @@ > > [% END # / IF casAuthentication %] > >+ [% IF ( invalidOAuth2Login ) %] >+ <h4>Automatic Login</h4> >+ <p>Sorry, your automatic login failed. <span class="error">[% invalidOAuth2Login %]</span></p> >+ <p>Please note that automatic login will only work if you are using the emal address registered with this library.</p> >+ <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> >+ <h4>Local login</h4> >+ <p>If you can't login automatically, you can still login manually: </p> >+ [% END %] >+ > <form action="[% url %]" name="auth" id="auth" method="post"> > <input type="hidden" name="koha_login_context" value="opac" /> > <fieldset class="brief"> >diff --git a/opac/svc/auth/googleoauth2 b/opac/svc/auth/googleoauth2 >new file mode 100755 >index 0000000..ee8826e >--- /dev/null >+++ b/opac/svc/auth/googleoauth2 >@@ -0,0 +1,169 @@ >+#!/usr/bin/perl >+# Copyright vanoudt@gmail.com 2014 >+# Based on persona code from chris@bigballofwax.co.nz 2013 >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+# >+# >+# Basic OAuth2 authentication for google goes like this First: >+# get your clientid, clientsecret from google. At this stage, tell >+# google that your redirect url is /cgi-bin/koha/svc/oauthlogin >+# >+# The first thing that happens when this script is called is >+# that one gets redirected to an authentication url from google >+# >+# If successful, that then redirects back to this script, setting >+# a CODE parameter which we use to look up a json authentication >+# token. This token includes an encrypted json id_token, which we >+# round-trip back to google to decrypt. Finally, we can extract >+# the email address from this. >+# >+# There is some room for improvement here. In particular, Google >+# recommends verifying and decrypting the id_token locally, which >+# means caching some information and updating it daily. But that >+# would make things a lot faster >+ >+use Modern::Perl; >+use CGI qw ( -utf8 escape ); >+use C4::Auth; >+use C4::Context; >+use C4::Output; >+ >+use LWP::UserAgent; >+use HTTP::Request::Common qw{ POST }; >+use JSON; >+ >+my $scope = "openid email"; >+my $host = C4::Context->preference('OPACBaseURL') // ''; >+my $restricttodomain = C4::Context->preference('GoogleOAuth2Domain') // ''; >+ >+# protocol is assumed in OPACBaseURL see bug 5010. >+my $redirecturl = $host . '/cgi-bin/koha/svc/googleoauth2'; >+my $issuer = 'accounts.google.com'; >+my $clientid = C4::Context->preference('GoogleOAuth2ClientID'); >+my $clientsecret = C4::Context->preference('GoogleOAuth2ClientSecret'); >+ >+my $query = new CGI; >+ >+sub loginfailed { >+ my $query = shift; >+ my $reason = shift; >+ $query->delete('code'); >+ $query->param( 'OAuth2Failed' => $reason ); >+ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >+ { >+ template_name => 'opac-user.tt', >+ query => $query, >+ type => 'opac', >+ authnotrequired => 0, >+ flagsrequired => { borrow => 1 }, >+ } >+ ); >+ $template->param( 'invalidOAuth2Login' => $reason ); >+ $template->param( 'loginprompt' => 1 ); >+ output_html_with_http_headers $query, $cookie, $template->output; >+} >+ >+if ( defined $query->param('error') ) { >+ loginfailed( $query, >+ 'An authentication error occurred. (Error:' >+ . $query->param('error') >+ . ')' ); >+} >+elsif ( defined $query->param('code') ) { >+ my $code = $query->param('code'); >+ my $ua = LWP::UserAgent->new(); >+ my $request = POST( >+ 'https://accounts.google.com/o/oauth2/token', >+ [ >+ code => $code, >+ client_id => $clientid, >+ client_secret => $clientsecret, >+ redirect_uri => $redirecturl, >+ grant_type => 'authorization_code', >+ $scope => $scope >+ ] >+ ); >+ my $response = $ua->request($request)->decoded_content; >+ my $json = decode_json($response); >+ if ( exists( $json->{'id_token'} ) ) { >+ $request = POST( 'https://www.googleapis.com/oauth2/v1/tokeninfo', >+ [ id_token => $json->{'id_token'} ] ); >+ $response = $ua->request($request)->decoded_content; >+ $json = decode_json($response); >+ >+# Confirm (as google suggests) that the issuer and audience are what we expect them to be >+ if ( ( $json->{'issuer'} eq $issuer ) >+ && ( $json->{'audience'} eq $clientid ) >+ && exists( $json->{'email'} ) ) >+ { >+ my $email = $json->{'email'}; >+ my ( $userid, $cookie, $sessionID ) = >+ checkauth( $query, 1, { borrow => 1 }, 'opac', $email ); >+ if ($userid) { # A valid user has logged in >+ if ( ( $restricttodomain ne '' ) >+ && ( index( $email, $restricttodomain ) == -1 ) ) >+ { >+ loginfailed( $query, >+'The email you have used is not valid for this library. Email addresses should conclude with ' >+ . $restricttodomain >+ . ' .' ); >+ } >+ else { >+ print $query->redirect( >+ -uri => '/cgi-bin/koha/opac-user.pl', >+ -cookie => $cookie >+ ); >+ } >+ } >+ else { >+ loginfailed( $query, >+'The email address you are trying to use is not associated with a borrower in this library.' >+ ); >+ } >+ } >+ else { # something went wrong with getting appropriate credentials >+ loginfailed( $query, >+ 'Failed to get proper credentials from google.' ); >+ } >+ } >+ else { # Failed to get ID Token >+ loginfailed( $query, >+'An authentication error occurred. (Error: No ID Token was supplied)' >+ ); >+ } >+ >+} >+else { >+ my $prompt = ''; >+ $prompt = $query->param('reauthenticate') >+ unless not( defined $query->param('reauthenticate') ); >+ >+ my $authorisationurl = >+ 'https://accounts.google.com/o/oauth2/auth?' >+ . 'response_type=code&' >+ . 'redirect_uri=' >+ . escape($redirecturl) . '&' >+ . 'client_id=' >+ . escape($clientid) . '&' >+ . 'scope=' >+ . escape($scope) . '&'; >+ if ( $query->param('reauthenticate') ) { >+ $authorisationurl .= >+ 'prompt=' . escape( $query->param('reauthenticate') ); >+ } >+ print $query->redirect($authorisationurl); >+} >-- >2.1.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 10988
:
21740
|
21936
|
21938
|
21939
|
25343
|
25570
|
25684
|
29594
|
29595
|
30014
|
30015
|
36354
|
36355
|
40087
|
40252
|
40442
|
40979
|
41663
|
43791
|
43792
|
43938
|
45667
|
45668
|
45895
|
46016
|
46473
|
46474
|
47780
|
47781
|
47782
|
49785
|
49786
|
49787