Awesome thanks Massimo- will test tonight

On Thu, Oct 4, 2012 at 4:13 PM, Massimo Di Pierro <
massimo.dipie...@gmail.com> wrote:

> OK. check trunk. Auth(db,secure=True).
>
>
> On Thursday, 4 October 2012 13:01:51 UTC-5, Yarin wrote:
>>
>> Yes exactly
>>
>> On Thursday, October 4, 2012 12:38:34 PM UTC-4, Massimo Di Pierro wrote:
>>>
>>> So... would replaing this in gluon.main.py
>>>
>>> is_https = env.wsgi_url_scheme in ['https', 'HTTPS'] or env.https=='on')
>>>
>>> with
>>>
>>> is_https = env.wsgi_url_scheme in ['https', 'HTTPS'] or env.https=='on'
>>> or request.env.http_x_**forwarded_proto in ['https', '**HTTPS']
>>>
>>> address the first issue?
>>>
>>> Massimo
>>>
>>> On Thursday, 4 October 2012 07:05:17 UTC-5, Yarin wrote:
>>>>
>>>> I'm revising my stance on this. After further digging around, I'm gonna
>>>> go with Niphlod's position that securing only the login traffic without
>>>> securing the entire session is for the most part pretty worthless. While
>>>> this might have value to some sites that have to deal with mixed content,
>>>> the complexity it introduces isn't worth it.
>>>>
>>>> I'm also taking back my recommendation that we need to have a setting
>>>> to explicitly allow SSL traffic. I think it's fine to just check the
>>>> headers for forwarded SSL traffic and trust that it is. Yes, headers can be
>>>> spoofed, but I can't think of how this could be exploited on the user end-
>>>>
>>>> So that leaves only *two recommended changes:*
>>>>
>>>>    - When checking whether HTTPS, check for forwarded SSL headers with
>>>>    if request.env.http_x_**forwarded_proto in ['https', '**HTTPS']:
>>>>    - Add a auth.secure = True convenience setting, which would call
>>>>    requires_https() while the user is logged in, and on all 
>>>> login/registration
>>>>    methods.
>>>>
>>>> I'll update the ticket
>>>>
>>>>
>>>>
>>>> On Friday, September 21, 2012 2:26:36 PM UTC-4, Yarin wrote:
>>>>>
>>>>> Done 
>>>>> http://code.google.com/p/**web2py/issues/detail?id=1023<http://code.google.com/p/web2py/issues/detail?id=1023>
>>>>>
>>>>> On Friday, September 21, 2012 2:05:41 PM UTC-4, Massimo Di Pierro
>>>>> wrote:
>>>>>>
>>>>>> Yarin, please open an issue on google code as suggested enhancement
>>>>>> so ti does not get lost. Also feel free to move the discussion on web2py
>>>>>> developers.
>>>>>>
>>>>>>
>>>>>> On Friday, 21 September 2012 12:22:57 UTC-5, Yarin wrote:
>>>>>>>
>>>>>>> Here's a complete example of our own implementation (simplified,
>>>>>>> untested) using the proposed auth settings:
>>>>>>>
>>>>>>> *In our model:*
>>>>>>>
>>>>>>> def force_https(trust_proxy = False, secure_session = False):
>>>>>>>     """ Enforces HTTPS in appropriate environments
>>>>>>>
>>>>>>>     Args:
>>>>>>>         trust_proxy: Can we trust proxy header
>>>>>>> 'http_x_forwarded_proto' to determine SSL.
>>>>>>>         (Set this only if ALL your traffic comes via trusted proxy.)
>>>>>>>         secure_session: Secure the session as well.
>>>>>>>         (Do this only when enforcing SSL throughout the session)
>>>>>>>     """
>>>>>>>
>>>>>>>     # If cronjob or scheduler, exit:
>>>>>>>     cronjob = request.global_settings.cronjo**b
>>>>>>>     cmd_options = request.global_settings.cmd_**options
>>>>>>>     if cronjob or (cmd_options and cmd_options.scheduler):
>>>>>>>         return
>>>>>>>
>>>>>>>     # If local host, exit:
>>>>>>>     if request.env.remote_addr == "127.0.0.1":
>>>>>>>         return
>>>>>>>
>>>>>>>     # If already HTTPS, exit:
>>>>>>>     if request.env.wsgi_url_scheme in ['https', 'HTTPS']:
>>>>>>>         if secure_session:
>>>>>>>             current.session.secure()
>>>>>>>         return
>>>>>>>
>>>>>>>     # If HTTPS request forwarded over HTTP via a SSL-terminating
>>>>>>> proxy, exit:
>>>>>>>     if trust_proxy and request.env.http_x_forwarded_**proto in [
>>>>>>> 'https', 'HTTPS']:
>>>>>>>         if secure_session:
>>>>>>>             current.session.secure()
>>>>>>>         return
>>>>>>>
>>>>>>>     # Redirect to HTTPS:
>>>>>>>     redirect(URL(scheme='https', args=request.args, vars=request.
>>>>>>> vars))
>>>>>>>
>>>>>>> # If a login function, force SSL:
>>>>>>> if request.controller == 'default' and request.function == 'user'
>>>>>>> and auth.settings.force_ssl_login:
>>>>>>>     force_https(trust_proxy = auth.settings.is_proxied, secu**re_session
>>>>>>> = auth.settings.force_ssl_**session)
>>>>>>> # If user is logged in and we're enforcing a full SSL session:
>>>>>>> elif auth.is_logged_in() and auth.settings.force_ssl_**session:
>>>>>>>     force_https(trust_proxy = auth.settings.is_proxied,secure_session
>>>>>>> = True)
>>>>>>>
>>>>>>> def on_login(form):
>>>>>>>     """ Post login redirection"""
>>>>>>>
>>>>>>>     # If we're enforcing SSL on login only, redirect from HTTPS to
>>>>>>> HTTP immediately after login:
>>>>>>>     if auth.settings.force_ssl_login is True and auth.settings.
>>>>>>> force_ssl_**session is False:
>>>>>>>         if request.env.wsgi_url_scheme in ['https', 'HTTPS'] orrequest
>>>>>>> .env.http_x_forwarded_**proto in ['https', 'HTTPS']:
>>>>>>>
>>>>>>>             # Extract the post-login url value from auth
>>>>>>>             # (hack - look at end of login() function in tools.py.
>>>>>>> This belongs in Auth itself.):
>>>>>>>             login_next_path = auth.next or auth.settings.login_next
>>>>>>>             # Build an absolute, HTTP url from it:
>>>>>>>             login_next_url = URL(scheme='http',c='default',**f=
>>>>>>> 'index') + login_next_path[1:]
>>>>>>>             # Redirect to the HTTP URL:
>>>>>>>             redirect(login_next_url)
>>>>>>>
>>>>>>> auth.settings.login_onaccept = on_login
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Friday, September 21, 2012 12:35:37 PM UTC-4, Yarin wrote:
>>>>>>>>
>>>>>>>> You can't detect this- it must be a setting. Please see my previous
>>>>>>>> answer:
>>>>>>>> https://groups.google.com/**forum/#!msg/web2py/**
>>>>>>>> me1e5d6Dudk/VQRQhdiryccJ<https://groups.google.com/forum/#!msg/web2py/me1e5d6Dudk/VQRQhdiryccJ>
>>>>>>>>
>>>>>>>> "you cannot detect whether proxied traffic is real because headers
>>>>>>>> are unreliable. Instead you must securely set up a server behind a 
>>>>>>>> proxy
>>>>>>>> and set the .is_proxied flag explicitly."
>>>>>>>>
>>>>>>>> "you can't mix direct and proxied traffic. To be able to handle
>>>>>>>> proxy-terminated SSL, we need to know that *all* the traffic is
>>>>>>>> via a trusted proxy."
>>>>>>>>
>>>>>>>>
>>>>>>>> On Friday, September 21, 2012 12:05:56 PM UTC-4, Massimo Di Pierro
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>> Yes but how do you detect if is_proxied reliably?
>>>>>>>>>
>>>>>>>>> On Friday, 21 September 2012 10:28:26 UTC-5, Yarin wrote:
>>>>>>>>>>
>>>>>>>>>> FYI this is the enforcer function we wrote for our
>>>>>>>>>> implementation- basically a rewrite of request.requires_https():
>>>>>>>>>>
>>>>>>>>>> def force_https(trust_proxy = False):
>>>>>>>>>>  """ Enforces HTTPS in appropriate environments
>>>>>>>>>>
>>>>>>>>>>  Args:
>>>>>>>>>>      trust_proxy: Can we trust proxy header
>>>>>>>>>> 'http_x_forwarded_proto' to determine SSL.
>>>>>>>>>>      (Set this only if ALL your traffic comes via trusted proxy.)
>>>>>>>>>>  """
>>>>>>>>>>
>>>>>>>>>>  # If cronjob or scheduler, exit:
>>>>>>>>>>  cronjob = request.global_**settings.cronjob
>>>>>>>>>>  cmd_options = request.global_**settings.cmd_options
>>>>>>>>>>  if cronjob or (cmd_options an**d cmd_options.scheduler):
>>>>>>>>>>      return
>>>>>>>>>>
>>>>>>>>>>  # If local host, exit:
>>>>>>>>>>  if request.env.remote_addr == "127.0.0.1":
>>>>>>>>>>      return
>>>>>>>>>>
>>>>>>>>>>  # If already HTTPS, exit:
>>>>>>>>>>  if request.env.wsgi_url_scheme in ['https', 'HTTPS']:
>>>>>>>>>>      return
>>>>>>>>>>
>>>>>>>>>>  # If HTTPS request forwarded over HTTP via SSL-terminating
>>>>>>>>>> proxy, exit:
>>>>>>>>>>  if trust_proxy and request.env.http_x_forwarded_**proto in [
>>>>>>>>>> 'https', 'HTTPS']:
>>>>>>>>>>      return
>>>>>>>>>>
>>>>>>>>>>  # Redirect to HTTPS:
>>>>>>>>>>  redirect(URL(scheme='https', args=request.args, vars=request.
>>>>>>>>>> vars))
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Friday, September 21, 2012 9:53:36 AM UTC-4, Yarin wrote:
>>>>>>>>>>>
>>>>>>>>>>> The completely naive approach would be to do:
>>>>>>>>>>>
>>>>>>>>>>> if request.env.http_x_forwarded_**for and \
>>>>>>>>>>>     request.env.http_x_forwarded_**proto in ['https', 'HTTPS']:
>>>>>>>>>>>      # Is HTTPS...
>>>>>>>>>>>
>>>>>>>>>>> But you cannot detect whether proxied traffic is real because
>>>>>>>>>>> headers are unreliable. Instead it is up to the user to securely 
>>>>>>>>>>> set up a
>>>>>>>>>>> server behind a proxy and set the .is_proxied flag themselves.
>>>>>>>>>>>
>>>>>>>>>>> *Example:*
>>>>>>>>>>> We put our app server behind an SSL-terminating load balancer on
>>>>>>>>>>> the cloud. The domain app.example.com points to the
>>>>>>>>>>> loadbalancer, so we configure app server's Apache to allow traffic 
>>>>>>>>>>> from
>>>>>>>>>>> that domain only, and block any outside direct traffic. Then we set
>>>>>>>>>>> *auth.settings.is_proxied* to tell web2py "this proxy traffic
>>>>>>>>>>> is legit"
>>>>>>>>>>>
>>>>>>>>>>> HTTPS/443 requests will hit the loadbalancer, and be transformed
>>>>>>>>>>> to HTTP/80 traffic with *http_x_forwarded_for* and *
>>>>>>>>>>> http_x_forwarded_proto* headers set. Now we can confidently
>>>>>>>>>>> check:
>>>>>>>>>>>
>>>>>>>>>>> if auth.settings.is_proxied and \
>>>>>>>>>>>     request.env.http_x_forwarded_**proto in ['https', 'HTTPS']:
>>>>>>>>>>>     # Is HTTPS...
>>>>>>>>>>>
>>>>>>>>>>> In other words *http_x_forwarded_for* header is useless and you
>>>>>>>>>>> can't mix direct and proxied traffic. To be able to handle 
>>>>>>>>>>> proxy-terminated
>>>>>>>>>>> SSL, we need to know that *all* the traffic is via a trusted
>>>>>>>>>>> proxy.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Friday, September 21, 2012 8:40:35 AM UTC-4, Massimo Di
>>>>>>>>>>> Pierro wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> Can you suggest a way to detect that?
>>>>>>>>>>>>
>>>>>>>>>>>> On Thursday, 20 September 2012 13:56:55 UTC-5, Yarin wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>> @Massimo - that'd be great.
>>>>>>>>>>>>>
>>>>>>>>>>>>> One more kink to throw in is recognizing proxied SSL calls.
>>>>>>>>>>>>> This requires knowing whether you can trust the traffic headers 
>>>>>>>>>>>>> (e.g.
>>>>>>>>>>>>> having apache locked down to all traffic except your load 
>>>>>>>>>>>>> balancer), so
>>>>>>>>>>>>> maybe we need a trust_proxied_ssl or is_proxied setting somewhere?
>>>>>>>>>>>>>
>>>>>>>>>>>>> if request.env.http_x_forwarded_**for and request.env.
>>>>>>>>>>>>> http_x_forwarded_**proto in ['https', 'HTTPS'] and auth.
>>>>>>>>>>>>> settings.is_proxied:
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Thursday, September 20, 2012 12:52:22 PM UTC-4, Massimo Di
>>>>>>>>>>>>> Pierro wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I think we should do something like this.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I think we should have auth.settings.force_ssl_login
>>>>>>>>>>>>>> and  auth.settings.force_ssl_**login.
>>>>>>>>>>>>>> We could add secure=True option to existing requires
>>>>>>>>>>>>>> validators.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> This should not be enforced from localhost.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On Thursday, 20 September 2012 09:07:14 UTC-5, Yarin wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> A proposal for improving SSL support in web2py
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> For authenticated web applications, there are two "grades"
>>>>>>>>>>>>>>> of SSL implementions: Forcing SSL on login, vs forcing SSL on 
>>>>>>>>>>>>>>> the entire
>>>>>>>>>>>>>>> authenticated session.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> In the first case, HTTPS is forced on login/registration,
>>>>>>>>>>>>>>> but reverts back to HTTP upon authentication. This protects 
>>>>>>>>>>>>>>> against
>>>>>>>>>>>>>>> passwords from being sent unencrypted, but won't prevent 
>>>>>>>>>>>>>>> session hijacking
>>>>>>>>>>>>>>> as the session cookie can still be compromised on subsequent 
>>>>>>>>>>>>>>> HTTP requests.
>>>>>>>>>>>>>>> (See Firesheep <http://codebutler.com/firesheep> for
>>>>>>>>>>>>>>> details). Nonetheless, many sites choose this approach for 
>>>>>>>>>>>>>>> performance
>>>>>>>>>>>>>>> reasons, as SSL-delivered content is not cached by browsers as 
>>>>>>>>>>>>>>> efficiently
>>>>>>>>>>>>>>> (discussed on 37signals 
>>>>>>>>>>>>>>> blog<http://37signals.com/svn/posts/1431-mixed-content-warning-how-i-loathe-thee>
>>>>>>>>>>>>>>> ).
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> In the second case, the entire authenticated session is
>>>>>>>>>>>>>>> secured by forcing all traffic to go over HTTPS while a user is 
>>>>>>>>>>>>>>> logged in
>>>>>>>>>>>>>>> *and* by securing the session cookie so that it will only
>>>>>>>>>>>>>>> be sent by the browser over HTTPS.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> (Also discussed in web2py users group - Auth over 
>>>>>>>>>>>>>>> SSL<https://groups.google.com/d/msg/web2py/7qoHMs-4Va8/jRFOqYHri4gJ>
>>>>>>>>>>>>>>> )
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> web2py should make it easier to deal with these scenarios. I
>>>>>>>>>>>>>>> just implemented a case-1 type solution and it took quite a bit 
>>>>>>>>>>>>>>> of work.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Moreover, web2py currently provides two SSL-control
>>>>>>>>>>>>>>> functions, which, taken on their own, can lead to problems for 
>>>>>>>>>>>>>>> the
>>>>>>>>>>>>>>> uninitiated:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>    - session.secure() will ensure that the session cookie
>>>>>>>>>>>>>>>    is only transmitted over HTTPS, but doesn't force HTTPS, so 
>>>>>>>>>>>>>>> that for any
>>>>>>>>>>>>>>>    subsequent session calls made over HTTP will simply not have 
>>>>>>>>>>>>>>> access to the
>>>>>>>>>>>>>>>    auth session, but this is not obvious (Correct me if I'm 
>>>>>>>>>>>>>>> wrong)
>>>>>>>>>>>>>>>    - request.requires_https() (undocumented?) is a
>>>>>>>>>>>>>>>    misnomer, because if forces HTTPS but then assumes a case-2
>>>>>>>>>>>>>>>    scenario and secures the session cookie
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> *Proposals:*
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>    - SSL auth settings
>>>>>>>>>>>>>>>       - auth.settings.force_ssl_login - Forces HTTPS for
>>>>>>>>>>>>>>>       login/registration
>>>>>>>>>>>>>>>       - auth.settings.force_ssl_**session - Forces HTTPS
>>>>>>>>>>>>>>>       throughout an authenticated session, and secure the 
>>>>>>>>>>>>>>> session cookie (If
>>>>>>>>>>>>>>>       True, force_ssl_login not necessary)
>>>>>>>>>>>>>>>    - Other more granular controls
>>>>>>>>>>>>>>>       - @requires_https() - decorator for controller
>>>>>>>>>>>>>>>       functions that forces HTTPS for that function only
>>>>>>>>>>>>>>>       - 'secure=True' option on forms ensures submission
>>>>>>>>>>>>>>>       over HTTPS
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>  --
>
>
>
>

-- 



Reply via email to