-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathverify_common.php
146 lines (126 loc) · 5.05 KB
/
verify_common.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?php
if (!defined('INSTANCE')) {
die("Developer error: INSTANCE is not set! If you see this, report to gabrielr#9134. Or maybe you directly tried to directly call a file that shouldn't be.");
}
/// Redirect discord2025.scripts.mit.edu to discord2025.mit.edu:444
if (strpos($_SERVER['SERVER_NAME'], 'scripts') !== false) {
header("Location: https://discord2025.mit.edu:444$_SERVER[REQUEST_URI]");
die();
}
/// Debug
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
/// Move GET parameters to a cookie.
/// This is because OAuth says the URL to redirect to "MUST exactly match one
/// of the Redirection URI values for the Client pre-registered at the OpenID Provider"
/// Since it's impossible to register every possible combination, saving them into a
/// cookie is the only solution I can think of to keep the parameters after authentication
/// TODO: A search on stackoverflow says that's what the state parameter is for. Implement that
/// https://stackoverflow.com/questions/55524480/should-dynamic-query-parameters-be-present-in-the-redirection-uri-for-an-oauth2
if (!isset($_SERVER['SSL_CLIENT_S_DN_Email']) && (isset($_GET['id']) || isset($_GET['auth']))) {
/// If authenticating using oidc, don't use 444 port so it matches the oauth redirect URL
if ($_SERVER['SERVER_PORT'] == 444) {
header("Location: https://discord2025.mit.edu$_SERVER[REQUEST_URI]");
die();
}
/// I'm checking for cert here so using cert authentication doesn't require having cookies enabled
if (isset($_GET['id'])) {
setcookie('id', $_GET['id']);
}
if (isset($_GET['auth'])) {
setcookie('auth', $_GET['auth']);
}
if (isset($_GET['server'])) {
setcookie('server', $_GET['server']);
}
header("Location: https://discord2025.mit.edu/".INSTANCE.".php");
die();
}
/// Code to make HTTP requests, used for OpenID/OAuth
/// Reference: https://www.php.net/manual/en/context.http.php
function make_http_request($method, $url, $args, $headers) {
$postdata = http_build_query($args);
$opts = array('http' => array(
'method' => $method,
'header' => $headers,
'content' => $postdata
));
$context = stream_context_create($opts);
return file_get_contents($url, false, $context);
}
/// Constants
require "constants.php";
/// SQL stuff
$connection = mysqli_connect(SQL_HOST, SQL_USERNAME, SQL_PASSWORD, SQL_DB);
/// Discord stuff
require_once "support/sdk_discord.php";
$discord = new DiscordSDK();
$discord->SetAccessInfo("Bot", TOKEN);
/// Get user email
if (isset($_SERVER['SSL_CLIENT_S_DN_Email'])) {
/// Pure cert authentication (preferred)
$email = $_SERVER['SSL_CLIENT_S_DN_Email'];
} else if (isset($_GET['code'])) {
/// OAuth authentication
$tokenstuff = make_http_request('POST', 'https://petrock.mit.edu/token', array(
'grant_type' => 'authorization_code',
'code' => $_GET['code'],
'redirect_uri' => 'https://discord2025.mit.edu/'.INSTANCE.'.php',
), [
'Content-type: application/x-www-form-urlencoded',
'Authorization: Basic '.base64_encode(OAUTH_ID.':'.OAUTH_SECRET),
]);
if (!$tokenstuff) {
/// If unable to get a token, try again
header("Location: https://discord2025.mit.edu/".INSTANCE.".php");
die();
}
$tokenstuff = json_decode($tokenstuff, true);
$token = $tokenstuff['access_token'];
// https://openid.net/specs/openid-connect-basic-1_0.html#UserInfoRequest
$userinfo = make_http_request('POST', 'https://petrock.mit.edu/userinfo', array(
'access_token' => $token
), 'Content-type: application/x-www-form-urlencoded');
$userinfo = json_decode($userinfo, true);
$email = $userinfo['email'];
} else {
/// If cert doesn't work, fallback to OAuth
header("Location: https://discord2025.mit.edu/redirect.php?instance=".INSTANCE);
die();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Discord verification</title>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans&display=swap" rel="stylesheet">
<!-- Credit to jt for the styling -->
<link rel="stylesheet" href="verify.css">
</head>
<body>
<div id="main">
<?php
/// Extract kerb from email
$email = strtolower($email);
if (substr($email, -8) != "@mit.edu") {
die("Given email is $email, which is not an MIT email! If you need help, contact Discord staff.");
}
$kerb = substr($email, 0, -8);
/// Authenticate Discord member (make sure they came from clicking the link, and therefore own the account)
if (!isset($_REQUEST['id'])) {
die('Internal error: You didn\'t specify a Discord account to verify!');
}
$member = intval($_REQUEST['id']);
$toHash = PEPPER.":$member";
$hash = hash('sha256', $toHash);
if (!isset($_REQUEST['auth'])) {
die('Internal error: No auth!');
}
$expectedHash = $_REQUEST['auth'];
if ($hash !== $expectedHash) {
die('Internal error: Could not verify that you own the Discord account you\'re trying to verify!');
}
?>