The Underlying Connection Was Closed - An Unexpected Error Occurred

The Underlying Connection Was Closed - An Unexpected Error Occurred
 

SharePoint Provider Hosted

The underlying connection was closed: An unexpected error occurred on a send. Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. An existing connection was forcibly closed by the remote host.

Recently, I was getting this error while deploying the SharePoint Provider hosted app in the Azure app service.

Exact Error

The underlying connection was closed: An unexpected error occurred on a send. Innerer Exception System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

Then, I started debugging locally with username and password and still getting errors while generating token as shown,

Token request failed. Innerer Exception System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.HttpWebRequest.GetResponse()
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2WebRequest.GetResponse()
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request)

The above error message gave me some hints and the issue is related to security protocol.

Solution: After a bit of research, I found that this error was happening only in older applications. This can be fixed by updating the security protocol.

We need to add the following code before doing authentication or generating tokens.

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

We can add this line of code just before the authentication part as shown.

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var webContext = new HttpContextWrapper(HttpContext.Current);
var spContext = SharePointContextProvider.Current.GetSharePointContext(webContext);

if (HttpContext.Current.Session["accessToken"] == null)
    HttpContext.Current.Session["accessToken"] = spContext.UserAccessTokenForSPHost;

Alternatively, for manual authentication (sample).

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Uri siteUri = new Uri(siteUrl);
var ll = siteUri.UserInfo;
string realm = TokenHelper.GetRealmFromTargetUrl(siteUri);
string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, siteUri.Authority, realm).AccessToken;

However, if you are creating the provider-hosted app with the latest version, then this issue has already been fixed.