/** * Fetch the provider key from verifyne server. * Verifies the key if libsodium is available. * After successful return the key can be read from the global class variables PROVIDER_KEY and PROVIDER_KEY_HEX. * * @return Returns TRUE if successful, or a WP_Error instance otherwise. */ static function get_provider_key() { if (NULL !== self::$PROVIDER_KEY) { return TRUE; } if (!extension_loaded('libsodium')) { return new WP_Error("verifyne", "libsodium not available"); } # Decode CA key self::$VERIFYNE_CA_KEY = base64_decode("i7dbWvlFdHwviUXav7N1Lwoi+DOJDG9SuFHNwP/AUjU=", true); if (FALSE === self::$VERIFYNE_CA_KEY) { return new WP_Error("verifyne", "Wrong CA key"); } # Invoke API $cont = @file_get_contents("https://api.verifyne.me/v1/provider-key"); if (FALSE === $cont) { return new WP_Error("verifyne", "Failed to query verifyne API"); } # Read JSON $resp = @json_decode($cont); if (NULL === $resp) { return new WP_Error("verifyne", "Invalid JSON received"); } # Decode signature $sig = base64_decode($resp->content->psig, $strict = true); if (FALSE === $sig) { return new WP_Error("verifyne", "Decoding signature failed"); } $pkey_b64 = $resp->content->pkey; # Verify signature if (TRUE !== @\Sodium\crypto_sign_verify_detached($sig, $pkey_b64, self::$VERIFYNE_CA_KEY)) { return new WP_Error("verifyne", "Failed to verify provider key"); } # Decode key (dec == 'ed25519:xxxxxxx...') $dec = base64_decode($pkey_b64, $strict = true); if (FALSE === $dec) { return new WP_Error("verifyne", "Decoding provider key description failed"); } # Decode raw provider key self::$PROVIDER_KEY = base64_decode(explode(":", $dec, 2)[1], $strict = true); if (FALSE === self::$PROVIDER_KEY) { return new WP_Error("verifyne", "Decoding provider key"); } self::$PROVIDER_KEY_HEX = @\Sodium\bin2hex(self::$PROVIDER_KEY); self::$VERIFYNE_CA_KEY_HEX = @\Sodium\bin2hex(self::$VERIFYNE_CA_KEY); return TRUE; }
/** * Generate verifyne settings page content */ function print_settings_page_content() { if (!current_user_can(self::REQUIRED_CAPABILITY)) { wp_die(__('You do not have sufficient permissions to access this page.')); } # Encapsulate everything within this wrapper tag echo '<div class="wrap">'; # Settings echo '<h2>Verifyne Settings</h2>'; echo '<form method="post" action="options.php">'; settings_fields('vf_option_group'); do_settings_sections('vf-basic-settings'); submit_button(); echo '</form>'; # Info table Wordpress_Verifyne_API::get_provider_key(); echo "<h3>Information</h3>"; echo "\r\n <table name='vf_info' class='form-table'>\r\n <tr valign='top'>\r\n <th scope='row'>Plugin version number</th>\r\n <td>" . Wordpress_Verifyne_Plugin::PLUGIN_VERSION_NUMBER . "</td>\r\n </tr>\r\n <tr valign='top'>\r\n <th scope='row'>Sodium library available</th>\r\n <td>" . (extension_loaded('libsodium') ? "YES" : "no") . "</td>\r\n </tr>\r\n <tr valign='top'>\r\n <th scope='row'>Verifyne CA Key</th>\r\n <td>" . (NULL === Wordpress_Verifyne_API::$VERIFYNE_CA_KEY_HEX ? "n/a" : Wordpress_Verifyne_API::$VERIFYNE_CA_KEY_HEX) . "</td>\r\n </tr>\r\n <tr valign='top'>\r\n <th scope='row'>Verifyne Provider Key</th>\r\n <td>" . (NULL === Wordpress_Verifyne_API::$PROVIDER_KEY_HEX ? "n/a" : Wordpress_Verifyne_API::$PROVIDER_KEY_HEX) . "</td>\r\n </tr>\r\n </table>"; echo '</div>'; // wrapper tag }
/** * Verify the user authentication */ function handle_verify_request() { # Get session ID if (!isset($_COOKIE["vf_session_id"])) { return new WP_Error("verifyne", "No active session. Please try again."); } # Get ticket ID if (!isset($_REQUEST["ticketid"])) { return new WP_Error("verifyne", "No ticket ID set."); } # Read and check session data $vf_data = get_transient($_REQUEST["ticketid"]); if ($vf_data === false) { return new WP_Error("verifyne", "Session expired."); } if ($vf_data["session"] !== $_COOKIE["vf_session_id"]) { return new WP_Error("verifyne", "Invalid session identifier."); } $ticket_data = $vf_data["ticket"]; if (!isset($ticket_data["ticketid"]) || !isset($ticket_data["purpose"]) || !isset($ticket_data["nonce"])) { return new WP_Error("verifyne", "Wrong session state"); } # Verify authentication $ret = Wordpress_Verifyne_API::verify_authentication($ticket_data["ticketid"], $ticket_data["purpose"], $ticket_data["nonce"]); if (is_wp_error($ret)) { return $ret; } $verifyne_user_id = $ret["userid"]; print "<div id='verifyne-state-div'>Authenticated:<br>" . $verifyne_user_id . "</div>"; $this->set_linked_verifyne_id($verifyne_user_id); print "<script>location.replace(window.location.origin + window.location.pathname + '#verifyne')</script>"; }
/** * User has scanned the ticket. Verify the signature and extract the user_id from the ticket. * * @return Returns an instance of WP_Error on failure, otherwise reloads page with parameter action set to "vf_login" */ function handle_verify_request() { # Get session ID if (!isset($_COOKIE["vf_session_id"])) { return new WP_Error("verifyne", "No session ID set."); } # Get ticket ID if (!isset($_REQUEST["ticketid"])) { return new WP_Error("verifyne", "No ticket ID set."); } # Read and check session data $vf_data = get_transient($_REQUEST["ticketid"]); if ($vf_data === false) { return new WP_Error("verifyne", "Session expired."); } if ($vf_data["session"] !== $_COOKIE["vf_session_id"]) { return new WP_Error("verifyne", "Invalid session identifier."); } $ticket_data = $vf_data["ticket"]; if (!isset($ticket_data["ticketid"]) || !isset($ticket_data["purpose"]) || !isset($ticket_data["nonce"])) { return new WP_Error("verifyne", "Wrong session state"); } # Verify authentication $ret = Wordpress_Verifyne_API::verify_authentication($ticket_data["ticketid"], $ticket_data["purpose"], $ticket_data["nonce"]); if (is_wp_error($ret)) { return $ret; } $verifyne_user_id = $ret["userid"]; $ret = get_users(array("meta_key" => "verifyne_user_id", "meta_value" => $verifyne_user_id)); if (!is_array($ret) || sizeof($ret) < 1 || !is_a($ret[0], "WP_User")) { return new WP_Error("verifyne", "This identity is not registered."); } if (sizeof($ret) > 1) { return new WP_Error("verifyne", "This identity is registered for multiple accounts."); } # # At this point the user is authenticated. # # This is the user $wpuser = $ret[0]; $this->log_user_in($wpuser->ID); }