Solved

How to delete cookie across a domain ...

Posted on 2014-01-29
20
340 Views
Last Modified: 2014-01-30
Hey all.

I need to delete a cookie for all sub-domains of a base domain.

Example, if my site is www.mysite.com, I have a  cookie being created that is available for xxx.mysite.com, yyy.mysite.com etc.

I need to be able to delete the cookie on xxx.mysite.com and have it deleted from yyy.mysite.com.

I've tried the following but it doesn't appear to work.

document.cookie = 'cookie_name=; domain=.mysite.com; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
0
Comment
Question by:Webspeeder
  • 6
  • 5
  • 3
  • +3
20 Comments
 
LVL 58

Expert Comment

by:Gary
Comment Utility
You cannot delete a cookie that does not belong to the currently accessed domain. i.e.
www.mysite.com is blocked from doing anything with a cookie set from xxx.mysite.com and vice versa

If you set a cookie from mysite.com (no www) then it is available to all domains.
0
 
LVL 82

Expert Comment

by:Dave Baldwin
Comment Utility
Sorry, that's backwards.  ".mysite.com" is supposed to be available on all subdomains.  http://en.wikipedia.org/wiki/HTTP_cookie#Cookie_attributes
0
 
LVL 58

Expert Comment

by:Gary
Comment Utility
Talking to me Dave? Yes, a mistake there
If you set a cookie from .mysite.com (no www) then it is available to all subdomains.
0
 
LVL 82

Expert Comment

by:Dave Baldwin
Comment Utility
Just checking.  I only have one site with subdomains and I haven't written anything to check the question.  Maybe later if a definitive answer to the original question isn't posted.
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
I don't know the answer if you set the cookie in JavaScript, and I do not recommend setting cookies in JavaScript because they are one of the "smells" of a manipulative site that is trying to get the client browser to do something unwanted.

Here is how to set a cookie in PHP.  To make the cookie go away, follow this same process with an expiration date in the past.

Note that if you're talking about one of those domains like example.co.uk you may need some adjustments in lines 48-60.

<?php // RAY_cookie_example.php
error_reporting(E_ALL);

// RECEIVE FORM INPUT AND SET A COOKIE WITH THE NAME, VALUE AND LIFE FROM THE FORM
// MAN PAGE: http://php.net/manual/en/function.setcookie.php
// TO SEE COOKIES IN FIREFOX, FOLLOW SOMETHING LIKE TOOLS => OPTIONS => PRIVACY => SHOW COOKIES (OR "REMOVE INDIVIDUAL")


// REQUIRED AT PHP 5+
date_default_timezone_set('America/New_York');


// IF THE FORM HAS BEEN POSTED
if (!empty($_POST))
{
    // TIDY UP THE POST INPUT - CLEAN AND NOT MORE THAN 16 BYTES
    $name = substr(clean_string($_POST["name"]),0,16);
    $data = substr(clean_string($_POST["data"]),0,16);
    $life = clean_number($_POST["life"]);

    // BE SURE WE HAVE USEFUL INFORMATION
    if ( ($name == '') || ($data == '') ) die("MISSING INPUT: PLEASE <a href=\"{$_SERVER['PHP_SELF']}\">TRY AGAIN</a>");


    // CHOOSE THE COOKIE NAME, VALUE, AND LIFE IN SECONDS
    $cookie_name    = $name;
    $cookie_value   = $data;
    $cookie_life    = $life;


    // CONFIGURE THE COOKIE LIFE
    if ($life == 0)
    {
        // USE THIS TO MAKE COOKIE EXPIRE AT END OF BROWSER LIFE
        $cookie_expires = 0;
    }
    else
    {
        // USE THIS TO MAKE A PERSISTENT COOKIE
        $cookie_expires = time() + $cookie_life;
    }


    // MAKE THE COOKIE AVAILABLE TO ALL DIRECTORY PATHS
    $cookie_path	= DIRECTORY_SEPARATOR;


    // MAKE THE COOKIE AVAILABLE TO ALL SUBDOMAINS - DOMAIN NAME STARTS WITH DOT AND OMITS WWW (OR OTHER SUBDOMAINS).
    $x = explode('.', strtolower($_SERVER["HTTP_HOST"]));
    $y = count($x);
    if ($y == 1) // MAYBE 'localhost'?
    {
        $cookie_domain = $x[0];
    }
    else // SOMETHING LIKE 'www2.atf70.whitehouse.gov'?
    {
        // USE THE LAST TWO POSITIONS TO MAKE THE HOST DOMAIN
        $cookie_domain = '.' . $x[$y-2] . '.' . $x[$y-1];
    }


    // MAKE THE COOKIE AVAILABLE TO HTTP, NOT JUST HTTPS
    $cookie_secure    = FALSE;


    // HIDE COOKIE FROM JAVASCRIPT (PHP 5.2+)
    $cookie_http      = TRUE;


    // SET THE COOKIE
    if ( setcookie
         ( $cookie_name
         , $cookie_value
         , $cookie_expires
         , $cookie_path
         , $cookie_domain
         , $cookie_secure
         , $cookie_http
         )
       )
    {
        echo PHP_EOL . "<br/>SUCCESS!  THE COOKIE HAS BEEN SET AND WILL BE AVAILABLE TO THE NEXT PAGE LOAD";
    }
    else
    {
        echo PHP_EOL . "<br/>FAILURE!  THE COOKIE WAS NOT SET AS EXPECTED";
    }


    // AT THIS POINT, THE COOKIE HAS BEEN SET, BUT IT IS NOT AVAILABLE IN THIS SCRIPT
    // THE COOKIE WILL NOT BE RETURNED FROM THE CLIENT TO THE SERVER UNTIL THE NEXT HTTP REQUEST
    // THIS IS BECAUSE THE BROWSER SENDS THE COOKIE TO OUR SCRIPT BEFORE OUR SCRIPT STARTS RUNNING
    echo '<pre>';
    echo PHP_EOL . '$_COOKIE CONTAINS '; var_dump($_COOKIE);
    echo PHP_EOL . '$_POST CONTAINS ';   var_dump($_POST);
    echo PHP_EOL . 'THE COOKIE HAS BEEN SET WITH THESE VALUES: ';
    echo PHP_EOL . 'COOKIE NAME:    ' . $cookie_name;
    echo PHP_EOL . 'COOKIE VALUE:   ' . $cookie_value;
    echo PHP_EOL . 'COOKIE EXPIRES: ' . number_format($cookie_expires) . " == " . date('r', $cookie_expires);
    echo PHP_EOL . 'COOKIE PATH:    ' . $cookie_path;
    echo PHP_EOL . 'COOKIE DOMAIN:  ' . $cookie_domain;
    echo PHP_EOL . 'COOKIE SECURE:  '; var_dump($cookie_secure);
    echo           'COOKIE HTTP:    '; var_dump($cookie_http);
    echo "</pre>";
}


// END OF SETTING THE COOKIE - CREATE THE FORM IN HEREDOC NOTATION
$self = $_SERVER["PHP_SELF"];
$form = <<<FORM
<pre>
<form method="post">
COOKIE NAME: <input name="name" /> STRING
COOKIE DATA: <input name="data" /> STRING
COOKIE LIFE: <input name="life" /> INTEGER SECONDS
<input type="submit" />
<b>TO SEE THE EXISTING COOKIES <a href="$self">CLICK HERE</a></b>
</form>
</pre>
FORM;
echo $form;


// SHOW THE COOKIE ARRAY, IF ANY
echo '<pre>$_COOKIE CONTAINS '; var_dump($_COOKIE); echo "</pre>";



// UNRELATED FUNCTIONS TO TIDY UP FORM INPUT
function clean_string($string)
{
    return trim(preg_replace('/[^A-Z0-9_]/i', NULL, $string));
}

function clean_number($string)
{
    return trim(preg_replace('/[^0-9]/i',     0,    $string));
}

Open in new window

HTH, ~Ray
0
 
LVL 58

Expert Comment

by:Gary
Comment Utility
Ahh maybe I misunderstood, thought he was setting the cookie at a sub domain level name not site wide.
0
 

Author Comment

by:Webspeeder
Comment Utility
The cookies are set using .mysite.com. Setting the cookies is good, setting it with .mysite.com, I have access from xxx.mysite.com and yyy.mysite.com.

I need to be able to delete them all from one sub-domain.
0
 

Author Comment

by:Webspeeder
Comment Utility
The cookie is set in PHP or via Confluence, both cookies use CROWD for authentication and they are set to httpOnly so Javascript can't read them.
0
 

Author Comment

by:Webspeeder
Comment Utility
Ray,

I tried expiring the cookie with this line of code, but it doesn't appear to work. Do i have it wrong or will it not work across all the sub-domains to begin with?

document.cookie = 'cookie_name=; domain=.mysite.com; expires=Thu, 01 Jan 1970 00:00:01 GMT;';

I thought setting the "domain=" parameter would be the key.
0
 
LVL 82

Expert Comment

by:leakim971
Comment Utility
1) maybenotyoursite.hosting.com
2) yoursite1.hosting.com
3) yoursite2.hosting.com

you say you want to delete all cookies of hosting.com but from 1,2 or 3 ? no way...
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 

Author Comment

by:Webspeeder
Comment Utility
I can set the cookie for all the sub-domains, so you're saying I can't delete that same cookie from all the sub-domains at once?
0
 

Author Comment

by:Webspeeder
Comment Utility
not all cookies, a cookie with a particular name that is located on all sub-domains.
0
 
LVL 82

Accepted Solution

by:
Dave Baldwin earned 500 total points
Comment Utility
"document.cookie" is javascript, not PHP.  You 'expire' a cookie by setting the exact same cookie with a date that is already past.  Which means that you 'expire' it in exactly the same way as you set it.
0
 
LVL 34

Expert Comment

by:gr8gonzo
Comment Utility
If you have a PHP page on all subdomains that simply deletes the cookie for that subdomain, then you can use JavaScript to dynamically create hidden frames and make the browser load those pages.
0
 
LVL 34

Expert Comment

by:gr8gonzo
Comment Utility
IFrames. Sorry, I gotta stop responding to questions via my phone.
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
The client side of the operation is JavaScript.  The server side is PHP.  For a variety of reasons that are too deep to go into in a Q&A forum like EE, these different sides interact in ways that produce security exposures.  Some of the background is available in this article:
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/A_11271-Understanding-Client-Server-Protocols-and-Web-Applications.html

You need to choose whether you will set and reset cookies in JavaScript OR PHP, but please do not try to make your choice work across the protocol boundaries.  You will be fighting an uphill battle.  Just pick one, and design your application layers so you can change quickly if the effect is not what you want.
0
 
LVL 82

Expert Comment

by:Dave Baldwin
Comment Utility
I tried Ray's code above to demo that it would work on subdomains to set and delete cookies.  Except I ran into a couple of problems.  'number_format' didn't work for me and I think it's because it returns a float.  And the 'clean_number()' didn't work because it was stripping off minus signs.  Here's a modified version that does allow you to set negative lifetimes to set and delete cookies on subdomains.
<?php // RAY_cookie_example.php
error_reporting(E_ALL);

// RECEIVE FORM INPUT AND SET A COOKIE WITH THE NAME, VALUE AND LIFE FROM THE FORM
// MAN PAGE: http://php.net/manual/en/function.setcookie.php
// TO SEE COOKIES IN FIREFOX, FOLLOW SOMETHING LIKE TOOLS => OPTIONS => PRIVACY => SHOW COOKIES (OR "REMOVE INDIVIDUAL")


// REQUIRED AT PHP 5+
date_default_timezone_set('America/Los_Angeles');


// IF THE FORM HAS BEEN POSTED
if (!empty($_POST))
{
    // TIDY UP THE POST INPUT - CLEAN AND NOT MORE THAN 16 BYTES
    $name = substr(clean_string($_POST["name"]),0,16);
    $data = substr(clean_string($_POST["data"]),0,16);
    $life = clean_number($_POST["life"]);
    //$life = $_POST["life"];

    // BE SURE WE HAVE USEFUL INFORMATION
    if ( ($name == '') || ($data == '') ) die("MISSING INPUT: PLEASE <a href=\"{$_SERVER['PHP_SELF']}\">TRY AGAIN</a>");


    // CHOOSE THE COOKIE NAME, VALUE, AND LIFE IN SECONDS
    $cookie_name    = $name;
    $cookie_value   = $data;
    $cookie_life    = $life;


    // CONFIGURE THE COOKIE LIFE
    if ($life == 0)
    {
        // USE THIS TO MAKE COOKIE EXPIRE AT END OF BROWSER LIFE
        $cookie_expires = 0;
    }
    else
    {
        // USE THIS TO MAKE A PERSISTENT COOKIE
        $cookie_expires = time() + $cookie_life;
    }


    // MAKE THE COOKIE AVAILABLE TO ALL DIRECTORY PATHS
    $cookie_path	= DIRECTORY_SEPARATOR;


    // MAKE THE COOKIE AVAILABLE TO ALL SUBDOMAINS - DOMAIN NAME STARTS WITH DOT AND OMITS WWW (OR OTHER SUBDOMAINS).
    $x = explode('.', strtolower($_SERVER["HTTP_HOST"]));
    $y = count($x);
    if ($y == 1) // MAYBE 'localhost'?
    {
        $cookie_domain = $x[0];
    }
    else // SOMETHING LIKE 'www2.atf70.whitehouse.gov'?
    {
        // USE THE LAST TWO POSITIONS TO MAKE THE HOST DOMAIN
        $cookie_domain = '.' . $x[$y-2] . '.' . $x[$y-1];
    }


    // MAKE THE COOKIE AVAILABLE TO HTTP, NOT JUST HTTPS
    $cookie_secure    = FALSE;


    // HIDE COOKIE FROM JAVASCRIPT (PHP 5.2+)
    $cookie_http      = TRUE;


    // SET THE COOKIE
    if ( setcookie
         ( $cookie_name
         , $cookie_value
         , $cookie_expires
         , $cookie_path
         , $cookie_domain
         , $cookie_secure
         , $cookie_http
         )
       )
    {
        echo PHP_EOL . "<br/>SUCCESS!  THE COOKIE HAS BEEN SET AND WILL BE AVAILABLE TO THE NEXT PAGE LOAD";
    }
    else
    {
        echo PHP_EOL . "<br/>FAILURE!  THE COOKIE WAS NOT SET AS EXPECTED";
    }


    // AT THIS POINT, THE COOKIE HAS BEEN SET, BUT IT IS NOT AVAILABLE IN THIS SCRIPT
    // THE COOKIE WILL NOT BE RETURNED FROM THE CLIENT TO THE SERVER UNTIL THE NEXT HTTP REQUEST
    // THIS IS BECAUSE THE BROWSER SENDS THE COOKIE TO OUR SCRIPT BEFORE OUR SCRIPT STARTS RUNNING
    echo '<pre>';
    echo PHP_EOL . '$_COOKIE CONTAINS '; var_dump($_COOKIE);
    echo PHP_EOL . '$_POST CONTAINS ';   var_dump($_POST);
    echo PHP_EOL . 'THE COOKIE HAS BEEN SET WITH THESE VALUES: ';
    echo PHP_EOL . 'COOKIE NAME:    ' . $cookie_name;
    echo PHP_EOL . 'COOKIE VALUE:   ' . $cookie_value;
    // echo PHP_EOL . 'COOKIE EXPIRES: ' . number_format($cookie_expires) . " == " . date('r', $cookie_expires);
    echo PHP_EOL . 'COOKIE EXPIRES: ' . $cookie_expires . " == " . date('r', $cookie_expires);
    echo PHP_EOL . 'COOKIE PATH:    ' . $cookie_path;
    echo PHP_EOL . 'COOKIE DOMAIN:  ' . $cookie_domain;
    echo PHP_EOL . 'COOKIE SECURE:  '; var_dump($cookie_secure);
    echo           'COOKIE HTTP:    '; var_dump($cookie_http);
    echo "</pre>";
}


// END OF SETTING THE COOKIE - CREATE THE FORM IN HEREDOC NOTATION
$self = $_SERVER["PHP_SELF"];
$form = <<<FORM
<pre>
<form method="post">
COOKIE NAME: <input name="name" /> STRING
COOKIE DATA: <input name="data" /> STRING
COOKIE LIFE: <input name="life" /> INTEGER SECONDS
<input type="submit" />
<b>TO SEE THE EXISTING COOKIES <a href="$self">CLICK HERE</a></b>
</form>
</pre>
FORM;
echo $form;


// SHOW THE COOKIE ARRAY, IF ANY
echo '<pre>$_COOKIE CONTAINS '; var_dump($_COOKIE); echo "</pre>";



// UNRELATED FUNCTIONS TO TIDY UP FORM INPUT
function clean_string($string)
{
    return trim(preg_replace('/[^A-Z0-9_]/i', NULL, $string));
}

function clean_number($string)
{
    return trim(preg_replace('/[^0-9]-/i',     0,    $string));
}

Open in new window

0
 

Author Closing Comment

by:Webspeeder
Comment Utility
"Expiring the same way it is created" is what led me to come up with a solution.

I was creating the cookie with PHP but trying to expire it with Javascript. Instead, I am running a PHP file to expire it and it works.

Here is the core of the PHP code for documentation purposes.

if (!empty($_COOKIE['cookie_name']))
{
      setcookie('cookie_name', '', time()-10, '/', '.mysite',false,true);
}

Thank you all for your responses.
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
@Dave:

Thanks for testing. Admittedly I have never tried to use that script to expire a cookie, so I will fix it to do that and push the new version to my teaching library.  PHP number_format() returns a string, but the string may contain formatting characters including comma and dot, so the function is probably out of place there, and simple (int) casting would be better.  It's always a little dicey when you accept external input and use it to set a cookie!

Best to all, ~Ray
0
 
LVL 82

Expert Comment

by:Dave Baldwin
Comment Utility
You're welcome Ray, these things are good exercises for me to try to figure out why it doesn't do exactly what I thought it should.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
Boost your ability to deliver ambitious and competitive web apps by choosing the right JavaScript framework to best suit your project’s needs.
In this tutorial viewers will learn how to position overlapping items using z-index in CSS. They will also learn the restrictions on the z-index property.  Create a new HTML document with an internal stylesheet.: Create a div in CSS and name it Red.…
In this tutorial viewers will learn how to embed videos in a webpage using HTML5. Ensure your DOCTYPE declaration is set to HTML5: "<!DOCTYPE html>": Use the <video> tag to insert a video. Define the src as the URL of your video; this is similar to …

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now