diff -rupN koha.original/intranet/htdocs/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref koha/intranet/htdocs/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref --- koha.original/intranet/htdocs/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref 2014-02-24 15:08:45.671011598 +0800 +++ koha/intranet/htdocs/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref 2014-02-24 15:13:37.015030253 +0800 @@ -113,3 +113,20 @@ Administration: Solr: Solr Zebra: Zebra - is the search engine used. + 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 + - pref: GoogleOAuth2Domain diff -rupN koha.original/lib/C4/Auth.pm koha/lib/C4/Auth.pm --- koha.original/lib/C4/Auth.pm 2014-02-24 15:08:49.825000508 +0800 +++ koha/lib/C4/Auth.pm 2014-02-24 15:12:36.814285381 +0800 @@ -34,7 +34,7 @@ use POSIX qw/strftime/; use List::MoreUtils qw/ any /; # use utf8; -use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $caslogout); +use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $googleoauth2 $ldap $cas $caslogout); BEGIN { sub psgi_env { any { /^psgi\./ } keys %ENV } @@ -52,6 +52,7 @@ BEGIN { ParseSearchHistoryCookie ); %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'); $caslogout = C4::Context->preference('casLogout'); @@ -399,6 +400,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"}:"", @@ -1092,6 +1094,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 -rupN koha.original/opac/cgi-bin/opac/svc/googleoauth2 koha/opac/cgi-bin/opac/svc/googleoauth2 --- koha.original/opac/cgi-bin/opac/svc/googleoauth2 1970-01-01 08:00:00.000000000 +0800 +++ koha/opac/cgi-bin/opac/svc/googleoauth2 2014-02-24 15:20:31.902504871 +0800 @@ -0,0 +1,130 @@ +opyright 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# +# 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 strict; +use warnings; +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'); +my $redirecturl = 'http://' . $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 . '&'; + } + $authorisationurl .= 'prompt=' . escape ( $query->param('reauthenticate') ); + print $query->redirect($authorisationurl); +} + + diff -rupN koha.original/opac/htdocs/opac-tmpl/bootstrap/en/includes/masthead.inc koha/opac/htdocs/opac-tmpl/bootstrap/en/includes/masthead.inc --- koha.original/opac/htdocs/opac-tmpl/bootstrap/en/includes/masthead.inc 2014-02-24 15:09:47.181847438 +0800 +++ koha/opac/htdocs/opac-tmpl/bootstrap/en/includes/masthead.inc 2014-02-24 15:15:25.479596560 +0800 @@ -58,7 +58,11 @@
  • New list
  • [% END %] [% ELSE %] -
  • Log in to create your own lists
  • + [% IF ( GoogleOAuth2 ) %] +
  • Log in to create your own lists
  • + [% ELSE %] +
  • Log in to create your own lists
  • + [% END %] [% END # / IF loggedinusername %] [% END # / IF opacuserlogin %] @@ -71,8 +75,12 @@
    - \ No newline at end of file + diff -rupN koha.original/opac/htdocs/opac-tmpl/bootstrap/en/modules/opac-auth.tt koha/opac/htdocs/opac-tmpl/bootstrap/en/modules/opac-auth.tt --- koha.original/opac/htdocs/opac-tmpl/bootstrap/en/modules/opac-auth.tt 2014-02-24 15:09:47.528846512 +0800 +++ koha/opac/htdocs/opac-tmpl/bootstrap/en/modules/opac-auth.tt 2014-02-24 15:16:04.111449097 +0800 @@ -84,6 +84,15 @@ [% END # / IF casAuthentication %] + [% IF ( invalidOAuth2Login ) %] +

    Automatic Login

    +

    Sorry, your automatic login failed. [% invalidOAuth2Login %]

    +

    Please note that automatic login will only work if you are using the email address registered with this library.

    +

    If you want to, you can try to login using a differen account +

    Local login

    +

    If you can't login automatically, you can still login in manually:

    + [% END %] +
    diff -rupN koha.original/opac/htdocs/opac-tmpl/ccsr/en/includes/top-bar.inc koha/opac/htdocs/opac-tmpl/ccsr/en/includes/top-bar.inc --- koha.original/opac/htdocs/opac-tmpl/ccsr/en/includes/top-bar.inc 2014-02-24 15:09:49.195842064 +0800 +++ koha/opac/htdocs/opac-tmpl/ccsr/en/includes/top-bar.inc 2014-02-24 15:16:54.998259806 +0800 @@ -55,7 +55,11 @@ [% IF ( opacuserlogin ) %]