Subversion Repositories oidplus

Rev

Rev 438 | 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
5
 * Copyright 2020 Daniel Marschall, ViaThinkSoft
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
 
39
$ch = curl_init();
40
curl_setopt($ch, CURLOPT_URL,"https://oauth2.googleapis.com/token");
41
curl_setopt($ch, CURLOPT_POST, 1);
42
curl_setopt($ch, CURLOPT_POSTFIELDS,
43
        "grant_type=authorization_code&".
44
        "code=".$_GET['code']."&".
45
        "redirect_uri=".urlencode(OIDplus::getSystemUrl(false).OIDplus::webpath(__DIR__).'oauth.php')."&".
46
        "client_id=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_ID'))."&".
47
        "client_secret=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_SECRET'))
48
);
49
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
50
$cont = curl_exec($ch);
51
curl_close($ch);
52
 
53
// Decode JWT "id_token"
54
// see https://medium.com/@darutk/understanding-id-token-5f83f50fa02e
55
// Note: We do not need to verify the signature because the token comes directly from Google
56
$data = json_decode($cont,true);
57
if (isset($data['error'])) {
440 daniel-mar 58
        throw new OIDplusException(_L('Error receiving the authentication token from %1: %2','Google',$data['error'].' '.$data['error_description']));
432 daniel-mar 59
}
60
$id_token = $data['id_token'];
61
$access_token = $data['access_token'];
62
list($header,$payload,$signature) = explode('.', $id_token);
438 daniel-mar 63
$data = json_decode(base64_decode($payload),true);
64
$email = $data['email'];
432 daniel-mar 65
 
438 daniel-mar 66
// Check if the email was verified
67
 
68
if ($data['email_verified'] != 'true') {
440 daniel-mar 69
        throw new OIDplusException(_L('The email address %1 was not verified. Please verify it first!',$email));
438 daniel-mar 70
}
71
 
432 daniel-mar 72
// Everything's done! Now login and/or create account
73
 
74
if (!empty($email)) {
75
        $ra = new OIDplusRA($email);
76
        if (!$ra->existing()) {
77
                $ra->register_ra(null); // create a user account without password
78
 
433 daniel-mar 79
                // Query user infos
80
                $ch = curl_init('https://www.googleapis.com/oauth2/v3/userinfo'); // Initialise cURL
81
                $data_string = '';
82
                curl_setopt($ch, CURLOPT_HTTPHEADER, array(
83
                        'Content-Length: ' . strlen($data_string),
84
                        "Authorization: Bearer ".$access_token
85
                ));
86
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
87
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
88
                curl_setopt($ch, CURLOPT_POST, 1);
89
                curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
90
                $result = curl_exec($ch);
91
                curl_close($ch);
92
                $data = json_decode($result,true);
93
                $personal_name = $data['name']; // = given_name + " " + family_name
94
 
432 daniel-mar 95
                OIDplus::db()->query("update ###ra set ra_name = ?, personal_name = ? where email = ?", array($personal_name, $personal_name, $email));
96
 
97
                OIDplus::logger()->log("[INFO]RA($email)!", "RA '$email' was created because of successful Google OAuth2 login");
98
        }
99
 
100
        OIDplus::logger()->log("[OK]RA($email)!", "RA '$email' logged in via Google OAuth2");
101
        OIDplus::authUtils()::raLogin($email);
102
 
103
        OIDplus::db()->query("UPDATE ###ra set last_login = ".OIDplus::db()->sqlDate()." where email = ?", array($email));
104
 
105
        // Go back to OIDplus
106
 
107
        header('Location:'.OIDplus::getSystemUrl(false));
108
}
433 daniel-mar 109
 
110
// We now have the data of the person that wanted to log in
111
// So we can log off again
112
$ch = curl_init();
113
curl_setopt($ch, CURLOPT_URL,"https://oauth2.googleapis.com/revoke");
114
curl_setopt($ch, CURLOPT_POST, 1);
115
curl_setopt($ch, CURLOPT_POSTFIELDS,
116
        "client_id=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_ID'))."&".
117
        "client_secret=".urlencode(OIDplus::baseConfig()->getValue('GOOGLE_OAUTH2_CLIENT_SECRET'))."&".
118
        "token_type_hint=access_token&".
119
        "token=".$access_token
120
);
121
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
122
curl_exec($ch);
123
curl_close($ch);