htaccess rule giving 403 error for homepage

Viewed 48

I need the following URLs to be allowed

  • https://www.example.com
  • https://www.example.com/index.php
  • https://www.example.com/login
  • https://www.example.com/logout
  • https://www.example.com/callback

The rule that I have added in .htaccess is:

Order deny,allow
Deny from all
<FilesMatch "login|logout|callback|index\.php">
  Allow from all
</FilesMatch>
### End


DirectoryIndex index.php

# enable apache rewrite engine
RewriteEngine on

# set your rewrite base
# Edit this in your init method too if you script lives in a subfolder
#RewriteBase /

# Deliver the folder or file directly if it exists on the server
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
 
# Push every request to index.php
RewriteRule ^(.*)$ index.php [QSA]

Then I am using Steampixel\Route package to process the request:

Route::add('/', function() {
    //code to process homepage request
});

Route::add('/login', function() {
    //code to process login request
});

Route::add('/logout', function() {
    //code to process logout request
});

Route::add('/callback', function() {
    //code to process callback request
});


Route::run('/');

URLs /login, /logout, /callback work, however, I get 403 "You don't have permission to access this resource." error when I access my homepage, either with or without / (forward slash )

1 Answers
<FilesMatch "login|logout|callback|index\.php">

You need to allow nothing (a request for the root). However, your existing regex is also far too broad as it matches the request if these strings are contained anywhere in the first path-segment. For instance, it will also permit /foologinbar and /login/bar etc.

It would need to be like this to allow nothing and be more restrictive.

<FilesMatch "^(login|logout|callback|index\.php)?$">

You are also using the deprecated Order, Deny and Allow directives. If you are on Apache 2.4 (as I expect you are) then you should be using the equivalent Require directives instead. (But you must avoid mixing old and new directives as you can get unexpected conflicts.) So, this should be written (on Apache 2.4) like this:

Require all denied
<FilesMatch "^(login|logout|callback|index\.php)?$">
  Require all granted
</FilesMatch>

However, strictly speaking the <FilesMatch> (and <Files>) containers are for matching against physical files, not URL-paths. Consider using mod_rewrite instead to specifically match the URL-path. For example, the following should go immediately after the RewriteEngine directive:

# Block all other requests
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule !^(login|logout|callback|index\.php)?$ - [F]

Aside:

when I access my homepage, either with or without / (forward slash)

The trailing slash after the hostname is (effectively) always present on the HTTP request, regardless of whether you explicitly include this in the browser's address bar or not. What you see in the browser's address bar often masks the true request.

Related