Optionally pass REMOTE_USER to application - apache

In our company we have an apache server running a django application (through wsgi) and some legacy php applications. To have some sort of single sign on we decided to use mod_auth_form and wsgi as the AuthFormProvider.
In django itself we enabled the RemoteUserBackend and all works fine.
The legacy php applications are also protected via mod_auth_form and wsgi.
The problem is that there are some locations which should be accessible by authenticated and anonymous users where authenticated users have some sort of extras (like personal greeting or an enabled logout button).
With our current configuration however I can't figure out to tell apache to set REMOTE_USER if a user has logged in previously but does not ask for a password if the user is not logged in.
I will try to give an example of what I want to accomplish.
This is an example configuration.
<Location "/protected-zone">
AuthType basic
AuthName "private area"
AuthBasicProvider file
AuthUserFile /usr/local/etc/apache2/userfile.htaccess
<RequireAll>
Require valid-user
</RequireAll>
</Location>
<Location "/mixed-zone">
AuthType basic
AuthName "private area"
AuthBasicProvider file
AuthUserFile /usr/local/etc/apache2/userfile.htaccess
<RequireAll>
Require [todo]
</RequireAll>
</Location>
If users go to /protected-zone they should be asked for a password - that's quite easy.
If the user then goes to /mixed-zone (after sucessfull login) he or she should be greeted with their username (based on the header REMOTE_USER).
If an unauthenticated user goes to /mixed-zone he or she should not be prompted to enter credentials.
What we've tried so far was to omit the ReqireAll tag in /mixed-zone which causes apache to never set REMOTE_USER even if the user was logged in before.

Thanks to the comment about sessions I was finally able to fix the problem in our specific case.
We now use sessions like in the example below.
SessionMaxAge [age in seconds]
SessionCookieName session-cookie path=/;httponly;secure;version=1
SessionCryptoPassphrase [some random string]
<Location "/protected-zone">
Session On
SessionEnv On
AuthType basic
AuthName "private"
AuthBasicProvider file
AuthUserFile /usr/local/etc/apache2/userfile.htaccess
<RequireAll>
Require valid-user
</RequireAll>
</Location>
<Location "/mixed-zone">
Session On
SessionEnv On
</Location>
With SessionEnv set to On apache sets an additional HTTP_SESSION header in the request which may be used by the underlying application (see PHP example below)
<?php
$session = array();
parse_str($_SERVER['HTTP_SESSION'], $session);
$username = $session['private-user'];
?>
Since we use django I wrote a small middleware which is executed before RemoteUserMiddleware and sets REMOTE_USER according to the user in the session if it was not specified previously.
from urllib.parse import parse_qs # works in pyhton3
class SessionUserMiddleware (object):
"""
Middleware to extract a user from a session if no REMOTE_USER is set.
"""
header = "REMOTE_USER"
session_header = "HTTP_SESSION"
session_key = "private-user"
def process_request(self, request):
if self.header not in request.META or not request.META[self.header]:
try:
username = parse_qs(request.META[self.session_header])[self.session_key]
request.META[self.header] = username
except KeyError:
pass

Related

Pass username after LDAP auth on Apache

I have users authenticating against a jumpcloud ldap db. They successfully authenticate but the username they enter does not get passed on to the application. I tried to set it to REMOTE_USER and called it but it gives out an empty output. aka REMOTE_USER = none
How do I pass the username to the application?
AllowOverride None
Order allow,deny
allow from all
AddHandler mod_python .py
PythonHandler mod_python.publisher
PythonDebug On
LDAPTrustedClientCert certbase /ssl/file/path
AuthType Basic
AuthName "name"
AuthBasicProvider ldap
AuthLDAPURL "ldaps://ldap.jumpcloud.com~~~~"
AuthLDAPBindDN "uid=userid,ou=Users,o=orgnum,dc=jumpcloud,dc=com"
AuthLDAPBindPassword password
RequestHeader set X-Remote-User expr=%{REMOTE_USER}
Require valid-user
I work at JumpCloud and am a member of the product team. While I don't know your precise auth'n use case, what I would recommend is to try a fully qualified username lookup. Our LDAP will require a user dn string that would be similar to something like this which we've seen other off the shelf products require:
uid=${userID},ou=users,o=(Your JumpCloud Org ID),dc=jumpcloud,dc=com
Also, specific to your LDAP BindDN (e.g. the service account in JumpCloud you're using to make the secure handshake to your service/app) needs to be very precise...e.g.:
uid=(Your BindDN Username),ou=users,o=(Your JumpCloud Org ID),dc=jumpcloud,dc=com
Absolutely feel free to shoot us an email at support#jumpcloud.com and we can get into a much deeper analysis to get you going.

BasicAuth with "ldap file" providers doesn't work for users in file

I have a host where authenticated users need to be in a certain ldap group. This worked perfectly. Afterwards I needed an external user that I put locally in a file and this one doesn't work.
When I comment out all the ldap lines that user works, so the file is created correctly and accessible by Apache 2.2, but when I add ldap, everything work for the ldap users but not for the file user.
When I try to log in with the local in file user with a bad password I get the log in pop-up again, as usual, but when I insert the correct credentials I get "Authorization Required
This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required."
Below is my set upon Apache 2.2
<Location "/">
Deny from all
AuthType Basic
AuthName "My Auth"
AuthBasicProvider ldap file
AuthLDAPURL LDAP_URL
AuthUserFile "path/to/pass/file"
Require user file_user
Require ldap-group cn=LDAP Group,cn=Groups,dc=DC,dc=org
Require ldap-user ldap_user_outside_group
Satisfy any
</Location>
You likely need AuthzLDAPAuthoritative to allow the failure to match the ldap-based Require directives to not be fatal. This kind of directive was made obsolete in later releases by internal improvements in 2.4.

Apache2 - display auth only for public IP's, only on testing server

I want to configure universal .htaccess file for my application to protect my testing server. I want to display basic auth for any request that comes from public IP, only if current server is testing.
How to archieve this? I know how to protect domain and exclude some IP:
AuthType Basic
AuthName "Please Log In"
AuthUserFile /some/path/.htpasswd
Require valid-user
Order deny,allow
Deny from all
Allow from 127.0.0.1
Satisfy any
But how I can let this code run only if server is dev/testing? I can't change env variables. I thought about detecting domain (server that I want to protect is on subdomain), and place code from above in some sort of if block, but I don't know how.
You use mod_setenvif to set an env variable based on current host and use it auth later:
SetEnvIfNoCase Host ^sub\.domain\.com$ SECURED
AuthType Basic
AuthName "Please Log In"
AuthUserFile /some/path/.htpasswd
Require valid-user
Order Allow,Deny
Allow from 127.0.0.1
Deny from env=SECURED
Satisfy any

How can I debug htpasswd access?

I have a site hosted on hostgator that I've set up with a directory to use htaccess/htpasswd for authentication. It's working fine but only for a user named test.
Here's the relevant htaccess
<filesMatch "(-priv)">
AuthType Basic
AuthName "Private Area"
AuthUserFile /home/username/public_html/site/test/.htpasswd
Require user test
</filesMatch>
and the htpasswd has 2 users
test:ovCvloB9kYgBQ
admin:RxvCRMqtdryys
I can log in using the test user but if I use any other name authentication fails. I can change the password for the test user and authentication reflects the change. The behavior is consistent across browsers and IPs.
Is there any way to debug this?
And before you say it, I know not to put the .htpasswd file above webroot, this is a test setup.
You have Require user test
Change to Require valid-user

Enforcing https connection

I have managed to get authentication at least partly set up but am mystified as to why security isn't working...
In my httpd.conf file for ssl I have....
<Directory /usr/local/apache2.2/cgi-bin/oia>
SSLRequireSSL
Satisfy All
AuthType basic
AuthName "Protected Intranet Area"
AuthUserFile conf/.passwd
AuthGroupFile conf/groups
Require valid-user
</Directory>
I do have the user password in the setup and when accessing the page via https://....../cgi-bin/oia, it does correctly prompt me for the user name and password. Problem is if I use the same URL with http:// there's no prompting for a user name or password.
Any advice is greatly appreciated.
Nikki
You could set up a mod_rewrite rule to always forward the http://x.y.com to https://x.y.com (which is probably what you want to do anyway)