I'm using Apache to implement Shibboleth single sign on for a Laravel site. I'd like to bypass one specific subset of URLs from authentication (api/public
, for example) so they're publicly accessible. For some reason the public folder's .htaccess
file seems to be preventing this from working as expected.
I've tried this a bunch of different ways and all roads have lead to this same issue. Here's what I'm trying currently.
<Directory /var/www/html/mysite/public>
SSLOptions +StdEnvVars
Options Indexes FollowSymLinks MultiViews
AllowOverride All
<If "%{REQUEST_URI} =~ m#api/public#">
Require all granted
</If>
<Else>
AuthType shibboleth
ShibRequestSetting requireSession 1
Require valid-user
</Else>
</Directory>
Here's the .htaccess
file that Laravel ships with:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Unfortunately with the .htaccess
file in place, the Else
code is still getting executed and the Shib code runs. But I'm pretty sure the If
condition is catching, because if throw in Require all denied
as a test then it does forbid as expected.
If I remove the .htaccess
however, this works! But it also means that any routing within Laravel is now broken, which I do need for this public-facing URL.
My best guess is that the .htaccess
RewriteRule
is causing the Else
code to still run even after the If
statement caught. Any suggestions on a way around this? Running into the same problem using Location
directive.
Thanks.
Figured out a solution for this, will share here in case someone else runs into this. The issue was indeed that RewriteRule
causes us to run through the whole thing again. The If
stopped Shibboleth as expected the first time, but then we'd go through again after Laravel redirects us to index.php
and pick it up anyway.
Solved it by changing the Else
to an ElseIf
where we exclude index.php
:
<Directory /var/www/html/mysite/public>
SSLOptions +StdEnvVars
Options Indexes FollowSymLinks MultiViews
AllowOverride All
<If "%{REQUEST_URI} =~ m#api/public#">
Require all granted
</If>
<ElseIf "%{REQUEST_URI} !~ m#index\.php#">
AuthType shibboleth
ShibRequestSetting requireSession 1
Require valid-user
</ElseIf>
</Directory>