The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel

Aug 23, 2012 at 5:43 PM


I develop a SharePoint-Webpart with LinqToTwitter and I keep getting the same Error!
And I just don't find any answers on Google or on the Discussions-Page.

My Code looks like this:

public partial class VisualWebPart1UserControl : UserControl
    {
       WebAuthorizer auth;
       TwitterContext twitterCtx;

        protected void Page_Load(object sender, EventArgs e)
        {
            IOAuthCredentials credentials = new InMemoryCredentials();

            if (credentials.ConsumerKey == null || credentials.ConsumerSecret == null)
            {
                credentials.ConsumerKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
                credentials.ConsumerSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
            }

            auth = new WebAuthorizer
            {
                Credentials = credentials,
                PerformRedirect = authUrl => Response.Redirect(authUrl)
            };

            if (!Page.IsPostBack)
            {
                auth.CompleteAuthorization(Request.Url);
            }
            twitterCtx = new TwitterContext(auth);
        }

        protected void Login_Click(object sender, EventArgs e)
        {
            auth.BeginAuthorization(Request.Url);
        }

        protected void Tweet_Click(object sender, EventArgs e)
        {
            twitterCtx.UpdateStatus(TextBox1.Text.ToString());
        }
   }


My Error occurs when I execute auth.BeginAuthorization(Request.Url)
Error Message is: "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."

What am I missing? Do I have to install some certificate or what?


Coordinator
Aug 23, 2012 at 6:20 PM


Linq2Twitter uses HTTPS as it’s transport protocol, which is the right thing to do.  The error you’re seeing is related to your SSL configuration and I don’t believe it’s related to LINQ to Twitter.  To isolate the problem, you can try a couple things:

1. Download the WebFormsOAuthDemo.zip from the Samples and see if it works: http://linqtotwitter.codeplex.com/wikipage?title=LINQ%20to%20Twitter%20Samples&referringTitle=Home. This will tell you if LINQ to Twitter is working for you outside of SharePoint and is a good way to isolate any other problems before integrating with your application.

2. Do a request on an HTTPS endpoint (such as https://search.twitter.com/search.json?q=linq2twitter) with a minimal amount of code. Maybe use the .NET WebClient.DownloadString() at http://msdn.microsoft.com/en-us/library/system.net.webclient.downloadstringcompleted(v=vs.100). This will give you a reproducible sample that you can use to dig deeper and find the reason for the error.

Maybe this will point you in the right direction.

Good luck,

Joe

Aug 30, 2012 at 12:31 PM
Edited Aug 30, 2012 at 2:04 PM

OKI Tested some Stuff,

 

your demo is working without any problems...even from my sharepoint-Serve!
The Download method gives me the same error when using the provided URL but works with any non https-URL.
So it seams to be a Sharepoint-Bug or something... but I cant figure out what I have to change to allow HTTPS-Requests...

So... as long as your are no Share Point-Proffesional too I'm stuck!!!

 

Thanks anyway ^^

 

Edit:

It seams to be a certification Problem. SharePoint only allows https-Connections to certified hosts. ... But I still dont get this running.

Coordinator
Aug 30, 2012 at 4:18 PM

Maybe you can visit one of the Sharepoint forums here. I would reproduce the problem in a sample with Step #2 above (i.e. you're unlikely to get an answer in a Sharepoint forum with a LINQ to Twitter sample).

BTW, LINQ to Twitter does have a strong-name key, LinqToTwitter.snk which is available in the downloadable source code.  I don't know how that would help, but I recall someone asking me to include it for something to do with Sharepoint.

I would be interested if you found the answer and posted it back here.  I have a growing FAQ and this would probably be a useful addition.

Joe

Aug 30, 2012 at 4:32 PM
Edited Aug 30, 2012 at 4:51 PM

OK, found the Solution to that Problem...
I had to include the VeriSign Class 3 Extended Validation SSL CA into the Trusted list in SharePoint.

VeriSign -> http://www.verisign.com/support/roots.html
 download the crt-File and then add it in the Central Administration->Security->Manage Trust->New

 

Tada...

But now I got a different Problem ^^
the authentication went well ...
but when I Try to update the status I get an 401 Unauthorized Error!

Edit:

    OK, somehow the authentication returns a wrong Access Token!!!
    How can that be?

Coordinator
Aug 30, 2012 at 4:55 PM

Good news. :)

Here's some help in tracking down the cause of the 401: http://linqtotwitter.codeplex.com/wikipage?title=LINQ%20to%20Twitter%20FAQ&referringTitle=Documentation.

Joe

Aug 30, 2012 at 5:13 PM

Hmm... the error seams to be that LinqToTwitter gets a wrong Access Token and Secret when Authenticating... It all works fine when I hard code the Access Token and Secret.

Coordinator
Aug 30, 2012 at 5:25 PM

Are you using the most recent release? 

Joe

Aug 30, 2012 at 5:29 PM

I included it via NuGet... the version is 2.0.29!?!?

Aug 30, 2012 at 5:38 PM
Edited Aug 30, 2012 at 5:45 PM

OK... I have an Idea...at what Point are the credentials overwritten with the credentials for the authorized user? when does it write in the Access Token etc...

Because I checked in the Debugger... I actually get an Access Token and Secret but they seam to be invalid or something!!!

 

OK... they get deleted when I click on the Tweet button!?!?
so they are there after authenticating but vanish as soon as I click the Tweet-Button!

Aug 30, 2012 at 6:04 PM

OK solved it!

It seams that SP reloads the page before sending the Update Status Request... and I did not have a routine to save  the Access Informations before that! ^^

My Working Code:

using System;
using System.Web.UI;
using LinqToTwitter;

namespace Tweete.VisualWebPart1
{
    public partial class VisualWebPart1UserControl : UserControl
    {

       WebAuthorizer auth;
       TwitterContext twitterCtx;

        protected void Page_Load(object sender, EventArgs e)
        {

         
            IOAuthCredentials credentials = new InMemoryCredentials();

            if (credentials.ConsumerKey == null || credentials.ConsumerSecret == null)
            {
                credentials.ConsumerKey = VisualWebPart1._ckey;
                credentials.ConsumerSecret = VisualWebPart1._csecret;

            }

            credentials.OAuthToken = VisualWebPart1._aToken;
            credentials.AccessToken = VisualWebPart1._aTokenSecret;

            auth = new WebAuthorizer
            {
                Credentials = credentials,
                PerformRedirect = authUrl => Response.Redirect(authUrl)
            };

            if (!Page.IsPostBack)
            {
                auth.CompleteAuthorization(Request.Url);
            }
            twitterCtx = new TwitterContext(auth);

            if (auth.IsAuthorized)
            {
                VisualWebPart1._aToken = auth.Credentials.OAuthToken;
                VisualWebPart1._aTokenSecret = auth.Credentials.AccessToken;

            }
            
              
        }

        protected void Login_Click(object sender, EventArgs e)
        {
            auth.BeginAuthorization(Request.Url);
        }

        protected void Tweet_Click(object sender, EventArgs e)
        {
            string text = TextBox1.Text.ToString();
            if (text.Length>0)
                twitterCtx.UpdateStatus(text);
        }
              
            
   }

       

}

Coordinator
Aug 30, 2012 at 6:06 PM

With the WebAuthorizer, you do a BeginAuthorize, which sends you to Twitter to authenticate the app. After the authenticate, Twitter redirects to your callback url, which defaults to the page that did the BeginAuthorize. When Twitter returns, you call CompleteAuthorize, which goes out and gets your final OAuthToken and AccessToken.

The credentials are available for the instance of TwitterContext that existed at the time of CompleteAuthorize.  If you're using SessionState credentials, the keys are in SessionState.  Otherwise, you can create your own IOAuthCredentials-derived type to store them as you like.  One thought is that you might want to check to see if you have session state persisting to either a state server or SQL server - you could check the sessionState element in web.config for this. If sessionState isn't defined or is using in-memory mode, your Web server could recycle at any time and cause you to loose session state, including OAuth credentials.

Joe

Sep 12, 2012 at 2:02 PM

Well I am using WebPart Config Variables now, which is a clean and easy way for SharePoint and allows saving stuff for ever either at User Scope or at Global Scope...

 

The Code for a WebPart-Variable is:

 [WebBrowsable(true), Category("Category Name"), Personalizable(PersonalizationScope.Shared), DefaultValue(""), WebDisplayName("Variable Display Name"), WebDescription("Description")]
        public string varName
        {
            get { return _varName; }
            set { _varName= value; }
        }
        public static string _varName;

Where Category, WebDisplayName and WebDescription are just relevant if WebBrowsable is True!!!