FinalsClub / karmaworld

KarmaNotes.org v3.0
GNU Affero General Public License v3.0
7 stars 6 forks source link

site forwards to example.com unyieldingly after login #320

Closed btbonval closed 10 years ago

btbonval commented 10 years ago

http://localhost:6659/admin/, once logged in, will forward to http://example.com/admin/.

Once I switched over to SSL: https://localhost:6659/admin/ forwards to https://example.com/admin/.

"example.com" doesn't actually appear to be written explicitly in the code, at least grep isn't finding it.

This wasn't a problem until this week.

Stackoverflow says some things. http://stackoverflow.com/questions/344851/django-admins-view-on-site-points-to-example-com-instead-of-my-domain#344909

btbonval commented 10 years ago

If I had to guess, this is the only recent change that plays around with the URL stuff: https://github.com/FinalsClub/karmaworld/blob/8ecc45d674be9b5957fb2774c637cb8d86342343/karmaworld/utils/SSLRedirect.py#L40

https://localhost:6659/ fowards to https://example.com/. https://localhost:6659/macomb-community-college/test-course-1/readmetxt forwards to https://example.com/macomb-community-college/test-course-1/readmetxt

So what is get_current_site(request) doing to somehow extract example.com? It doesn't seem obvious why Sites would be getting involved here :(

btbonval commented 10 years ago

The suggested fix from SO implies going to /admin/sites, but that too is forwarded to example.com. For now I can edit this in the database. I'll have to learn more about Django Sites to configure the VM properly on bootup, if that's where this is leading.

Btw, get_current_site calls Django Sites. I thought it parsed the info out of the request, but alas. https://docs.djangoproject.com/en/1.5/ref/contrib/sites/

btbonval commented 10 years ago

it'll still be very hard to automatically fix the VM or any staging/prod systems if we need to redeploy using this solution, but it's the best I've seen yet: http://stackoverflow.com/a/11420955/1867779 which links to http://codeinthehole.com/writing/a-data-migration-for-every-django-project/

btbonval commented 10 years ago

Btw, Django Sites by default sets example.com and (by the documentation) offers no way to fix that without cracking open the database or website. The link above using South for data migrations is a hack. We could potentially use it, but it isn't a portable hack.

btbonval commented 10 years ago

By hand fix:

karmaworld=> SELECT * FROM django_site;
 id |   domain    |    name     
----+-------------+-------------
  1 | example.com | example.com
(1 row)

karmaworld=> UPDATE django_site SET domain = 'localhost', name = 'localhost';
UPDATE 1
karmaworld=> SELECT * FROM django_site;
 id |  domain   |   name    
----+-----------+-----------
  1 | localhost | localhost
(1 row)

Didn't take effect even though it was in the database. Restarted supervisord, yet still somehow forwarding to example.com. Maybe a caching problem? Closed private browse window in FireFox, restart. Aha, there it goes.

Okay, now site https://localhost:6659/* forwards unyieldingly to https://localhost/*, so I still can't use the VM at all. The SSLRedirect would need to preserve the port, or else there needs to be a way to write it into Django Sites?

localhost:6659 is cool in the database? Nope. causes infinite redirect loop in my browser. Thanks Django Sites, stay classy.

btbonval commented 10 years ago

"But non-standard ports are pointless, just do what prod/staging are doing!" I am, on the Virtual Machine. If someone were to try doing dev work on some system they don't have root access, or such a devver is already running other sites on the standard ports beacuse he/she devs multiple sites, then non-standard ports are a great answer. That's ignoring the VM forwarded port issue, in case one were to try arguing that the VM isn't worth using.

Just trying to nip that whole argument before it happens. Non-standard ports: helping webdev since 1994.

charlesconnell commented 10 years ago

I found that putting localhost:8000 in my database worked well for me. Clear your cache after testing the redirect stuff, because Firefox will remember the permanent redirect that we're giving it. That's probably the cause of your loop.

btbonval commented 10 years ago

@charlesconnell What's your django_site look like?

I did clear the cache and try again multiple times.

After sleeping on the problem, I wonder why we always redirect. If I'm already HTTPS, why would we redirect to HTTPS? We should be able to extract the current state and compare it to the desired state, and only forward if we desire HTTPS but the client is trying HTTP.

btbonval commented 10 years ago

322 made to cover failure to distinguish between HTTP(S) in my environment. Ideally, fixing that will prevent Django from forwarding every single time, which will be enough of a workaround to close this ticket.

btbonval commented 10 years ago

Problem was completely solved by #322

btbonval commented 10 years ago

Hrm, now HTTPS is forwarding unconditionally to example.com even if I'm not logged in. This is why I nuke the VM and rebuild it: some problems that look solved just aren't when you try it fresh.

btbonval commented 10 years ago

Logged out (secure == False), but request is secure (self._is_secure(request) == True), should be fine, but current logic redirects.

> /home/vagrant/karmaworld/karmaworld/utils/SSLRedirect.py(27)process_view()
-> if not secure == self._is_secure(request):
(Pdb) secure
False
(Pdb) self._is_secure(request)
True
(Pdb) list
 27  ->         if not secure == self._is_secure(request):
 28                 return self._redirect(request, secure)

So let's see, secure should be thought of as "connection requires security" while self._is_secure(request) should be thought of "connection already has security." We only need to forward if the connection does not have security, but requires it:

if not self._is_secure(request) and secure:
    return self._redirect(request, secure)
btbonval commented 10 years ago

That logic helped.

Logging in gives CSRF failure if I try to login to /admin/ with HTTPS. However, I can log into /admin/ with HTTP (probably a bad idea, plaintext password) and then I'm forwarded to HTTPS. Now I'm logged in with HTTPS.

Above logic fix is in the pipe works, this ticket will close when I commit it.

After everything is written and tested, if that /admin/ page is still giving CSRF login, it'll need its own ticket.