Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a requirement to allow users to SSO from our SharePoint 2010 portal to other websites that are authenticated by disparate LDAP servers. We will not be able to collapse them together.

We have determined that we will store users' credentials in a Secure Store application in our SharePoint portal (site A). We will use these credentials when the user wants to log into another site (site B). Site B runs a simple forms based authentication. I'm using the code behind an empty ASPX page running in Visual Studio 2010.

The idea is that we want users to click a link to site B and for SharePoint to send their credentials for them.

I have the code to extract the user's credentials from the SharePoint Secure Store application. But I am having trouble finding working examples of the second part of this. I'm testing the authentication piece with a test app that I control and can tightly monitor.

First of all, in the Page_Load of the aspx, I have:

            CookieContainer cookieContainer = new CookieContainer();

            // Create a request using a URL that can receive a post. 
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://test.edu/admin_login.cfm") as HttpWebRequest;
            request.CookieContainer = cookieContainer;

            // Set the Method property of the request to POST.
            request.Method = "POST";
            // Create POST data and convert it to a byte array.
            string postData = "userName=testUser&password=testPW&login=Login";

            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            // Set the ContentType property of the WebRequest.
            request.ContentType = "application/x-www-form-urlencoded";
            // Set the ContentLength property of the WebRequest.
            request.ContentLength = byteArray.Length;
            // Get the request stream.
            Stream dataStream = request.GetRequestStream();
            // Write the data to the request stream.
            dataStream.Write(byteArray, 0, byteArray.Length);
            // Close the Stream object.
            dataStream.Close();
            // Get the response
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            response.Cookies = request.CookieContainer.GetCookies(request.RequestUri);
            StreamReader reader = new StreamReader(response.GetResponseStream());
            string tmp = reader.ReadToEnd();
            foreach (Cookie cook in response.Cookies)
            {
                Response.Cookies.Add(CookieToHttpCookie(cook));
            }

here's the code I'm using to convert to an HTTPCookie:

    public System.Web.HttpCookie CookieToHttpCookie(Cookie cookie)
    {
        System.Web.HttpCookie httpCookie = new System.Web.HttpCookie(cookie.Name);
        /*Copy keys and values*/
        foreach (string value in cookie.Value.Split('&'))
        {
            string[] val = value.Split('=');
            if (0 < val.Length)
            {
                httpCookie.Values.Add(val[0], null);
            }
            else
            {
                httpCookie.Values.Add(val[0], val[1]);
            }

        }
        /*Copy Porperties*/
        httpCookie.Domain = cookie.Domain;
        httpCookie.Expires = cookie.Expires;
        httpCookie.HttpOnly = cookie.HttpOnly;
        httpCookie.Path = cookie.Path;
        httpCookie.Secure = cookie.Secure;
        return httpCookie;
    }
}

I have eliminated the class file that handles the request and response and now just have it running in the body of the page_load event handler method. I understand how I will pass back the cookies that the server has received from the target login site. This code runs and debugs perfectly.

However, my issue now is that the cookies never appear on the browser. Is this because they are from a different domain than the server? The target login application is at xxxx.test.edu and my development server is sp-developer. Is that causing a problem? What am I missing?

share|improve this question
    
Update: I have discovered that the Post() method above and some code that I've found that uses HttpWebRequest request = (HttpWebRequest)WebRequest.Create("test.edu/admin_login.cfm"); is getting an System.NotSupportedException. Microsoft is saying that the The request scheme specified in requestUriString needs to be registered. Any idea what that means? –  Eric Carlson Mar 19 at 16:20
    
I have evolved my code and I now have better understanding of cookie handling in C# as the code acts as a client and a server. My only issue left is that the cookies don't appear in the browser now, even though I'm not seeing any problems with the following line: Response.Cookies.Add(CookieToHttpCookie(cook)); –  Eric Carlson Apr 2 at 16:40
    
I seem to remember you could have cookie-less cookies... which still let you have cookies but they were not saved to the drive but encoded in the URL, maybe that's why you are not seeing the cookies but it's still working. –  axawire Apr 4 at 18:12

1 Answer 1

up vote 0 down vote accepted

I found a different way to do this. I ran across a clearer version of a post I'd been directed to some time ago and this time I understand better what the author was trying to do: Posting from ASP.Net page to another URL

So the code ends up looking like this:

 public class  RemotePost{
 private  System.Collections.Specialized.NameValueCollection Inputs 
 = new  System.Collections.Specialized.NameValueCollection() ;

public string  Url  =  "" ;
public string  Method  =  "post" ;
public string  FormName  =  "form1" ;

public void  Add( string  name, string value ){
    Inputs.Add(name, value ) ;
 }

 public void  Post(){
    System.Web.HttpContext.Current.Response.Clear() ;

     System.Web.HttpContext.Current.Response.Write( "<html><head>" ) ;

     System.Web.HttpContext.Current.Response.Write( string .Format( "</head><body onload=\"document.{0}.submit()\">" ,FormName)) ;

     System.Web.HttpContext.Current.Response.Write( string .Format( "<form name=\"{0}\" method=\"{1}\" action=\"{2}\" >" ,

    FormName,Method,Url)) ;
        for ( int  i = 0 ; i< Inputs.Keys.Count ; i++){
        System.Web.HttpContext.Current.Response.Write( string .Format( "<input name=\"{0}\" type=\"hidden\" value=\"{1}\">" ,Inputs.Keys[i],Inputs[Inputs.Keys[i]])) ;
     }
    System.Web.HttpContext.Current.Response.Write( "</form>" ) ;
     System.Web.HttpContext.Current.Response.Write( "</body></html>" ) ;
     System.Web.HttpContext.Current.Response.End() ;
 }
} 

I just set the properties on the class defined above and call Post().

Works like a charm.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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