3 * Single signon for phpMyAdmin using OpenID
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.
9 * It uses OpenID pear package, see https://pear.php.net/package/OpenID
11 * User first authenticates using OpenID and based on content of $AUTH_MAP
12 * the login information is passed to phpMyAdmin in session data.
15 declare(strict_types
=1);
17 if (false === @include_once
'OpenID/RelyingParty.php') {
21 /* Change this to true if using phpMyAdmin over https */
22 $secure_cookie = false;
25 * Map of authenticated users to MySQL user/password pairs.
28 'https://launchpad.net/~username' => [
34 // phpcs:disable PSR1.Files.SideEffects,Squiz.Functions.GlobalFunction
37 * Simple function to show HTML page with given content.
39 * @param string $contents Content to include in page
41 function Show_page($contents): void
43 header('Content-Type: text/html; charset=utf-8');
45 echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
47 <html lang="en" dir="ltr">
49 <link rel="icon" href="../favicon.ico" type="image/x-icon">
50 <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
51 <meta charset="utf-8">
52 <title>phpMyAdmin OpenID signon example</title>
56 if (isset($_SESSION['PMA_single_signon_error_message'])) {
57 echo '<p class="error">' . $_SESSION['PMA_single_signon_message'] . '</p>';
58 unset($_SESSION['PMA_single_signon_message']);
62 echo '</body></html>';
66 * Display error and exit
68 * @param Exception $e Exception object
70 function Die_error($e): void
72 $contents = "<div class='relyingparty_results'>\n";
73 $contents .= '<pre>' . htmlspecialchars($e->getMessage()) . "</pre>\n";
74 $contents .= "</div class='relyingparty_results'>";
81 /* Need to have cookie visible from parent directory */
82 session_set_cookie_params(0, '/', '', $secure_cookie, true);
83 /* Create signon session */
84 $session_name = 'SignonSession';
85 session_name($session_name);
88 // Determine realm and return_to
90 if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') {
94 $base .= '://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'];
97 $returnTo = $base . dirname($_SERVER['PHP_SELF']);
98 if ($returnTo[strlen($returnTo) - 1] !== '/') {
102 $returnTo .= 'openid.php';
105 if ((! count($_GET) && ! count($_POST)) ||
isset($_GET['phpMyAdmin'])) {
106 /* Show simple form */
107 $content = '<form action="openid.php" method="post">
108 OpenID: <input type="text" name="identifier"><br>
109 <input type="submit" name="start">
115 /* Grab identifier */
117 if (isset($_POST['identifier']) && is_string($_POST['identifier'])) {
118 $identifier = $_POST['identifier'];
119 } elseif (isset($_SESSION['identifier']) && is_string($_SESSION['identifier'])) {
120 $identifier = $_SESSION['identifier'];
123 /* Create OpenID object */
125 $o = new OpenID_RelyingParty($returnTo, $realm, $identifier);
126 } catch (Throwable
$e) {
130 /* Redirect to OpenID provider */
131 if (isset($_POST['start'])) {
133 $authRequest = $o->prepare();
134 } catch (Throwable
$e) {
138 $url = $authRequest->getAuthorizeURL();
140 header('Location: ' . $url);
144 /* Grab query string */
145 if (! count($_POST)) {
146 [, $queryString] = explode('?', $_SERVER['REQUEST_URI']);
148 // Fetch the raw query body
149 $queryString = file_get_contents('php://input');
154 $message = new OpenID_Message($queryString, OpenID_Message
::FORMAT_HTTP
);
155 } catch (Throwable
$e) {
159 $id = $message->get('openid.claimed_id');
161 if (empty($id) ||
! isset($AUTH_MAP[$id])) {
162 Show_page('<p>User not allowed!</p>');
166 $_SESSION['PMA_single_signon_user'] = $AUTH_MAP[$id]['user'];
167 $_SESSION['PMA_single_signon_password'] = $AUTH_MAP[$id]['password'];
168 $_SESSION['PMA_single_signon_HMAC_secret'] = hash('sha1', uniqid(strval(random_int(0, mt_getrandmax())), true));
169 session_write_close();
170 /* Redirect to phpMyAdmin (should use absolute URL here!) */
171 header('Location: ../index.php');