0
votes

I am trying to get OneLogin Saml authentication working on my live servers and am running into a problem with my AWS load balancer setup. I think the problem is that I have a classic load balancer which is listening on both port 80 and 443 with a AWS wildcard HTTPS certificate. The load balancer forwards both ports to port 80 on my servers and adds the HTTP_X_FORWARDED_PROTO headers.

When I use my normal dev server (not behind load balancer) the SAML authentication works fine. I am getting a proper response back. But when I push to live the SAML response returns an empty POST dictionary without RELAY STATE.

Any idea why the POST would be empty?

My setup is:

  • Python social auth with the SAML connector
  • Works fine on Dev server
  • When I use my live servers behind the firewall, the response is empty

I suspect it has something to do with my SSL certificate or my load balancer forwarding the 443 to the server on port 80 with the additional header. I tried fixing this by creating the auth request by analyzing the forwarded headers:

def _create_saml_auth(self, idp):
    """Get an instance of OneLogin_Saml2_Auth"""

    config = self.generate_saml_config(idp)
    request_info = {
        'https': 'on' if self.strategy.request_is_secure() else 'off',
        'http_host': self.strategy.request_host(),
        'script_name': self.strategy.request_path(),
        'server_port': self.strategy.request_port(),
        'get_data': self.strategy.request_get(),
        'post_data': self.strategy.request_post(),
    }

    if 'HTTP_X_FORWARDED_PROTO' in self.strategy.request.META:
        request_info['https'] = 'on' if self.strategy.request.META.get('HTTP_X_FORWARDED_PROTO') == 'https' else 'off'
        request_info['server_port'] = self.strategy.request.META.get('HTTP_X_FORWARDED_PORT')

But that still does return the empyy POST dictionary on the SAML response from Onelogin. The intial url is generated properly with HTTPS on though.

Has anyone had a similar issue. I am stuck and would love to get Onelogin to work.

Thanks so much for your time.

Cheers,

Phil

1

1 Answers

0
votes

You can check what's in the errors. i'm using code like this:

    auth = OneLogin_Saml2_Auth(saml_req, saml_settings)
    auth.process_response()

    if not auth.is_authenticated():
        error = auth.get_last_error_reason() # here's the error message

i'm guessing you are bumping into the same issue with the ELB that i was, which will go something like Authentication error: The response was received at http://... instead of https://...

The solution is either to perform a https->https redirect, or to make pysaml think it received the response on https. Here's how i did it (in this case in a django app, but should be easy enough to modify for other environments):

    saml_req = {
        'http_host': request.META['HTTP_HOST'],
        'server_port': request.META['SERVER_PORT'],
        'script_name': request.META['PATH_INFO'],
        'get_data': request.GET.copy(),
        'post_data': request.POST.copy()
    }

    if settings.SAML_FUDGE_HTTPS:  # made a settings flag so it can be toggled
        saml_req['https'] = True  # this one forces https in the check url
        saml_req['server_port'] = None  # this one removes the port number (80)

    auth = OneLogin_Saml2_Auth(saml_req, saml_settings)
    auth.process_response()

Update: as @smartin mentions in the comment - you might be able to sniff out HTTP_X_FORWARDED_FOR header and avoid creating a settings var