2

I would like to allow the user to be "logged in" and maintain state / logged in status between pages within an iframe. The iframe content is ours, and will be hosted on various clients' websites.

Since the usual session cookie will most likely be blocked as a third party cookie I am trying to find a suitable way to do this.

I am considering always passing ?PHPSESSID=x in the query string for each relevant url as a workaround.

Is this considered bad practice and are there any risks involved?

  • Yes, it's bad practice. Regardless, the cookie shouldn't be blocked as 3rd party, unless the user has a very overzealous privacy plugin. Your cookie should just get set and sent under the standard same origin policy for your domain. – Polynomial Dec 1 '14 at 14:09
  • 1
    I'm a bit curious how you are able to set ?PHPSESSID=x from a client website (that you don't own right?). – Gudradain Dec 1 '14 at 15:17
  • This is not how SSO should work, use OAuth. – rook Dec 1 '14 at 16:38
  • @Gudradain It's my understanding that I can send the PHPSESSID (for iframe domain/server) by including it in the urls of the links used within my iframe-contained application (ie. yourdomain.com/member-profile.php?PHPSESSID=XYZ123) – Marc Dec 1 '14 at 17:22
  • @Marc Yes you can include it in the URL IF you know it. But, you said that the iframe will be displayed on client websites, hence it is the client website that need to know the SESSION ID. I suppose that client website are not own by you. Then why, would a website that you don't own know the session id from your website? That sounds very insecure to me. – Gudradain Dec 1 '14 at 18:36
1

I am considering always passing ?PHPSESSID=x in the query string for each relevant url as a workaround.

This is not the best practice, but if you decide to choose this method (because it is easy), you can make something like this:

<?php

    define("COOKIE_NAME", "PHPSESSID");
    define("DOMAIN", "example.com");

    function is_valid_cookie($cookie){
        //Test if the cookie is valid and does not have any malicious chars (";", etc)

        //...
        return true;

        //...
        return false;
    }

    function is_logged_in(){
        //Test if the user is logged in

        //...
        return true;

        //...
        return false;
    }

    function sanitize_url($url){
        //Sanitize URL
        //If you have PHP >= 4.4.2 or PHP >= 5.1.2, I believe you have nothing to worry here

        //...
        return $url;
    }


    function remove_querystring_var($url, $toRemove){
        //Removes $toRemove from query string of the $url
        $parsed = array();
        parse_str(substr($url, strpos($url, '?')+1), $parsed);
        $url = substr($url, 0, strpos($url, '?'));
        unset($parsed[$toRemove]);
        if(!empty($parsed)){
            $url .= '?' . http_build_query($parsed);
        }
        return $url;
    }

    if(isset($_GET[COOKIE_NAME])){
        if(is_valid_cookie($_GET[COOKIE_NAME])){
            setcookie(COOKIE_NAME, $_GET[COOKIE_NAME], time()+24*3600, "/", ".".DOMAIN, true, true);
            header("Location: ".sanitize_url(remove_querystring_var("https://".DOMAIN.$_SERVER["REQUEST_URI"], COOKIE_NAME)));
            exit(0);
        }
        else{
            header("Location: ".sanitize_url(remove_querystring_var("https://".DOMAIN.$_SERVER["REQUEST_URI"], COOKIE_NAME)));
            exit(0);
        }
    }
    else if(!is_logged_in()){
        echo "Invalid session!";
        exit(0);
    }

    //...
    echo "Welcome!";

?>

Example:

https://mail.google.com/mail/u/0/?auth=xxxxx&anything=yyyyy

Google will use and exclude the &auth variable, but will keep the &anything, because &auth have sensitive data for Google.

1

Have a look how other solve this. For example Facebook has the same problem because it includes his apps as iframes.

In the current sdk they implement an oauth but the older version is much simpler. Basically it comes down to this:

$data['issued_at'] = time();
$json = json_encode($data);
$b64 = self::base64UrlEncode($json);
$signature = hash_hmac('sha256', $b64, $this->getAppSecret(), true);

They have an array with the data like your session token. They sign this data with a secret password so it can't be changed by anyone. A timestamp is added to deny replay attacks. Now you transfer the data $b64 and the $signature to the other webpage. On the other side you verify the signature still match the data.

Full oauth is probably better but a little bit more work.

  • Very interesting. I'll take a look at that. Thanks. – Marc Jan 13 '15 at 11:12
0

It's bad practice. Whenever you can, reuse what already exist instead of creating your own. Session management is pretty common and just work.

Since the usual session cookie will most likely be blocked as a third party cookie I am trying to find a suitable way to do this.

No, the cookie will not be blocked in your iframe. Cookie are set browser wide and the same origin policy apply to them. That's why no matter if you open the page in a new tab, new window or new iframe, the cookie will still be sent.

I am considering always passing ?PHPSESSID=x in the query string for each relevant url as a workaround.

This answer contains some good information about that practice. It is not automatically insecure if you use HTTPS and a long enough random Session ID. But it might cause problem if people start sharing url between each other, for example, since the URL contains information about your session.

  • Unfortunately my my iframe domain is NOT the same as the main website domain. The contents of the iframe will be one one domain, the main website(s) will be a completely different domain(s) – Marc Dec 1 '14 at 14:56
  • @Marc If the user has a cookie for the domain of your iframe then the cookie will be loaded when you call load the iframe. – Gudradain Dec 1 '14 at 15:10
  • @Gudradain how exactly could I do this? My domain www.example.com is hosting iframe in www.example2.com but there is no session in example2. The user has session in www.example.com ... – Fane Oct 25 '15 at 18:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.