openid.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. /**
  3. * Single signon for phpMyAdmin using OpenID
  4. *
  5. * This is just example how to use single signon with phpMyAdmin, it is
  6. * not intended to be perfect code and look, only shows how you can
  7. * integrate this functionality in your application.
  8. *
  9. * It uses OpenID pear package, see https://pear.php.net/package/OpenID
  10. *
  11. * User first authenticates using OpenID and based on content of $AUTH_MAP
  12. * the login information is passed to phpMyAdmin in session data.
  13. */
  14. declare(strict_types=1);
  15. if (false === @include_once 'OpenID/RelyingParty.php') {
  16. exit;
  17. }
  18. /* Change this to true if using phpMyAdmin over https */
  19. $secure_cookie = false;
  20. /**
  21. * Map of authenticated users to MySQL user/password pairs.
  22. */
  23. $AUTH_MAP = [
  24. 'https://launchpad.net/~username' => [
  25. 'user' => 'root',
  26. 'password' => '',
  27. ],
  28. ];
  29. // phpcs:disable PSR1.Files.SideEffects,Squiz.Functions.GlobalFunction
  30. /**
  31. * Simple function to show HTML page with given content.
  32. *
  33. * @param string $contents Content to include in page
  34. *
  35. * @return void
  36. */
  37. function Show_page($contents)
  38. {
  39. header('Content-Type: text/html; charset=utf-8');
  40. echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
  41. echo '<!DOCTYPE HTML>
  42. <html lang="en" dir="ltr">
  43. <head>
  44. <link rel="icon" href="../favicon.ico" type="image/x-icon">
  45. <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
  46. <meta charset="utf-8">
  47. <title>phpMyAdmin OpenID signon example</title>
  48. </head>
  49. <body>';
  50. if (isset($_SESSION['PMA_single_signon_error_message'])) {
  51. echo '<p class="error">' . $_SESSION['PMA_single_signon_message'] . '</p>';
  52. unset($_SESSION['PMA_single_signon_message']);
  53. }
  54. echo $contents;
  55. echo '</body></html>';
  56. }
  57. /**
  58. * Display error and exit
  59. *
  60. * @param Exception $e Exception object
  61. *
  62. * @return void
  63. */
  64. function Die_error($e)
  65. {
  66. $contents = "<div class='relyingparty_results'>\n";
  67. $contents .= '<pre>' . htmlspecialchars($e->getMessage()) . "</pre>\n";
  68. $contents .= "</div class='relyingparty_results'>";
  69. Show_page($contents);
  70. exit;
  71. }
  72. // phpcs:enable
  73. /* Need to have cookie visible from parent directory */
  74. session_set_cookie_params(0, '/', '', $secure_cookie, true);
  75. /* Create signon session */
  76. $session_name = 'SignonSession';
  77. session_name($session_name);
  78. @session_start();
  79. // Determine realm and return_to
  80. $base = 'http';
  81. if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
  82. $base .= 's';
  83. }
  84. $base .= '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'];
  85. $realm = $base . '/';
  86. $returnTo = $base . dirname($_SERVER['PHP_SELF']);
  87. if ($returnTo[strlen($returnTo) - 1] !== '/') {
  88. $returnTo .= '/';
  89. }
  90. $returnTo .= 'openid.php';
  91. /* Display form */
  92. if ((! count($_GET) && ! count($_POST)) || isset($_GET['phpMyAdmin'])) {
  93. /* Show simple form */
  94. $content = '<form action="openid.php" method="post">
  95. OpenID: <input type="text" name="identifier"><br>
  96. <input type="submit" name="start">
  97. </form>';
  98. Show_page($content);
  99. exit;
  100. }
  101. /* Grab identifier */
  102. if (isset($_POST['identifier']) && is_string($_POST['identifier'])) {
  103. $identifier = $_POST['identifier'];
  104. } elseif (isset($_SESSION['identifier']) && is_string($_SESSION['identifier'])) {
  105. $identifier = $_SESSION['identifier'];
  106. } else {
  107. $identifier = null;
  108. }
  109. /* Create OpenID object */
  110. try {
  111. $o = new OpenID_RelyingParty($returnTo, $realm, $identifier);
  112. } catch (Throwable $e) {
  113. Die_error($e);
  114. }
  115. /* Redirect to OpenID provider */
  116. if (isset($_POST['start'])) {
  117. try {
  118. $authRequest = $o->prepare();
  119. } catch (Throwable $e) {
  120. Die_error($e);
  121. }
  122. $url = $authRequest->getAuthorizeURL();
  123. header('Location: ' . $url);
  124. exit;
  125. }
  126. /* Grab query string */
  127. if (! count($_POST)) {
  128. [, $queryString] = explode('?', $_SERVER['REQUEST_URI']);
  129. } else {
  130. // I hate php sometimes
  131. $queryString = file_get_contents('php://input');
  132. }
  133. /* Check reply */
  134. try {
  135. $message = new OpenID_Message($queryString, OpenID_Message::FORMAT_HTTP);
  136. } catch (Throwable $e) {
  137. Die_error($e);
  138. }
  139. $id = $message->get('openid.claimed_id');
  140. if (empty($id) || ! isset($AUTH_MAP[$id])) {
  141. Show_page('<p>User not allowed!</p>');
  142. exit;
  143. }
  144. $_SESSION['PMA_single_signon_user'] = $AUTH_MAP[$id]['user'];
  145. $_SESSION['PMA_single_signon_password'] = $AUTH_MAP[$id]['password'];
  146. $_SESSION['PMA_single_signon_HMAC_secret'] = hash('sha1', uniqid(strval(rand()), true));
  147. session_write_close();
  148. /* Redirect to phpMyAdmin (should use absolute URL here!) */
  149. header('Location: ../index.php');