@wasinger opened this issue on October 15th 2014

Hi folks,

in a Piwik installation I restricted access to the piwik user interface using the following .htaccess rules as recommended in the FAQ:

<Files "*">
    Order deny, allow
    Deny from all
    Allow from .mydomain.com

<Files ~ "^piwik\.(js|php)$">
    Allow from all

But now the CustomOptOut module is not accessible any more, too. It's not possible to add this module to the regex that allows the "public" URLs piwik.js and piwik.php because it's called as "index.php?module=CustomOptOut", i.e. the path is index.php and the module is only specified in the query string, but in the Files/FilesMatch (or Location/LocationMatch) directive of the apache config you can only access the file path, not the query string.*

So IMHO the best solution for this problem would be to have another entry point for calling "public" modules like CustomOptOut. If there would be another PHP script besides index.php that is called, let's say, "public.php" that would allow to call only "public" modules, one could easily exclude it from the access restriction along with piwik.js and piwik.php the following way:

<Files ~ "^piwik\.(js|php)|public\.php$">
    Allow from all

So piwik.js, piwik.php and public.php would be public URLs accessible to anyone, while index.php would serve the private user interface only and could be protected.

* There is a solution to make this work by using mod_rewrite, but this solution is not possible in .htaccess files but only when you have access to the main apache configuration files.

@mattab commented on October 17th 2014

Maybe we could whitelist the URL index.php?module=CustomOptOut so this page will load? I guess it's a documentation mistake.

@wasinger commented on April 16th 2015

I don't think it's a documentation mistake, because in Apache config / .htaccess files it's not possible to simply whitelist the URL depending on the query string, i.e. in or blocks only the file path of the URL is checked but not the query string.

The solution for an apache config using mod_rewrite setting an environment variable would look like this:

RewriteCond %{QUERY_STRING} \bmodule=CustomOptOut\b
RewriteRule .* - [E=CustomOptOut]

<Location /piwik/>
    Allow from env=CustomOptOut

but this solution is not possible in .htaccess files.

@wasinger commented on April 16th 2015

So I am using the solution with an additional php script as entry point for public modules as proposed above. It has been working for me for six month now.

To use this approach, just place a file called "public.php" into the piwik folder with the following code:

# Modules that should be publicly accessible
$allowed_modules = array('CustomOptOut');

$requested_module = $_GET['module'];

if (in_array($requested_module, $allowed_modules)) {
    include __DIR__ . '/index.php';
} else {
    if (strpos(PHP_SAPI, 'fcgi') !== false) {
        header("Status: 403 Forbidden");
    } else {
        header("HTTP/1.0 403 Forbidden");
    die('Error 403: Access not allowed');

Then, in your HTML page containing the iframe for CustomOptOut, change the URL from "index.php?module=CustomOptOut" to "public.php?module=CustomOptOut"

@marcopenhacking commented on November 19th 2015

@wasinger your public.php solution/workaround works for me :smile:

The new file need to be added to the .htaccess as well:

<Files ~ "^piwik\.(js|php)|^public\.php">
   Allow from all
    Satisfy any
@kbabioch commented on May 2nd 2017

Why isn't this fixed properly by providing a separate entry point for opt-out? Routing opt-out as well as all of the admin interface over index.php is insanity. A lot of people fix this by creating a public.php (just as explained above), but this is not guaranteed to work ... This should definitely be something that Piwik should support out of the box.

@mattab commented on June 21st 2017

see https://github.com/piwik/piwik/issues/11039#issuecomment-281108416 and comments below for a solution

This issue was closed on June 21st 2017
Powered by GitHub Issue Mirror