Search code examples
asp.netcookiessilverlight-4.0wcf-ria-services

RIA Services, Forms Authentication and extra cookies


I have an Silverlight 4 RIA Services application with custom Forms Authentication. The custom authentication service works like a charm.

The problems is I want to serialize the user object in a cookie which is then sent with each subsequent request.

I create the cookie and add it to the response cookie collection but on the next request the only cookies in the cookie collection are ASPXAUT and ASPX_SESSIONId, of the custom cookie not a trace.

This is the cookie management class:

public class CookieManager:ISessionManager
{

    public object this[string key]
    {
        get
        {
            var context = getCurrentContext();
            var cookie = context.Request.Cookies[key];
            if (cookie == null) return null;
            return deserialize(cookie.Value);
        }
        set
        {
            var context = getCurrentContext();
            string cookieValue = serialize(value);

            HttpCookie cookie = new HttpCookie(key, cookieValue);
            cookie.Expires = DateTime.Now.AddDays(10000);
            cookie.HttpOnly = false;

            context.Response.Cookies.Remove(key);
            context.Response.Cookies.Add(cookie);
        }
    }

    public void Abandon()
    {
        var context = getCurrentContext();
        context.Response.Cookies.Clear();
    }

    public void Clear()
    {
        Abandon();
    }

    private HttpContext getCurrentContext()
    {
        return HttpContext.Current;
    }

    private string serialize(object value)
    {
        MemoryStream stream = new MemoryStream();

        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Context = new StreamingContext(StreamingContextStates.Clone);
        formatter.Serialize(stream, value);

        StreamReader reader = new StreamReader(stream);
        stream.Position = 0;

        string result = reader.ReadToEnd();
        reader.Close();
        stream.Close();

        return HttpUtility.UrlEncodeUnicode(result);
    }

    public object deserialize(string value)
    {
        value = HttpUtility.UrlDecode(value);

        MemoryStream stream = new MemoryStream();
        StreamWriter writer = new StreamWriter(stream);
        writer.Write(value);

        BinaryFormatter formatter = new BinaryFormatter();
        return formatter.Deserialize(stream);


    }

}

It reads and saves cookies.

Now my problem is this:

  1. What I need to enable in silverlight or in the ASP.NET (WCF) application in order for extra cookies to be sent with each request along side the authentication cookie.

EDIT:

I've inspected the HTTP request/response stack and those extra cookies are sent from the server with the WCF RIA Services response but not returned by the next service call from the client.


Solution

  • If I understand your edit above correctly, you've already inspected the HTTP requests and found the desired cookie present in the HTTP Set-Cookie header of the response, but missing in the Cookie header of the next request. Is this correct? If not, please clarify.

    If so, the problem sounds like one of three things:

    1. the client is not successfully saving the cookie, due to many possible reasons including:
      • cookie not properly formatted (unlikley)
      • cookie is too long
      • there's a client- or server-side policy (e.g. P3P) preventing saving persistent cookies.
    2. The client is saving the cookie OK, but is not sending it back, even without Silverlight. This could be caused by, for example, a security issue where the hostname of the first request is different from the second.
    3. The client is saving the cookie and can send it back over regular HTML pages, but not via HTTP requests sent by Silverlight.

    To see if #1 is the problem, look (using your browser's ability to view cookies) at the cookies saved by your browser for that site. Is the expected cookie saved? If it is, then you can eliminate #1 as the problem. If it's not saved, start looking

    To see if #2 is the problem, try creating a server-side page with no silverlight on it-- just a simple HTML page. When you visit that page with your browser, is the cookie sent as expected? If yes, then #2 is not your problem.

    If #1 and #2 are not the problem, that leaves #3. Silverlight's HTTP handling is complicated, not least because you have to choose between having HTTP client requests handled by the browser or by Silverlight. Read the Silverlight cookies documentation carefully and see if any of the info therein will help you figure out the problem. Consider trying to use the "Client HTTP" setting, or if you're already using this, consider switching back to the "browser HTTP" setting and see if your problem goes away. Note that the Client HTTP setting apparently has a problem with losing new cookies after an HTTP redirect. See this thread for more info. There's a workaround discussed in that thread: using CookieContainer.

    BTW, could you edit your question to include all the HTTP headers of the request and the subsequent request? This may help diagnosis.