Subversion Repositories oidplus

Rev

Rev 496 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
432 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
511 daniel-mar 5
 * Copyright 2019 - 2021 Daniel Marschall, ViaThinkSoft
432 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
20
# More information about the OAuth2 implementation:
21
# - https://developers.google.com/identity/protocols/oauth2/openid-connect
22
 
23
require_once __DIR__ . '/../../../includes/oidplus.inc.php';
24
 
25
OIDplus::init(true);
440 daniel-mar 26
set_exception_handler(array('OIDplusGui', 'html_exception_handler'));
432 daniel-mar 27
 
28
if (!OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_ENABLED', false)) {
29
        throw new OIDplusException(_L('Google OAuth authentication is disabled on this system.'));
30
}
31
 
32
if (!isset($_GET['code'])) die();
33
if (!isset($_GET['state'])) die();
34
 
35
if ($_GET['state'] != $_COOKIE['csrf_token']) {
36
        die('Invalid CSRF token');
37
}
38
 
484 daniel-mar 39
if (!function_exists('curl_init')) {
464 daniel-mar 40
        die(_L('The "%1" PHP extension is not installed at your system. Please enable the PHP extension <code>%2</code>.','CURL','php_curl'));
463 daniel-mar 41
}
42
 
432 daniel-mar 43
$ch = curl_init();
496 daniel-mar 44
if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . '3p/certs/cacert.pem');
432 daniel-mar 45
curl_setopt($ch, CURLOPT_URL,"https://oauth2.googleapis.com/token");
46
curl_setopt($ch, CURLOPT_POST, 1);
47
curl_setopt($ch, CURLOPT_POSTFIELDS,
48
        "grant_type=authorization_code&".
49
        "code=".$_GET['code']."&".
496 daniel-mar 50
        "redirect_uri=".urlencode(OIDplus::webpath(__DIR__,false).'oauth.php')."&".
432 daniel-mar 51
        "client_id=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_ID'))."&".
52
        "client_secret=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_SECRET'))
53
);
54
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
55
$cont = curl_exec($ch);
56
curl_close($ch);
57
 
58
// Decode JWT "id_token"
59
// see https://medium.com/@darutk/understanding-id-token-5f83f50fa02e
60
// Note: We do not need to verify the signature because the token comes directly from Google
61
$data = json_decode($cont,true);
62
if (isset($data['error'])) {
440 daniel-mar 63
        throw new OIDplusException(_L('Error receiving the authentication token from %1: %2','Google',$data['error'].' '.$data['error_description']));
432 daniel-mar 64
}
65
$id_token = $data['id_token'];
66
$access_token = $data['access_token'];
67
list($header,$payload,$signature) = explode('.', $id_token);
438 daniel-mar 68
$data = json_decode(base64_decode($payload),true);
69
$email = $data['email'];
432 daniel-mar 70
 
438 daniel-mar 71
// Check if the email was verified
72
 
73
if ($data['email_verified'] != 'true') {
440 daniel-mar 74
        throw new OIDplusException(_L('The email address %1 was not verified. Please verify it first!',$email));
438 daniel-mar 75
}
76
 
432 daniel-mar 77
// Everything's done! Now login and/or create account
78
 
79
if (!empty($email)) {
80
        $ra = new OIDplusRA($email);
81
        if (!$ra->existing()) {
82
                $ra->register_ra(null); // create a user account without password
83
 
433 daniel-mar 84
                // Query user infos
85
                $ch = curl_init('https://www.googleapis.com/oauth2/v3/userinfo'); // Initialise cURL
496 daniel-mar 86
                if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . '3p/certs/cacert.pem');
433 daniel-mar 87
                $data_string = '';
88
                curl_setopt($ch, CURLOPT_HTTPHEADER, array(
89
                        'Content-Length: ' . strlen($data_string),
90
                        "Authorization: Bearer ".$access_token
91
                ));
92
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
93
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
94
                curl_setopt($ch, CURLOPT_POST, 1);
95
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
96
                $result = curl_exec($ch);
97
                curl_close($ch);
98
                $data = json_decode($result,true);
99
                $personal_name = $data['name']; // = given_name + " " + family_name
100
 
432 daniel-mar 101
                OIDplus::db()->query("update ###ra set ra_name = ?, personal_name = ? where email = ?", array($personal_name, $personal_name, $email));
102
 
103
                OIDplus::logger()->log("[INFO]RA($email)!", "RA '$email' was created because of successful Google OAuth2 login");
104
        }
105
 
106
        OIDplus::logger()->log("[OK]RA($email)!", "RA '$email' logged in via Google OAuth2");
107
        OIDplus::authUtils()::raLogin($email);
108
 
109
        OIDplus::db()->query("UPDATE ###ra set last_login = ".OIDplus::db()->sqlDate()." where email = ?", array($email));
110
 
111
        // Go back to OIDplus
112
 
496 daniel-mar 113
        header('Location:'.OIDplus::webpath(null,false));
432 daniel-mar 114
}
433 daniel-mar 115
 
116
// We now have the data of the person that wanted to log in
117
// So we can log off again
118
$ch = curl_init();
496 daniel-mar 119
if (ini_get('curl.cainfo') == '') curl_setopt($ch, CURLOPT_CAINFO, OIDplus::localpath() . '3p/certs/cacert.pem');
433 daniel-mar 120
curl_setopt($ch, CURLOPT_URL,"https://oauth2.googleapis.com/revoke");
121
curl_setopt($ch, CURLOPT_POST, 1);
122
curl_setopt($ch, CURLOPT_POSTFIELDS,
123
        "client_id=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_ID'))."&".
124
        "client_secret=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_SECRET'))."&".
125
        "token_type_hint=access_token&".
126
        "token=".$access_token
127
);
128
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
129
curl_exec($ch);
130
curl_close($ch);