Bugzilla – Attachment 36354 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), 18.57 KB, created by
Mark Tompsett
on 2015-03-02 23:50:15 UTC
(
hide
)
Description:
Bug 10988 - Allow login via Google OAuth2
Filename:
MIME Type:
Creator:
Mark Tompsett
Created:
2015-03-02 23:50:15 UTC
Size:
18.57 KB
patch
obsolete
>From e137e3c4015f43d747b42fc6dbb44ef735214fbd Mon Sep 17 00:00:00 2001 >From: Mark Tompsett <mtompset@hotmail.com> >Date: Mon, 2 Mar 2015 17:44:53 -0500 >Subject: [PATCH] Bug 10988 - Allow login via Google OAuth2 > >This is my rework of a patch by Nicholas van Oudtshoorn. >Fixed the patch so that it again cleanly applies. > >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. > >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) -> Administration > -- There should be a 'Google OAuth2' section with the ability > to set those 4 system preferences. > 9) In a new tab, go to https://console.developers.google.com/project >10) Click 'Create Project' >11) Type in a project name that won't freak users out, like your > library name (e.g. South Pole Library). >12) Click the 'Create' button. >13) Click the 'APIs & auth' in the left frame. >14) Click 'Credentials' >15) Click 'Create new Client ID' >16) Select 'Web application' and click 'Configure consent screen'. >17) Select the Email Address. >18) Put it a meaningful string into the Product Name > (e.g. South Pole Library Authentication) >19) Fill in the other fields as desired (or not) >20) Click 'Save' >21) Change the 'AUTHORIZED JAVASCRIPT ORIGINS' to your OPACBaseURL. > (http://library.yourDNS.org) >22) Change the 'AUTHORIZED REDIRECT URIS' to point to the new > googleoauth2 script > (http://library.yourDNS.org/cgi-bin/koha/svc/googleoauth2) >23) Click 'Create Client ID' >24) Copy and paste the 'CLIENT ID' into the GoogleOAuth2ClientID > system preference. >25) Copy and paste the 'CLIENT SECRET' into the GoogleOAuth2ClientSecret > system preference. >26) Change the GoogleOAuth2 preference to 'Use'. >27) Click 'Save all Administration preferences' >28) 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. >29) Run koha qa test tools >--- > C4/Auth.pm | 11 +- > installer/data/mysql/sysprefs.sql | 4 + > installer/data/mysql/updatedatabase.pl | 16 ++ > .../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/googleoauth2 | 161 +++++++++++++++++++++ > 7 files changed, 222 insertions(+), 1 deletion(-) > create mode 100755 opac/svc/googleoauth2 > >diff --git a/C4/Auth.pm b/C4/Auth.pm >index 22f1e8e..960bceb 100644 >--- a/C4/Auth.pm >+++ b/C4/Auth.pm >@@ -37,7 +37,7 @@ use List::MoreUtils qw/ any /; > use Encode qw( encode is_utf8); > > # use utf8; >-use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout $shib $shib_login); >+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $googleoauth2 $ldap $cas $caslogout $shib $shib_login); > > BEGIN { > sub psgi_env { any { /^psgi\./ } keys %ENV } >@@ -55,6 +55,7 @@ BEGIN { > &get_all_subpermissions &get_user_subpermissions > ); > %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] ); >+ $googleoauth2 = C4::Context->preference('GoogleOAuth2'); > $ldap = C4::Context->config('useldapserver') || 0; > $cas = C4::Context->preference('casAuthentication'); > $shib = C4::Context->config('useshibboleth') || 0; >@@ -465,6 +466,7 @@ sub get_template_and_user { > BranchesLoop => GetBranchesLoop($opac_name), > BranchCategoriesLoop => GetBranchCategories( 'searchdomain', 1, $opac_name ), > CalendarFirstDayOfWeek => ( C4::Context->preference("CalendarFirstDayOfWeek") eq "Sunday" ) ? 0 : 1, >+ GoogleOAuth2 => (C4::Context->preference("GoogleOAuth2")), > LibraryName => "" . C4::Context->preference("LibraryName"), > LibraryNameTitle => "" . $LibraryNameTitle, > LoginBranchname => C4::Context->userenv ? C4::Context->userenv->{"branchname"} : "", >@@ -1240,6 +1242,13 @@ sub checkauth { > ); > } > >+ if ($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/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index 9020b4b..6fe81d3 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -134,6 +134,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/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 0ed56c6..070ec36 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -9793,6 +9793,22 @@ if(CheckVersion($DBversion)) { > SetVersion($DBversion); > } > >+$DBversion = "XXX"; >+if(CheckVersion($DBversion)) { >+ $dbh->do(q{ >+ 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') >+ }); >+ >+ print "Upgrade to $DBversion done (Bug 10988: Allow login via Google OAuth2)\n"; >+ SetVersion($DBversion); >+} >+ > =head1 FUNCTIONS > > =head2 TableExists($table) >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 e1d54a6..d22d958 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/oauthlogin . >+ - >+ - 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 904c232..0f5290a 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/masthead.inc >@@ -58,6 +58,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 ( GoogleOAuth2 ) %] >+ <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 %] >@@ -76,6 +78,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 ( GoogleOAuth2 ) %] >+ <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 a82b079..4f809a8 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/googleoauth2 b/opac/svc/googleoauth2 >new file mode 100755 >index 0000000..e058a60 >--- /dev/null >+++ b/opac/svc/googleoauth2 >@@ -0,0 +1,161 @@ >+#!/usr/bin/perl -w >+# 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/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.tmpl', >+ 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; >+} >+ >+#die $query->param('code'); >+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 >+ 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 ( $restricttodomain ne '' ) { >+ $authorisationurl .= 'hd=' . $restricttodomain . '&'; >+ } >+ if ( $query->param('reauthenticate') ) { >+ $authorisationurl .= 'prompt=' . escape( $query->param('reauthenticate') ); >+ } >+ print $query->redirect($authorisationurl); >+} >-- >1.9.1
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