Search code examples
c#cookiesdotnetnukeashx

Why is DNN killing my authentication cookies when I access an ashx from a child portal?


I am seeing a really wierd issue that only happens with non-administration users.

When the user logs in and accesses one page, they are logged out of the system. The page finishes loading as if they were logged in, but once they try any other actions (including refreshing the browser page) they are considered not logged in and presented with a login prompt.

Opening up fiddler, I can see one of the responses from the server contains the following:

Response sent 71 bytes of Cookie data: Set-Cookie: portalaliasid=; expires=Sat, 08-May-1982 17:26:06 GMT; path=/; HttpOnly

Response sent 69 bytes of Cookie data: Set-Cookie: portalroles=; expires=Sat, 08-May-1982 17:26:06 GMT; path=/; HttpOnly

Response sent 69 bytes of Cookie data: Set-Cookie: .DOTNETNUKE=; expires=Tue, 12-Oct-1999 04:00:00 GMT; path=/; HttpOnly

Response sent 27 bytes of Cookie data: Set-Cookie: language=; path=/; HttpOnly

Response sent 33 bytes of Cookie data: Set-Cookie: authentication=; path=/; HttpOnly

This always seems to happen when I access my custom ashx web call. The code making this call is the following javascript:

$('#lstStates').empty();
var selectedRegions = $('select[id*=lbxRegions]').val();

// Get the list of states for the selected regions
$.ajax({
    url: '/DesktopModules/MyModule/ashx/GetStatesForRegions.ashx',
    data: { regions: selectedRegions },
    dataType: 'json',
    success: function (data) {
        if (IsArray(data)) {
            for (var state in data) {
                $('#lstStates').append('<option>' + data[state] + '</option>');
            }
        }
    }
});

The code in the ashx is

public class GetStatesForRegions : IHttpHandler
{
    public bool IsReusable { get { return false; } }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        // Get the list of region ids from the GET request
        string[] ids;
        string regionsArray = context.Request["regions[]"] ?? string.Empty;
        ids = regionsArray.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

        using (var dbContext = new MyDataContext())
        {
            string[] states;

            var query = dbContext.Schools.Where(x => x.PodRegionId != null);

            if (ids != null && ids.Length > 0)
                query = query.Where(x => ids.Contains(x.PodRegionId.ToString()));

            states = query.Select(x => x.xosAddress.State)
                          .Distinct()
                          .OrderBy(x => x)
                          .ToArray();

            context.Response.Write(JsonConvert.SerializeObject(states));
            context.Response.End();
        }
    }
}

Why is this clearing my relevant cookies and logging out non-administrator users?


Edit: To add to the mystery, when you access the ashx as a non-administrator DNN seems to return a 302 HTTP response, redirecting you to the same url again. That 302 response is what contains the cookie clearing data. The 2nd time it accesses the ashx (due to the redirect) the correct data is returned.


Solution

  • This occurs because the user is only defined in the child portal, but the request to the ASHX occurs (from DNN's perspective) in the parent portal. When DNN receives the request, it sees that you've "switched portals," no longer have a valid identity, and removes your authentication information. This doesn't occur for super users because they do have a valid identity across both portals.

    To fix this issue, you need to add a querystring parameter to your request with the portal ID. This let's DNN disambiguate the request and keep your authentication intact:

    $.ajax({
        url: '/DesktopModules/MyModule/ashx/GetStatesForRegions.ashx?portalId=' + <%:PortalId%>,
        ....
    });