mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-04-27 03:00:12 -04:00
Redirect through HSTS granting / revoking endpoint on base domain
Since grants / revokes only happen on the base domain for simplicity, we need to redirect through an endpoint on the base domain whenever we perform an action that might change a user's HSTS eligibility.
This commit is contained in:
committed by
Neil Williams
parent
b70556a3ab
commit
7a4fa77a23
@@ -322,6 +322,8 @@ def make_map():
|
||||
mc('/resetpassword', controller='forms',
|
||||
action='resetpassword')
|
||||
|
||||
mc('/modify_hsts_grant', controller='front', action='modify_hsts_grant')
|
||||
|
||||
mc('/post/:action/:url_user', controller='post',
|
||||
requirements=dict(action="login|reg"))
|
||||
mc('/post/:action', controller='post',
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
from r2.controllers.reddit_base import (
|
||||
cross_domain,
|
||||
hsts_modify_redirect,
|
||||
MinimalController,
|
||||
pagecache_policy,
|
||||
PAGECACHE_POLICY,
|
||||
@@ -521,6 +522,13 @@ class ApiController(RedditController):
|
||||
if request.params.get("hoist") != "cookie":
|
||||
responder._send_data(modhash = user.modhash())
|
||||
responder._send_data(cookie = user.make_cookie())
|
||||
if user.pref_force_https:
|
||||
# The client may decide to redirect somewhere after a successful
|
||||
# login, send it our HSTS grant endpoint so it can redirect through
|
||||
# there and pick up the user's grant.
|
||||
hsts_redir = "https://" + g.domain + "/modify_hsts_grant?dest="
|
||||
responder._send_data(hsts_redir=hsts_redir)
|
||||
responder._send_data(need_https=user.pref_force_https)
|
||||
|
||||
@validatedForm(VLoggedOut(),
|
||||
user = VThrottledLogin(['user', 'passwd']),
|
||||
@@ -1213,8 +1221,11 @@ class ApiController(RedditController):
|
||||
form.has_errors("passwd", errors.WRONG_PASSWORD) or
|
||||
form.has_errors("delete_message", errors.TOO_LONG) or
|
||||
form.has_errors("confirm", errors.CONFIRM)):
|
||||
redirect_url = "/?deleted=true"
|
||||
if c.user.pref_force_https:
|
||||
redirect_url = hsts_modify_redirect(redirect_url)
|
||||
c.user.delete(delete_message)
|
||||
form.redirect("/?deleted=true")
|
||||
form.redirect(redirect_url)
|
||||
|
||||
@require_oauth2_scope("edit")
|
||||
@noresponse(VUser(),
|
||||
|
||||
@@ -23,11 +23,14 @@
|
||||
from pylons.i18n import _, ungettext
|
||||
from r2.controllers.reddit_base import (
|
||||
base_listing,
|
||||
disable_subreddit_css,
|
||||
hsts_modify_redirect,
|
||||
hsts_eligible,
|
||||
pagecache_policy,
|
||||
PAGECACHE_POLICY,
|
||||
paginated_listing,
|
||||
disable_subreddit_css,
|
||||
RedditController,
|
||||
require_https,
|
||||
)
|
||||
from r2 import config
|
||||
from r2.models import *
|
||||
@@ -54,7 +57,7 @@ from r2.lib.validator import *
|
||||
from r2.lib import jsontemplates
|
||||
from r2.lib import sup
|
||||
import r2.lib.db.thing as thing
|
||||
from r2.lib.errors import errors
|
||||
from r2.lib.errors import errors, ForbiddenError
|
||||
from listingcontroller import ListingController
|
||||
from oauth2 import require_oauth2_scope
|
||||
from api_docs import api_doc, api_section
|
||||
@@ -1256,6 +1259,19 @@ class FrontController(RedditController):
|
||||
page_classes=["gold-page", "gilding"],
|
||||
).render()
|
||||
|
||||
@validate(dest=VDestination(default='/'))
|
||||
def _modify_hsts_grant(self, dest):
|
||||
"""Endpoint subdomains can redirect through to update HSTS grants."""
|
||||
require_https()
|
||||
if request.host != g.domain:
|
||||
abort(ForbiddenError(errors.WRONG_DOMAIN))
|
||||
self.redirect(dest, code=307)
|
||||
|
||||
POST_modify_hsts_grant = _modify_hsts_grant
|
||||
GET_modify_hsts_grant = _modify_hsts_grant
|
||||
DELETE_modify_hsts_grant = _modify_hsts_grant
|
||||
PUT_modify_hsts_grant = _modify_hsts_grant
|
||||
|
||||
|
||||
class FormsController(RedditController):
|
||||
|
||||
@@ -1397,6 +1413,8 @@ class FormsController(RedditController):
|
||||
dest=VDestination())
|
||||
def POST_logout(self, dest):
|
||||
"""wipe login cookie and redirect to referer."""
|
||||
if hsts_eligible():
|
||||
dest = hsts_modify_redirect(dest)
|
||||
self.logout()
|
||||
return self.redirect(dest)
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
from r2.lib.pages import *
|
||||
from reddit_base import (
|
||||
change_user_cookie_security,
|
||||
delete_force_https_cookie,
|
||||
set_force_https_cookie,
|
||||
hsts_modify_redirect,
|
||||
hsts_eligible,
|
||||
)
|
||||
from api import ApiController
|
||||
from r2.lib.errors import BadRequestError, errors
|
||||
@@ -70,7 +70,10 @@ class PostController(ApiController):
|
||||
u.update_query(done = 'true')
|
||||
if c.cname:
|
||||
u.put_in_frame()
|
||||
return self.redirect(u.unparse())
|
||||
redirect_url = u.unparse()
|
||||
if new_https_pref:
|
||||
redirect_url = hsts_modify_redirect(u)
|
||||
return self.redirect(redirect_url)
|
||||
|
||||
def GET_over18(self):
|
||||
return BoringPage(_("over 18?"),
|
||||
@@ -122,6 +125,8 @@ class PostController(ApiController):
|
||||
return LoginPage(user_login = request.POST.get('user'),
|
||||
dest = dest).render()
|
||||
|
||||
if hsts_eligible():
|
||||
dest = hsts_modify_redirect(dest)
|
||||
return self.redirect(dest)
|
||||
|
||||
@validate(dest = VDestination(default = "/"))
|
||||
@@ -134,6 +139,8 @@ class PostController(ApiController):
|
||||
return LoginPage(user_reg = request.POST.get('user'),
|
||||
dest = dest).render()
|
||||
|
||||
if hsts_eligible():
|
||||
dest = hsts_modify_redirect(dest)
|
||||
return self.redirect(dest)
|
||||
|
||||
def GET_login(self, *a, **kw):
|
||||
|
||||
@@ -124,8 +124,12 @@ r.login.ui = {
|
||||
}
|
||||
}
|
||||
|
||||
this.popup.showLogin(true, dest && $.proxy(function() {
|
||||
this.popup.showLogin(true, dest && $.proxy(function(result) {
|
||||
this.popup.loginForm.$el.addClass('working')
|
||||
var hsts_redir = result.json.data.hsts_redir
|
||||
if(hsts_redir) {
|
||||
dest = hsts_redir + encodeURIComponent(dest)
|
||||
}
|
||||
window.location = dest
|
||||
}, this))
|
||||
|
||||
@@ -176,8 +180,15 @@ r.ui.LoginForm.prototype = $.extend(new r.ui.Form(), {
|
||||
this.$el.addClass('working')
|
||||
var base = r.config.extension ? '/.'+r.config.extension : '/',
|
||||
defaultDest = /\/login\/?$/.test($.url().attr('path')) ? base : window.location,
|
||||
destParam = this.$el.find('input[name="dest"]').val()
|
||||
window.location = destParam || defaultDest
|
||||
destParam = this.$el.find('input[name="dest"]').val(),
|
||||
hsts_redir = result.json.data.hsts_redir
|
||||
var redir = destParam || defaultDest
|
||||
// We might need to redirect through the base domain to grab
|
||||
// our HSTS grant.
|
||||
if (hsts_redir) {
|
||||
redir = hsts_redir + encodeURIComponent(redir)
|
||||
}
|
||||
window.location = redir
|
||||
}
|
||||
} else {
|
||||
r.ui.Form.prototype._handleResult.call(this, result)
|
||||
|
||||
Reference in New Issue
Block a user