#!/bin/perl -w
# Copyright 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 LOTS of room for improvement here.
# 1. move the clientid, clientsecret to systempreferences
# 2. use the OPACBaseURL preference to compute the redirecturl
# 3. See if this works on plain http (only tested on https
# 4. 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 CGI;
use strict;
use warnings;
use C4::Auth;
use C4::Context;

use LWP::UserAgent; 
use HTTP::Request::Common qw{ POST };
use LWP::Authen::OAuth2;
use JSON;

my $clientid = "OBTAIN FROM GOOGLE";
my $clientsecret = "OBTAIN FROM GOOGLE";
my $scope = "https://www.googleapis.com/auth/userinfo.email";
my $host = C4::Context->preference('OPACBaseURL');
my $redirecturl = "https://library.pbc.wa.edu.au/cgi-bin/koha/svc/oauthlogin";
my $issuer = "accounts.google.com";

my $query = new CGI;


if (defined $query->param('error')) {
	die "Authentication failed: " .$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->header . $cookie;
				print $query->redirect( -uri => "/cgi-bin/koha/opac-user.pl", -cookie => $cookie );
			} else {
				die "Email not associated with a borrower";
			}
		} else {
		#Login failed, invalid 
			die "Failed to get appropriate OAuth2 credentials";
		}
	} else {
		die "Failed to get appropriate OAuth2 credentials";
	}	

} else {
         my $oauth2 = LWP::Authen::OAuth2->new(
            client_id => $clientid,
            client_secret => $clientsecret,
            service_provider => "Google",
            response_type => "code",
            redirect_uri => $redirecturl,
            scope => $scope,
        );
       
	my $url = $oauth2->authorization_url();
	print CGI->redirect($url);
}

