/
authenticate.php
109 lines (97 loc) · 4.06 KB
/
authenticate.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
declare(strict_types=1);
set_time_limit(120);
@session_start(['read_and_close' => true]);
require_once 'html_headers.php';
require_once 'setup.php';
// To use the oauthclient library, run: composer require mediawiki/oauthclient
use MediaWiki\OAuthClient\Client;
use MediaWiki\OAuthClient\ClientConfig;
use MediaWiki\OAuthClient\Consumer;
use MediaWiki\OAuthClient\Token;
// The two ways we leave this script
function death_time(string $err): never {
@session_start(); // Need write access
unset($_SESSION['access_key'], $_SESSION['access_secret'], $_SESSION['citation_bot_user_id'], $_SESSION['request_key'], $_SESSION['request_secret']);
@session_write_close(); // Paranoid
echo '<!DOCTYPE html><html lang="en" dir="ltr"><head><title>Authentifcation System Failure</title></head><body><main>' . $err . '</main></body></html>';
exit(0);
}
function return_to_sender(string $where = 'https://citations.toolforge.org/'): never {
@session_write_close(); // Paranoid
$where = preg_replace('~\s+~', '', $where); // Security paranoia
header("Location: " . $where);
exit(0);
}
if (!getenv('PHP_WP_OAUTH_CONSUMER') || !getenv('PHP_WP_OAUTH_SECRET')) {
death_time("Citation Bot's authorization tokens not configured");
}
try {
$conf = new ClientConfig('https://meta.wikimedia.org/w/index.php?title=Special:OAuth');
}
catch (Throwable $e) {
death_time("Citation Bot Could not contact meta.wikimedia.org");
}
try {
$conf->setConsumer(new Consumer((string) getenv('PHP_WP_OAUTH_CONSUMER'), (string) getenv('PHP_WP_OAUTH_SECRET')));
$conf->setUserAgent(BOT_USER_AGENT);
$client = new Client($conf);
unset($conf);
}
catch (Throwable $e) {
death_time("Citation Bot's internal authorization tokens did not work");
}
// Existing Access Grant - verify that it works since we are here anyway
if (isset($_SESSION['access_key']) && isset($_SESSION['access_secret'])) {
try {
$client->makeOAuthCall(
new Token($_SESSION['access_key'], $_SESSION['access_secret']),
'https://meta.wikimedia.org/w/api.php?action=query&meta=tokens&format=json');
return_to_sender();
}
catch (Throwable $e) { ; }
}
// clear anything left over that did not work
@session_start(); // Need write access
unset($_SESSION['access_key'], $_SESSION['access_secret']);
// New Incoming Access Grant
if (is_string(@$_GET['oauth_verifier']) && is_string(@$_SESSION['request_key']) && is_string(@$_SESSION['request_secret']) ) {
try {
$accessToken = $client->complete(new Token($_SESSION['request_key'], $_SESSION['request_secret']), $_GET['oauth_verifier']);
if (empty($accessToken->key) || empty($accessToken->secret)) {
throw new Exception('OAuth complete() call failed');
}
$_SESSION['access_key'] = $accessToken->key;
$_SESSION['access_secret'] = $accessToken->secret;
unset($_SESSION['request_key'], $_SESSION['request_secret']);
if (is_string(@$_GET['return'])) {
// This could only be tainted input if OAuth server itself was hacked, so flag as safe
/** @psalm-taint-escape header */
$where = trim($_GET['return']);
return_to_sender($where);
}
return_to_sender();
}
catch (Throwable $e) { ; }
death_time("Incoming authorization tokens did not work - try again please");
}
unset($_SESSION['request_key'], $_SESSION['request_secret']);
// Nothing found. Needs an access grant from scratch
try {
if (!isset($_SERVER['HTTP_HOST']) || !isset($_SERVER['REQUEST_URI'])) {
throw new Exception('Webserver URL variables not set');
}
$proto = (
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
) ? "https://" : "http://";
$newcallback = $proto . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$client->setCallback($newcallback);
list( $authUrl, $token ) = $client->initiate();
$_SESSION['request_key'] = $token->key;
$_SESSION['request_secret'] = $token->secret;
return_to_sender($authUrl);
}
catch (Throwable $e) { ; }
death_time("Unable to initiate OAuth.");
?>