diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -131,6 +131,7 @@ facilities.
         tracopt.perm.config_perm_provider = tracopt.perm.config_perm_provider
         tracopt.ticket.commit_updater = tracopt.ticket.commit_updater
         tracopt.ticket.deleter = tracopt.ticket.deleter
+        tracopt.web.altlinks = tracopt.web.altlinks
     """,
 
     **extra
diff --git a/trac/web/auth.py b/trac/web/auth.py
--- a/trac/web/auth.py
+++ b/trac/web/auth.py
@@ -225,8 +225,9 @@ class LoginModule(Component):
     def _redirect_back(self, req):
         """Redirect the user back to the URL she came from."""
         referer = self._referer(req)
-        if referer and not (referer == req.base_url or \
-                referer.startswith(req.base_url.rstrip('/')+'/')):
+        if referer and referer.startswith(('http://', 'https://')) \
+                and not (referer == req.base_url or \
+                         referer.startswith(req.base_url.rstrip('/') + '/')):
             # only redirect to referer if it is from the same site
             referer = None
         req.redirect(referer or req.abs_href())
diff --git a/tracopt/web/__init__.py b/tracopt/web/__init__.py
new file mode 100644
diff --git a/tracopt/web/altlinks.py b/tracopt/web/altlinks.py
new file mode 100644
--- /dev/null
+++ b/tracopt/web/altlinks.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2010 Edgewall Software
+# All rights reserved.
+#
+# This software is licensed as described in the file COPYING, which
+# you should have received as part of this distribution. The terms
+# are also available at http://trac.edgewall.org/wiki/TracLicense.
+#
+# This software consists of voluntary contributions made by many
+# individuals. For the exact contribution history, see the revision
+# history and logs, available at http://trac.edgewall.org/log/.
+
+import re
+
+from trac.config import Option
+from trac.core import Component, implements
+from trac.web.api import IRequestFilter
+
+
+class AltLinkLoginRewriter(Component):
+    """Rewrite selected alternative format links to require authentication.
+    
+    This component rewrites alternative format links matching the regexp in
+    `[web] altlink_rewrite` for authenticated users to redirect through
+    `/login`, therefore requiring authentication. The default regexp matches
+    all links containing a `format=rss` or `format=ics` query argument,
+    therefore ensuring that e.g. RSS readers log in before requesting a feed.
+    
+    This component doesn't work with form-based login.
+    """
+
+    implements(IRequestFilter)
+
+    altlink_login_rewrite = Option('web', 'altlink_login_rewrite',
+        r'.*\?(.*&)?format=(rss|ics)(&.*)?$',
+        """Regexp pattern defining the alternative format links that should be
+        rewritten to require authentication.""")
+
+    _pattern = None
+
+    # IRequestFilter methods
+
+    def pre_process_request(self, req, handler):
+        return handler
+
+    def post_process_request(self, req, template, data, content_type):
+        if req.authname and req.authname != 'anonymous':
+            if self._pattern is None:
+                self._pattern = re.compile(self.altlink_login_rewrite)
+            for link in req.chrome.get('links', {}).get('alternate', []):
+                href = link.get('href')
+                if href is not None and self._pattern.match(href):
+                    link['href'] = req.href.login(referer=href)
+        return template, data, content_type

