diff --git a/trac/ticket/report.py b/trac/ticket/report.py
--- a/trac/ticket/report.py
+++ b/trac/ticket/report.py
@@ -38,7 +38,7 @@ from trac.util.text import exception_to_
 from trac.util.translation import _
 from trac.web.api import IRequestHandler, RequestDone
 from trac.web.chrome import add_ctxtnav, add_link, add_notice, add_script, \
-                            add_stylesheet, add_warning, \
+                            add_stylesheet, add_warning, auth_link, \
                             INavigationContributor, Chrome
 from trac.wiki import IWikiSyntaxProvider, WikiParser
 
@@ -266,8 +266,8 @@ class ReportModule(Component):
             return req.href.report(sort=req.args.get('sort'),
                                    asc=asc and '1' or '0', **kwargs)
 
-        add_link(req, 'alternate', 
-                 report_href(format='rss'),
+        add_link(req, 'alternate',
+                 auth_link(req, report_href(format='rss')),
                  _('RSS Feed'), 'application/rss+xml', 'rss')
         add_link(req, 'alternate', report_href(format='csv'),
                  _('Comma-delimited Text'), 'text/plain')
@@ -548,8 +548,8 @@ class ReportModule(Component):
                            filename=filename)
         else:
             p = max is not None and page or None
-            add_link(req, 'alternate', 
-                     report_href(format='rss', page=None),
+            add_link(req, 'alternate',
+                     auth_link(req, report_href(format='rss', page=None)),
                      _('RSS Feed'), 'application/rss+xml', 'rss')
             add_link(req, 'alternate', report_href(format='csv', page=p),
                      _('Comma-delimited Text'), 'text/plain')
diff --git a/trac/ticket/roadmap.py b/trac/ticket/roadmap.py
--- a/trac/ticket/roadmap.py
+++ b/trac/ticket/roadmap.py
@@ -42,7 +42,8 @@ from trac.ticket.query import QueryModul
 from trac.timeline.api import ITimelineEventProvider
 from trac.web import IRequestHandler, RequestDone
 from trac.web.chrome import add_link, add_notice, add_script, add_stylesheet, \
-                            add_warning, Chrome, INavigationContributor
+                            add_warning, auth_link, Chrome, \
+                            INavigationContributor
 from trac.wiki.api import IWikiSyntaxProvider
 from trac.wiki.formatter import format_to
 
@@ -368,8 +369,8 @@ class RoadmapModule(Component):
         if req.authname and req.authname != 'anonymous':
             username = req.authname
         icshref = req.href.roadmap(show=show, user=username, format='ics')
-        add_link(req, 'alternate', icshref, _('iCalendar'), 'text/calendar',
-                 'ics')
+        add_link(req, 'alternate', auth_link(req, icshref), _('iCalendar'),
+                 'text/calendar', 'ics')
 
         data = {
             'milestones': milestones,
diff --git a/trac/ticket/web_ui.py b/trac/ticket/web_ui.py
--- a/trac/ticket/web_ui.py
+++ b/trac/ticket/web_ui.py
@@ -46,8 +46,9 @@ from trac.util.translation import _, tag
 from trac.versioncontrol.diff import get_diff_options, diff_blocks
 from trac.web import arg_list_to_args, parse_arg_list, IRequestHandler
 from trac.web.chrome import add_link, add_notice, add_script, add_stylesheet, \
-                            add_warning, add_ctxtnav, prevnext_nav, Chrome, \
-                            INavigationContributor, ITemplateProvider
+                            add_warning, add_ctxtnav, auth_link, \
+                            prevnext_nav, Chrome, INavigationContributor, \
+                            ITemplateProvider
 from trac.wiki.formatter import format_to, format_to_html, format_to_oneliner
 
 
@@ -630,6 +631,8 @@ class TicketModule(Component):
             format = conversion[0]
             conversion_href = get_resource_url(self.env, ticket.resource,
                                                req.href, format=format)
+            if format == 'rss':
+                conversion_href = auth_link(req, conversion_href)
             add_link(req, 'alternate', conversion_href, conversion[1],
                      conversion[4], format)
                      
diff --git a/trac/timeline/web_ui.py b/trac/timeline/web_ui.py
--- a/trac/timeline/web_ui.py
+++ b/trac/timeline/web_ui.py
@@ -34,8 +34,9 @@ from trac.util.datefmt import format_dat
 from trac.util.text import exception_to_unicode, to_unicode
 from trac.util.translation import _, tag_
 from trac.web import IRequestHandler, IRequestFilter
-from trac.web.chrome import add_link, add_stylesheet, prevnext_nav, Chrome, \
-                            INavigationContributor, ITemplateProvider
+from trac.web.chrome import add_link, add_stylesheet, auth_link, \
+                            prevnext_nav, Chrome, INavigationContributor, \
+                            ITemplateProvider
                             
 from trac.wiki.api import IWikiSyntaxProvider
 
@@ -225,7 +226,7 @@ class TimelineModule(Component):
         rss_href = req.href.timeline([(f, 'on') for f in filters],
                                      daysback=90, max=50, authors=authors,
                                      format='rss')
-        add_link(req, 'alternate', rss_href, _('RSS Feed'),
+        add_link(req, 'alternate', auth_link(req, rss_href), _('RSS Feed'),
                  'application/rss+xml', 'rss')
 
         for filter_ in available_filters:
diff --git a/trac/versioncontrol/web_ui/log.py b/trac/versioncontrol/web_ui/log.py
--- a/trac/versioncontrol/web_ui/log.py
+++ b/trac/versioncontrol/web_ui/log.py
@@ -35,7 +35,7 @@ from trac.versioncontrol.web_ui.changese
 from trac.versioncontrol.web_ui.util import *
 from trac.web import IRequestHandler
 from trac.web.chrome import add_ctxtnav, add_link, add_stylesheet, \
-                            INavigationContributor, Chrome
+                            auth_link, INavigationContributor, Chrome
 from trac.wiki import IWikiSyntaxProvider, WikiParser 
 
 class LogModule(Component):
@@ -294,7 +294,7 @@ class LogModule(Component):
 
         rss_href = make_log_href(path, format='rss', revs=revs,
                                  stop_rev=stop_rev)
-        add_link(req, 'alternate', rss_href, _('RSS Feed'),
+        add_link(req, 'alternate', auth_link(req, rss_href), _('RSS Feed'),
                  'application/rss+xml', 'rss')
         changelog_href = make_log_href(path, format='changelog', revs=revs,
                                        stop_rev=stop_rev)
diff --git a/trac/web/auth.py b/trac/web/auth.py
--- a/trac/web/auth.py
+++ b/trac/web/auth.py
@@ -84,7 +84,12 @@ class LoginModule(Component):
         if req.remote_user:
             authname = req.remote_user
         elif req.incookie.has_key('trac_auth'):
-            authname = self._get_name_for_cookie(req, req.incookie['trac_auth'])
+            authname = self._get_name_for_cookie(req,
+                                                 req.incookie['trac_auth'])
+            if authname is None:
+                # The cookie is invalid (or has been purged from the database),
+                # so tell the user agent to drop it as it is invalid
+                self._expire_cookie(req)
 
         if not authname:
             return None
@@ -153,15 +158,23 @@ class LoginModule(Component):
         assert req.authname in ('anonymous', remote_user), \
                _('Already logged in as %(user)s.', user=req.authname)
 
-        cookie = hex_entropy()
         with self.env.db_transaction as db:
-            # Delete cookies older than 10 days
-            db("DELETE FROM auth_cookie WHERE time < %s",
-               (int(time.time()) - 86400 * 10,))
-            db("""
-                INSERT INTO auth_cookie (cookie, name, ipnr, time)
-                     VALUES (%s, %s, %s, %s)
-               """, (cookie, remote_user, req.remote_addr, int(time.time())))
+            cookie = None
+            trac_auth = req.incookie.get('trac_auth')
+            if trac_auth is not None:
+                name = self._get_name_for_cookie(req, trac_auth)
+                cookie = trac_auth.value if name == remote_user else None
+            # Only insert a new cookie if we don't already have one
+            if cookie is None:
+                # Delete cookies older than 10 days
+                db("DELETE FROM auth_cookie WHERE time < %s",
+                   (int(time.time()) - 86400 * 10,))
+                cookie = hex_entropy()
+                db("""
+                    INSERT INTO auth_cookie (cookie, name, ipnr, time)
+                         VALUES (%s, %s, %s, %s)
+                   """, (cookie, remote_user, req.remote_addr,
+                         int(time.time())))
         req.authname = remote_user
         req.outcookie['trac_auth'] = cookie
         req.outcookie['trac_auth']['path'] = self.auth_cookie_path \
@@ -213,15 +226,13 @@ class LoginModule(Component):
             args = (cookie.value,)
         for name, in self.env.db_query(sql, args):
             return name
-        # The cookie is invalid (or has been purged from the database),
-        # so tell the user agent to drop it as it is invalid
-        self._expire_cookie(req)
 
     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
         if referer and referer.rstrip('/') == req.base_url.rstrip('/') \
diff --git a/trac/web/chrome.py b/trac/web/chrome.py
--- a/trac/web/chrome.py
+++ b/trac/web/chrome.py
@@ -189,6 +189,18 @@ def prevnext_nav(req, prev_label, next_l
                               class_=not next_link and 'missing' or None))
 
 
+def auth_link(req, link):
+    """Return an "authenticated" link to `link` for authenticated users.
+    
+    If the user is anonymous, returns `link` unchanged. For authenticated
+    users, returns a link to `/login` that redirects to `link` after
+    authentication.
+    """
+    if req.authname != 'anonymous':
+        return req.href.login(referer=link)
+    return link
+
+
 def _save_messages(req, url, permanent):
     """Save warnings and notices in case of redirect, so that they can
     be displayed after the redirect."""

