Single-sign-on and self-serve account management. https://netsyms.biz/apps/accounthub
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

login.php 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. <?php
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /**
  6. * Authentication and account functions. Connects to an AccountHub instance.
  7. */
  8. /**
  9. * Check the login server API for sanity
  10. * @return boolean true if OK, else false
  11. */
  12. function checkLoginServer() {
  13. try {
  14. $client = new GuzzleHttp\Client();
  15. $response = $client
  16. ->request('POST', PORTAL_API, [
  17. 'form_params' => [
  18. 'key' => PORTAL_KEY,
  19. 'action' => "ping"
  20. ]
  21. ]);
  22. if ($response->getStatusCode() != 200) {
  23. return false;
  24. }
  25. $resp = json_decode($response->getBody(), TRUE);
  26. if ($resp['status'] == "OK") {
  27. return true;
  28. } else {
  29. return false;
  30. }
  31. } catch (Exception $e) {
  32. return false;
  33. }
  34. }
  35. /**
  36. * Checks if the given AccountHub API key is valid by attempting to
  37. * access the API with it.
  38. * @param String $key The API key to check
  39. * @return boolean TRUE if the key is valid, FALSE if invalid or something went wrong
  40. */
  41. function checkAPIKey($key) {
  42. try {
  43. $client = new GuzzleHttp\Client();
  44. $response = $client
  45. ->request('POST', PORTAL_API, [
  46. 'form_params' => [
  47. 'key' => $key,
  48. 'action' => "ping"
  49. ]
  50. ]);
  51. if ($response->getStatusCode() === 200) {
  52. return true;
  53. }
  54. return false;
  55. } catch (Exception $e) {
  56. return false;
  57. }
  58. }
  59. ////////////////////////////////////////////////////////////////////////////////
  60. // Account handling //
  61. ////////////////////////////////////////////////////////////////////////////////
  62. /**
  63. * Checks the given credentials against the API.
  64. * @param string $username
  65. * @param string $password
  66. * @return boolean True if OK, else false
  67. */
  68. function authenticate_user($username, $password, &$errmsg) {
  69. $client = new GuzzleHttp\Client();
  70. $response = $client
  71. ->request('POST', PORTAL_API, [
  72. 'form_params' => [
  73. 'key' => PORTAL_KEY,
  74. 'action' => "auth",
  75. 'username' => $username,
  76. 'password' => $password
  77. ]
  78. ]);
  79. if ($response->getStatusCode() > 299) {
  80. sendError("Login server error: " . $response->getBody());
  81. }
  82. $resp = json_decode($response->getBody(), TRUE);
  83. if ($resp['status'] == "OK") {
  84. return true;
  85. } else {
  86. $errmsg = $resp['msg'];
  87. return false;
  88. }
  89. }
  90. /**
  91. * Check if a username exists.
  92. * @param String $username
  93. */
  94. function user_exists($username) {
  95. $client = new GuzzleHttp\Client();
  96. $response = $client
  97. ->request('POST', PORTAL_API, [
  98. 'form_params' => [
  99. 'key' => PORTAL_KEY,
  100. 'action' => "userexists",
  101. 'username' => $username
  102. ]
  103. ]);
  104. if ($response->getStatusCode() > 299) {
  105. sendError("Login server error: " . $response->getBody());
  106. }
  107. $resp = json_decode($response->getBody(), TRUE);
  108. if ($resp['status'] == "OK" && $resp['exists'] === true) {
  109. return true;
  110. } else {
  111. return false;
  112. }
  113. }
  114. /**
  115. * Check if a UID exists.
  116. * @param String $uid
  117. */
  118. function uid_exists($uid) {
  119. $client = new GuzzleHttp\Client();
  120. $response = $client
  121. ->request('POST', PORTAL_API, [
  122. 'form_params' => [
  123. 'key' => PORTAL_KEY,
  124. 'action' => "userexists",
  125. 'uid' => $uid
  126. ]
  127. ]);
  128. if ($response->getStatusCode() > 299) {
  129. sendError("Login server error: " . $response->getBody());
  130. }
  131. $resp = json_decode($response->getBody(), TRUE);
  132. if ($resp['status'] == "OK" && $resp['exists'] === true) {
  133. return true;
  134. } else {
  135. return false;
  136. }
  137. }
  138. /**
  139. * Get the account status: NORMAL, TERMINATED, LOCKED_OR_DISABLED,
  140. * CHANGE_PASSWORD, or ALERT_ON_ACCESS
  141. * @param string $username
  142. * @return string
  143. */
  144. function get_account_status($username) {
  145. $client = new GuzzleHttp\Client();
  146. $response = $client
  147. ->request('POST', PORTAL_API, [
  148. 'form_params' => [
  149. 'key' => PORTAL_KEY,
  150. 'action' => "acctstatus",
  151. 'username' => $username
  152. ]
  153. ]);
  154. if ($response->getStatusCode() > 299) {
  155. sendError("Login server error: " . $response->getBody());
  156. }
  157. $resp = json_decode($response->getBody(), TRUE);
  158. if ($resp['status'] == "OK") {
  159. return $resp['account'];
  160. } else {
  161. return false;
  162. }
  163. }
  164. /**
  165. * Check if the given username has the given permission (or admin access)
  166. * @param string $username
  167. * @param string $permcode
  168. * @return boolean TRUE if the user has the permission (or admin access), else FALSE
  169. */
  170. function account_has_permission($username, $permcode) {
  171. $client = new GuzzleHttp\Client();
  172. $response = $client
  173. ->request('POST', PORTAL_API, [
  174. 'form_params' => [
  175. 'key' => PORTAL_KEY,
  176. 'action' => "permission",
  177. 'username' => $username,
  178. 'code' => $permcode
  179. ]
  180. ]);
  181. if ($response->getStatusCode() > 299) {
  182. sendError("Login server error: " . $response->getBody());
  183. }
  184. $resp = json_decode($response->getBody(), TRUE);
  185. if ($resp['status'] == "OK") {
  186. return $resp['has_permission'];
  187. } else {
  188. return false;
  189. }
  190. }
  191. ////////////////////////////////////////////////////////////////////////////////
  192. // Login handling //
  193. ////////////////////////////////////////////////////////////////////////////////
  194. /**
  195. * Setup $_SESSION values with user data and set loggedin flag to true
  196. * @param string $username
  197. */
  198. function doLoginUser($username) {
  199. $client = new GuzzleHttp\Client();
  200. $response = $client
  201. ->request('POST', PORTAL_API, [
  202. 'form_params' => [
  203. 'key' => PORTAL_KEY,
  204. 'action' => "userinfo",
  205. 'username' => $username
  206. ]
  207. ]);
  208. if ($response->getStatusCode() > 299) {
  209. sendError("Login server error: " . $response->getBody());
  210. }
  211. $resp = json_decode($response->getBody(), TRUE);
  212. if ($resp['status'] == "OK") {
  213. $userinfo = $resp['data'];
  214. $_SESSION['username'] = $username;
  215. $_SESSION['uid'] = $userinfo['uid'];
  216. $_SESSION['email'] = $userinfo['email'];
  217. $_SESSION['realname'] = $userinfo['name'];
  218. $_SESSION['loggedin'] = true;
  219. return true;
  220. } else {
  221. return false;
  222. }
  223. }
  224. function sendLoginAlertEmail($username) {
  225. $client = new GuzzleHttp\Client();
  226. $response = $client
  227. ->request('POST', PORTAL_API, [
  228. 'form_params' => [
  229. 'key' => PORTAL_KEY,
  230. 'action' => "alertemail",
  231. 'username' => $username,
  232. 'appname' => SITE_TITLE
  233. ]
  234. ]);
  235. if ($response->getStatusCode() > 299) {
  236. return "An unknown error occurred.";
  237. }
  238. $resp = json_decode($response->getBody(), TRUE);
  239. if ($resp['status'] == "OK") {
  240. return true;
  241. } else {
  242. return $resp['msg'];
  243. }
  244. }
  245. function simLogin($username, $password) {
  246. $client = new GuzzleHttp\Client();
  247. $response = $client
  248. ->request('POST', PORTAL_API, [
  249. 'form_params' => [
  250. 'key' => PORTAL_KEY,
  251. 'action' => "login",
  252. 'username' => $username,
  253. 'password' => $password
  254. ]
  255. ]);
  256. if ($response->getStatusCode() > 299) {
  257. sendError("Login server error: " . $response->getBody());
  258. }
  259. $resp = json_decode($response->getBody(), TRUE);
  260. if ($resp['status'] == "OK") {
  261. return true;
  262. } else {
  263. return $resp['msg'];
  264. }
  265. }
  266. function verifyReCaptcha($code) {
  267. try {
  268. $client = new GuzzleHttp\Client();
  269. $response = $client
  270. ->request('POST', "https://www.google.com/recaptcha/api/siteverify", [
  271. 'form_params' => [
  272. 'secret' => RECAPTCHA_SECRET_KEY,
  273. 'response' => $code
  274. ]
  275. ]);
  276. if ($response->getStatusCode() != 200) {
  277. return false;
  278. }
  279. $resp = json_decode($response->getBody(), TRUE);
  280. if ($resp['success'] === true) {
  281. return true;
  282. }
  283. return false;
  284. } catch (Exception $e) {
  285. return false;
  286. }
  287. }
  288. ////////////////////////////////////////////////////////////////////////////////
  289. // 2-factor authentication //
  290. ////////////////////////////////////////////////////////////////////////////////
  291. /**
  292. * Check if a user has TOTP setup
  293. * @param string $username
  294. * @return boolean true if TOTP secret exists, else false
  295. */
  296. function userHasTOTP($username) {
  297. $client = new GuzzleHttp\Client();
  298. $response = $client
  299. ->request('POST', PORTAL_API, [
  300. 'form_params' => [
  301. 'key' => PORTAL_KEY,
  302. 'action' => "hastotp",
  303. 'username' => $username
  304. ]
  305. ]);
  306. if ($response->getStatusCode() > 299) {
  307. sendError("Login server error: " . $response->getBody());
  308. }
  309. $resp = json_decode($response->getBody(), TRUE);
  310. if ($resp['status'] == "OK") {
  311. return $resp['otp'];
  312. } else {
  313. return false;
  314. }
  315. }
  316. /**
  317. * Verify a TOTP multiauth code
  318. * @global $database
  319. * @param string $username
  320. * @param int $code
  321. * @return boolean true if it's legit, else false
  322. */
  323. function verifyTOTP($username, $code) {
  324. $client = new GuzzleHttp\Client();
  325. $response = $client
  326. ->request('POST', PORTAL_API, [
  327. 'form_params' => [
  328. 'key' => PORTAL_KEY,
  329. 'action' => "verifytotp",
  330. 'username' => $username,
  331. 'code' => $code
  332. ]
  333. ]);
  334. if ($response->getStatusCode() > 299) {
  335. sendError("Login server error: " . $response->getBody());
  336. }
  337. $resp = json_decode($response->getBody(), TRUE);
  338. if ($resp['status'] == "OK") {
  339. return $resp['valid'];
  340. } else {
  341. return false;
  342. }
  343. }