Ticket #4733 (new enhancement)
Option for all login links to use HTTPS
| Reported by: | jeffcorbets@… | Owned by: | jonas |
|---|---|---|---|
| Priority: | normal | Milestone: | next-major-0.1X |
| Component: | general | Version: | |
| Severity: | normal | Keywords: | secure, login, https |
| Cc: | felix.schwarz@…, trac-bugs@… |
Description
It would be nice if trac could automatically use the https protocol in creating links to login with an appropriately configured web server.
I have tried a number of mod_rewrite rules and LocationMatch directives, but have not been successful in getting logins for multiple trac projects to be re-directed to the secure server for processing.
Attachments
Change History
comment:2 Changed 3 years ago by jeffcorbets@…
It would be nice to see this incorporated as soon as possible, hopefully no later than 0.11. The proposed additional option seems like a fine solution to me.
comment:3 Changed 3 years ago by dacat
The following is the solution I have implemented to do what I believe jeffcorbets@… is trying to achieve.
Make Trac use SSL for login links on a Multi-Environment Setup
Summary
After implementing the following solution..
- All the Environments Login links will force an SSL connection.
- All other pages that are not Login pages will be served up on a non-ssl connection.
Assumptions
This solution assumes the following
- You have a working Apache2 web server configured.
- You have a working Trac installation.
- You have root on the machine your are attempting to configure.
- You have a working SSL configuration.
Solution
For this solution to work you need
- Two Virtual Hosts configured
- One vhost that listens on yourhost:80
- One vhost that listens on yourhost:443
Let:
- host_name
- be the FQDN of your Apache web server.
- myvhost.conf
- be the name of the apache configuration file for your virtual host that listens on port 80
- myvhost-ssl.conf
- be the name of the apache configuration file for your virtual host that listens on port 443 and has SSL enabled
Apache Virutal Host Configuration Changes
myvhost.conf changes
- Move you Trac specific directives into myvhost.conf
- Add the RedirectMatch Directive into myhost.conf
- Should look something like this
<IfModule mod_python.c> RedirectMatch /([^/]+)/login https://host_name/trac/$1/login <Location /trac > SetHandler mod_python PythonHandler trac.web.modpython_frontend PythonOption TracEnvParentDir /path/to/trac/projects/ </Location> </IfModule>
myvhost-ssl.conf changes
- Add a LocationMatch Directive for the login page.
- Add a RedirectMatch Directive to redirect all other Trac pages.
- Should look something like
<IfModule mod_python.c> RedirectMatch "/trac/([^/]+($|/))(?!login$)" http://host_name/trac/$1 <LocationMatch /trac/[^/]+/login> SSLRequireSSL SetHandler mod_python PythonHandler trac.web.modpython_frontend PythonOption TracEnvParentDir /path/to/trac/projects/ AuthType Basic AuthName "Trac" AuthUserFile /path/to/your/auth/file Require valid-user </LocationMatch> </IfModule>
Make sure you change the parameters above to match your installation of Trac.
Execution Flow
What should happen after the changes are implemented is the following:
- User clicks on 'login' on the non-ssl port 80 vhost
- The RecirectMatch in myvhost.conf fires redirecting the user to the SSL site on port 443 site.
- The LocationMatch directive in myvhost-ssl.conf fires and pops up the authentication window you will see https://yourhost identified in the authentication window.
- After the user authenticates, Trac redirects the user to the Trac page, where the user clicked login, on the SSL site port 443 vhost.
- The RedirectMatch in myvhost-ssl.conf fires redirecting the user to the Trac wiki for the environment they are using on the non-ssl port 80 vhost
Conclusion
I have attempted to test this solution extensively.
- I watched the apache ssl request logs to make sure ssl requests are being made.
- I clicked through all seven of my Trac projects and they function normally.
- I've modified urls by hand to see what the effects would be and everything appears to function normally.
I really do hope this helps people. Questions Comments? my email is dacat_spamalot_ATunt.edu remove _spamalot_ to send mail
comment:4 Changed 3 years ago by jeffcorbets
That solutions works fairly well. I wish it would return the user to the page they tried to log in from after authentication instead of the wiki every time, but beggars cannot be choosers.
Also, my setup makes extensive use of LDAP for authentication. For each project I create, right now I hand add it to the configuration file so that the required (LDAP) group is different for each project. Is there anyway that can be simplified using the LocationMatch directive by actually capturing the regular expression group and then using it later in the Require group ... directive??
comment:5 Changed 3 years ago by shap
The proposed redirect solution looks pretty good. Returning to the same page requires putting some kind of query string into the login URI.
However, this solution is not complete, because password changes are not guarded. Also, a case can be made that administration pages want to be SSL-guarded as well. Getting all of this right requires that the core be in on the joke, and it requires much more than just a secure login URI.
comment:6 Changed 2 years ago by Martin <martin@…>
FYI, this configuracion didn't work for me (don't know why). I made two rewrite rules in the ssl.conf file and I get excelent redirection both ways.
In trac.conf I have something like:
Redirect /cursos/login https://mytracserver/cursos/login
<Location /cursos>
Allow from all
SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnv /var/lib/trac/cursos
PythonOption TracUriRoot /cursos
SetEnv PYTHON_EGG_CACHE /tmp/
</Location>
On the ssl.conf I have this:
RewriteEngine On
RewriteRule ^/cursos/login https://mytracserver/cursos/login [L]
RewriteRule ^/cursos/(.*) http://mytracserver/cursos/$1 [L]
<Location /cursos/>
Allow from all
SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnv /var/lib/trac/cursos
PythonOption TracUriRoot /cursos
SetEnv PYTHON_EGG_CACHE /tmp/
</Location>
Hope it helps anybody.
comment:7 follow-up: ↓ 8 Changed 2 years ago by robin-trac@…
Hi,
I was looking into doing something similar to this and asked on #trac IRC. I was told that once logged in sensitive data is transferred for every request (login details) so it is sensible to remain in https after logging in.
R.
comment:8 in reply to: ↑ 7 Changed 2 years ago by nkantrowitz
Replying to robin-trac@robinbowes.com:
I was looking into doing something similar to this and asked on #trac IRC. I was told that once logged in sensitive data is transferred for every request (login details) so it is sensible to remain in https after logging in.
The username and password are not sent again, but a login cookie is. This original credentials can't be retrieved even with this cookie, but an attacker could impersonate the user until the cookie expires and is reissued (every 8 hours IIRC).
comment:9 follow-up: ↓ 18 Changed 18 months ago by djs@…
We're using an apache rewrite to send the request back to the referring page:
RewriteEngine on
# Go to the referer if there is one
RewriteCond %{REQUEST_URI} !/trac/(.*)/login$
RewriteCond %{HTTP_REFERER} ^http://mytracserver/trac/.*
RewriteRule . %{HTTP_REFERER} [R]
# If not, go to wherever Trac wants to go
RewriteCond %{REQUEST_URI} !/trac/(.*)/login$
RewriteCond %{HTTP_REFERER} !^http://mytracserver/trac/.*
RewriteRule ^/trac/(.*)$ http://mytracserver/trac/$1 [R]
comment:11 Changed 16 months ago by Olivier Mehani <shtrom-trac@…>
I'm using the standalone tracd server and successfully did something quite similar to djs. I have two virtual hosts acting as proxies to the actual tracd port.
Connection on port 80 is transparently proxied until a login URL is found, in which case the user's browser is redirected to the same URL on port 443. After logging in, there is little point in returning the user to unencrypted HTTP (though there is no more point in keeping him using HTTPS, except for lazyness (: ), so nothing is done about it.
The HTTP VirtualHost:
<VirtualHost *:80>
ServerName mytracserver
DocumentRoot /htdocs/trac
RewriteEngine On
RewriteRule ^/([^/]+)/login https://mytracserver/$1/login [R]
RewriteRule ^/(.*) http://localhost:8080/$1 [P]
<Directory proxy:http://localhost:8080>
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
and the SSL VirtualHost:
<VirtualHost *:443>
ServerName mytracserver
DocumentRoot /htdocs/trac
ProxyRequests off
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
<Directory proxy:http://localhost:8080>
Order allow,deny
Allow from all
</Directory>
# Other standard SSL configuration goes here
</VirtualHost>
comment:13 follow-up: ↓ 14 Changed 10 months ago by madyogi
Well,
As far as I think the virtual hosts don't share cookies/session name-spaces between themselves. The Apache goal was to make virtual hosts work as totally separate physical boxes, beside what about security??? If one redirects to https using rewrite rules and logs in, as long as he/she stays there, will be able to use privileged trac account possibilities. But whenever one goes back to http (different virtual host) the information about being logged in will disappear... At least it should!!! (The great truth about login cookie from the post above.)
If you do something like:
http (80) virtual host, knows about <location /trac > only and
https (443) virtual host, knows about <location /trac/login > only.
These are two (virtual) hosts not one physical apache, using two transmission protocols (http/https) for the same purpose.
If you connect the cookie data with a specific session opened one one virtual host how do you want the cookie to still be there, accessible from a different session?
It's quite easy to redirect one from http to https and make the trac page look the same on both hosts. Next, when you rewrite the URI that https://.../trac/login redirects back to http://.../trac, you will make a loop, not giving a chance to log in. Or you don't do it and using other tricks you stay at https and user logs in. (That's what I managed to do using myvhost and myvhost-ssl post from above).
After all, when he/she clicks a link and comes back to http, he/she will not be logged in because http virtual host never received users login/password data (login cookie). Though they (it) still exist(s) when one goes back to https again...
Or, am I wrong???
Beside, Trac had not to be a MasterCard? PIN tracking tool, at least as long as you don't use your credit card number as a login and a PIN number as a password... (Though it would be a great extension too...)
comment:14 in reply to: ↑ 13 Changed 10 months ago by Felix Schwarz <felix.schwarz@…>
Replying to madyogi:
As far as I think the virtual hosts don't share cookies/session name-spaces between themselves. The Apache goal was to make virtual hosts work as totally separate physical boxes, beside what about security??? If one redirects to https using rewrite rules and logs in, as long as he/she stays there, will be able to use privileged trac account possibilities. But whenever one goes back to http (different virtual host) the information about being logged in will disappear... At least it should!!!
I'm not sure that I understood you correctly. However if both virtual hosts serve the same domain name (just http/https) and trac does not mark the cookie as 'https only', the cookie can be used with the non-encrypted pages as well.
comment:15 follow-up: ↓ 16 Changed 10 months ago by anonymous
Well, you understood me fine,
I thought about the previous post this morning and I guess that I wrote it a bit wrong way, sorry for that.
The reason I wrote the previous post was that I've created some time ago my own trac and mod-python extension – a new pythonathenhandler function. The goal was to authenticate users basing on MySQL database content and not using local .htpassword file. I did it and the extension works well, as long as I use single virtual host environment. Note I'm not python / apache internals guru.
Plenty of people write that BasicAuth? over SSL can be done! Whenever I tried to spread the trac over two virtual machines the authentication failed. Whenever I stayed at https I was authenticated and whenever I came back to http the authentication credentials were lost... :( The same thing happened when I used my own pythonauthenhandler function.
So is SSL Basicauth really possible, is there something rally bad with my vhost environment?
comment:16 in reply to: ↑ 15 Changed 10 months ago by Felix Schwarz <felix.schwarz@…>
Replying to anonymous:
So is SSL Basicauth really possible, is there something rally bad with my vhost environment?
Yes, it is. I'm using it on a daily basis.
comment:17 Changed 10 months ago by madyogi
I did a bit more extensive tests this Sunday because the entire thing doesn't make me sleep well.
Used a bit simpler server side tool - PHP and observed the "sess*" files that server creates. I used two virtual hosts for tests - result:
http://www.myhost.com is not the same as https://ssl.myhost.com so optimistically thinking – I was partially right here but:
http://www.myhost.com seams to be the same as https://www.myhost.com, so at this point I was wrong and you are right! PERIOD
Yes, I've learned something!
Back to Trac.
It took me entire morning to figure out how to make it and finally it works as it supposed to. User enters http, clicks [login], is being redirected to https virtual host, authenticates and is being automatically redirected back to http site. It's worth to mention here that https box is not a dedicated host for Trac only, it also hosts a different encrypted content at the same port (443).
I had to put this into my vhost.conf file:
RewriteEngine On
# Redirect was not working as it should for me... :(
RewriteRule ^/trac/login https://www.myhost.com/trac/login [R]
<Location /trac >
SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnv /pub/trac/myproject
PythonOption TracEnvIndexTemplate /pub/trac/myproject/templates
# PythonOption TracEnvParentDir /pub/trac
</Location>
And this into vhost-ssl.conf:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/trac [NC]
RewriteRule !^/trac/login http://www.myhost.com%{REQUEST_URI}
# Same story with RedirectMatch – not working, had strange issues with
# CSS stylesheets.
<LocationMatch "/trac/login" >
SetHandler mod_python
PythonInterpreter main_interpreter
PythonOption TracEnv /pub/trac/myproject
PythonOption TracEnvIndexTemplate /pub/trac/myproject/templates
# PythonOption TracEnvParentDir /pub/trac
PythonHandler trac.web.modpython_frontend
# Use a MySQLdb and mod_python to read users data from SQL tables
# instead of .htpasswd file. Don't use it if you use htpassword.
# PythonAuthenHandler tpm_handler
# PythonDebug On
# AuthBasicAuthoritative Off
AuthType Basic
AuthName "Authorized users area."
Require valid-user
</LocationMatch>
Hope this will be helpful to others and Felix thanks for your opinion...
I'm using Trac 0.11.5 (out of the box), Apache 2.2.11 (Unix) with Python 2.6 and mod_python-3.3.1 + a tiny C code patch (all compiled on my own from sources).
comment:18 in reply to: ↑ 9 Changed 4 months ago by ronalde
Replying to djs@…:
We're using an apache rewrite to send the request back to the referring page:
Maybe it's worth noting that this should be applied in ssl vhost.
For future reference I'll include our complete setup:
- multi repositories under /trac
- custom trac projects index page
- use of mod_wsgi
- only https for authentication; everything else via http
- use of basis ldap authentication
Custom index page for trac root /var/www/multitrac/generated-index/html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:py="http://genshi.edgewall.org/" xmlns:xi="http://www.w3.org/2001/XInclude"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Generated Trac Index</title> <style type="text/css" title="Standaard (Scherm)" media="all"> @import url("/stylesheets/screen.css"); </style> </head> <body> <div id="contents"> <h1>Projects </h1> <!-- start #generated --> <!-- only display trac projects which do not start with 'Archive' --> <div id="generated" class="project" py:for="project in projects" py:if="project.name.startswith('Archive') == False"> <h2> <!-- replace 'Trac - ' by empty string in description --> <a href="$project.href" title="$project.description"> ${project.name.replace(Trac - ','')} </a> </h2> <p>$project.description</p> </div><!-- end #generated --> </div><!-- end #contents --> </body> </html>
wsgi script in /etc/trac/wsgi/multitrac.wsgi
# application script to enable apache wsgi hosting of trac # see: # * http://trac.edgewall.org/wiki/TracModWSGI # * http://code.google.com/p/modwsgi/wiki/IntegrationWithTrac import sys sys.stdout = sys.stderr import os os.environ['TRAC_ENV_PARENT_DIR'] = '/var/lib/trac' os.environ['PYTHON_EGG_CACHE'] = '/var/cache/trac' os.environ['TRAC_ENV_INDEX_TEMPLATE'] = '/var/www/multitrac/trac/index-generated.html' import trac.web.main application = trac.web.main.dispatch_request
apache 2 virtual host in /etc/apacha2/sites-available/multitrac
# /etc/apache2/sites-available/multitrac # # reference: # * only logins via https: http://trac.edgewall.org/ticket/4733 # * usage of mod_wsgi for trac: http://code.google.com/p/modwsgi/wiki/IntegrationWithTrac # * overview of apache mod_rewrite: http://httpd.apache.org/docs/trunk/rewrite/intro.html <VirtualHost *:80> # static root for other pages and htdocs DocumentRoot /var/www/multitrac ServerName multitrac # trac: rewrite to https:// when uri is trac login page RewriteEngine on RewriteRule ^/trac/([[:alnum:]]+)/login https://multitrac/trac/$1/login [R] # trac: match root uri for trac handling WSGIScriptAliasMatch ^/trac /etc/trac/wsgi/multitrac.wsgi <Directory /etc/trac/wsgi> WSGIApplicationGroup %{GLOBAL} # trac: root for trac projects SetEnv trac.env_parent_dir /var/lib/trac Order deny,allow Allow from all </Directory> <IfModule mod_mem_cache.c> CacheEnable mem / # cache memory in KB MCacheSize 1000000 MCacheMaxObjectSize 6400000 MCacheMaxObjectCount 1009 </IfModule> </VirtualHost> <VirtualHost *:443> DocumentRoot /var/www/multitrac ServerName multitrac # ssl-cettings; certificate is generated using cacert SSLEngine on SSLCertificateFile /etc/ssl/certs/ssl-cert-multitrac.pem SSLCertificateKeyFile /etc/ssl/private/ssl-key-multitrac.pem RewriteEngine on # trac: redirect to non-https connection when uri is not login-uri # trac: go back to the http referer if there is one RewriteCond %{REQUEST_URI} !/trac/[[:alnum:]]+/login$ RewriteCond %{HTTP_REFERER} ^http://multitrac/trac/.* RewriteRule . %{HTTP_REFERER} [R] # trac: if there is no referrer, go to the original requested http uri RewriteCond %{REQUEST_URI} !/trac/[[:alnum:]]+/login$ RewriteCond %{HTTP_REFERER} !^http://multitrac/trac/.* RewriteRule ^/trac/(.*)$ http://multitrac/trac/$1 [R] # trac: define wsgi application WSGIScriptAliasMatch ^/trac /etc/trac/wsgi/multitrac.wsgi <Directory /etc/trac/wsgi> WSGIApplicationGroup %{GLOBAL} # trac: root for trac projects SetEnv trac.env_parent_dir /var/lib/trac Order deny,allow Allow from all </Directory> # trac: match login page for specific trac project <LocationMatch "/trac/[[:alnum:]]+/login"> AuthType Basic AuthName "Multitrac - LDAP-Authentication" AuthBasicProvider ldap AuthzLDAPAuthoritative off AuthLDAPURL "ldaps://ldaphost/dc=search,dc=base?uid?sub?(objectClass=employee)" Require valid-user </LocationMatch> </VirtualHost>
comment:19 Changed 7 weeks ago by Oliver Tappe <zooey@…>
I'm a bit confused as to why the posted solutions switch away from https as soon as the login page has been left. AFAICS, this means that every security-related cookie (or other information) will travel unprotected through the net, once a person is logged on.
A couple of months ago, I have activated http-digest authentication on our trac installation in order to protect the passwords, which works just fine, but still has the disadvantage of allowing session hijacking by some man-in-the-middle grabbing the cookies. I tried that myself at the time and was easily able to take over a session of someone else and change his password.
That's what makes me believe that the redirection from https back to http should be done on the 'logout' page, not on everything that's not 'login'.
Or am I being daft?
cheers,
Oliver
comment:20 Changed 7 weeks ago by labs@…
The redirecting trick based upon the referer doesn't seem to work with me. After the credentials are securely entered on the /login/ page, trac is redirecting back to the home page, not to the original refering page.
Do other people get this to work? Or do I need to patch the login page somehow?
best,
Dirk
comment:21 Changed 3 weeks ago by labs@…
Replying to myself:
I fixed this double referer issue in the AccountManagerPlugin?. See here http://trac-hacks.org/ticket/3783#comment:6
Dirk



We could define a new front-end setting, similar to TracUriRoot, e.g. TracLoginUri.