.NET 4.0 client certificate validation error - security

I have the following code
var factory = new ChannelFactory<INewsClient>();
factory.Credentials.ClientCertificate.Certificate = GetCertificate();
factory.Endpoint.Address = new EndpointAddress("https://blabla.com/myservice/");
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
factory.Endpoint.Binding = binding;
var channel = factory.CreateChannel();
channel.GetNews();
It works in .NET 3.5, but not in .NET4.0. Bizzare huh?
The Certificate I am using doesn't validate on the local machine (no chain). In 3.5, the client cert's validity is irrelevant to establishing SSL, but when migrating to 4.0, the certificate is validated before being used for SSL. (I can see errors in the CAPI2 Event logs). Resulting in an ugly SecurityNegotiationException...
Stack Trace:
System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'pep.uat.dialectpayments.com'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
--- End of inner exception stack trace ---
Server stack trace:
at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at ConsoleApplication2.Program.INewsClient.Get()
at ConsoleApplication2.Program.Main(String[] args) in d:\dev\ConsoleApplication2\Program.cs:line 44
In our security architecture, certs are validated against an LDAP directory on the server, therefore no need for clients to know the full chain.
Question is, how do I disable this new behaviour?

Ok, I'll provide my own answer here...
In a nutshell: It seems you cannot use a non-persistent CSP with .NET 4 for X509. I.e. Your CSP must have a KeyContainerName for it to work.
My GetCertificate() method was doing the following: (i.e. Non-Persistent)
var certificate = new X509Certificate2(#"C:\public.cer");
var rsa = RSA.Create();
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;
Changing it to this makes my sample work in 3.5 and 4.0: (Setting KeyContainerName will create a physical entry in your crypto folders)
var certificate = new X509Certificate2(#"C:\public.cer");
CspParameters parameters = new CspParameters { KeyContainerName = "KeyContainer" };
var rsa = new RSACryptoServiceProvider(parameters);
rsa.FromXmlString("<RSAKeyValue>......</RSAKeyValue>");
certificate.PrivateKey = rsa;
return certificate;
For simplicity, I was trying to export the private key into a .pfx file, but couldn't using the first approach in .NET 4.0, but could using .NET 3.5. Somwhow, the private key is not exportable in .NET 4.0.
This link helped me fix it.
Still, would be nice to know what's changed between 3.5 and 4.0 here.

Related

RBAC issues using MassTransit with Azure service bus and MSI authentication

We are using MassTransit (v.5.5.5) with Azure Service Bus in a .net core v.2.2 application running in a container within Kubernetes. During the Bus setup we create a token using the managed service identity (MSI), like this...
var tokenProvider = TokenProvider.CreateManagedServiceIdentityTokenProvider();
var busControl = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
IServiceBusHost busHost = cfg.Host(new Uri(Settings.Host), h =>
{
h.OperationTimeout = TimeSpan.FromSeconds(5);
h.TokenProvider = tokenProvider;
h.TransportType = Settings.TransportType;
});
...
}
Within Azure, the MSI is configured with all 3 Service Bus permissions (Owner, Sender and Receiver) - as decribed here.
When the application starts authentication seems to happen successfully but when MassTransit begins to listen on the specific queues we create it fails with the following error:
MassTransit.Azure.ServiceBus.Core.Transport.ReceiveTransport Error: 0 :
ReceiveTransport Faulted: sb://hostname.servicebus.windows.net/some-custom-queue,
Microsoft.Azure.ServiceBus.UnauthorizedException: Generic: Failed during RBAC check,
please make sure service resource provider is registered on your tenant.
Points to note:
The application does create the temporary bus queue, and there are no errors to do with accessing it.
The application does not create our custom queues.
If the MSI permissions are removed then no queues are created and the error is different: Authorization failed for specified action: Manage,EntityWrite.
For what it's worth we are using the AmqpWebSockets transport type.
It seems weird that the temporary queue is created but not our application-specific ones.
So I guess my question is this... have I done anything wrong or is this something that is not yet available for MassTransit using Service Bus with MSI?
Thanks in advance.
We came across the same issue. We are using Mass Transit 6.* and Azure Service Bus. When switched to MSI we start see the same error:
Microsoft.Azure.ServiceBus.UnauthorizedException: Generic: Failed during RBAC check, please make sure service resource provider is registered on your tenant. TrackingId:2644d62a-83a9-444f-8aeb-b4bdee2fa84d_G30, SystemTracker:NoSystemTracker, Timestamp:2020-02-13T15:54:49
at Microsoft.Azure.ServiceBus.Management.ManagementClient.SendHttpRequest(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Azure.ServiceBus.Management.ManagementClient.PutEntity(String path, String requestBody, Boolean isUpdate, String forwardTo, String fwdDeadLetterTo, CancellationToken cancellationToken)
at Microsoft.Azure.ServiceBus.Management.ManagementClient.CreateTopicAsync(TopicDescription topicDescription, CancellationToken cancellationToken)
at MassTransit.Azure.ServiceBus.Core.Contexts.NamespaceManager.<>c__DisplayClass25_0`1.<<RunOperation>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func`1 operation, TimeSpan operationTimeout)
at Microsoft.Azure.ServiceBus.RetryPolicy.RunOperation(Func`1 operation, TimeSpan operationTimeout)
at MassTransit.Azure.ServiceBus.Core.Contexts.NamespaceManager.RunOperation[T](Func`1 operation)
at MassTransit.Azure.ServiceBus.Core.Contexts.ServiceBusNamespaceContext.CreateTopic(TopicDescription topicDescription)
at MassTransit.Azure.ServiceBus.Core.Pipeline.ConfigureTopologyFilter`1.ConfigureTopology(NamespaceContext context)
at MassTransit.Azure.ServiceBus.Core.Pipeline.ConfigureTopologyFilter`1.<>c__DisplayClass5_0.<<Send>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at GreenPipes.PipeExtensions.OneTimeSetup[T](PipeContext context, Func`2 setupMethod, PayloadFactory`1 payloadFactory)
at MassTransit.Azure.ServiceBus.Core.Pipeline.ConfigureTopologyFilter`1.Send(NamespaceContext context, IPipe`1 next)
at GreenPipes.Agents.AsyncPipeContextPipe`1.Send(TContext context)
at GreenPipes.Agents.PipeContextSupervisor`1.GreenPipes.IPipeContextSource<TContext>.Send(IPipe`1 pipe, CancellationToken cancellationToken)
at GreenPipes.Agents.PipeContextSupervisor`1.GreenPipes.IPipeContextSource<TContext>.Send(IPipe`1 pipe, CancellationToken cancellationToken)
at GreenPipes.Agents.PipeContextSupervisor`1.GreenPipes.IPipeContextSource<TContext>.Send(IPipe`1 pipe, CancellationToken cancellationToken)
at MassTransit.Azure.ServiceBus.Core.Pipeline.JoinContextFactory`3.<>c__DisplayClass7_0.<<CreateJoinContext>g__Join|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at MassTransit.Azure.ServiceBus.Core.Pipeline.ClientContextFactory.CreateSharedContext(Task`1 context, CancellationToken cancellationToken)
at GreenPipes.Agents.PipeContextSupervisor`1.GreenPipes.IPipeContextSource<TContext>.Send(IPipe`1 pipe, CancellationToken cancellationToken)
at GreenPipes.Agents.PipeContextSupervisor`1.GreenPipes.IPipeContextSource<TContext>.Send(IPipe`1 pipe, CancellationToken cancellationToken)
at GreenPipes.Agents.PipeContextSupervisor`1.GreenPipes.IPipeContextSource<TContext>.Send(IPipe`1 pipe, CancellationToken cancellationToken)
at MassTransit.Azure.ServiceBus.Core.Transport.ReceiveTransport.<Receiver>b__12_0()
at MassTransit.Azure.ServiceBus.Core.Pipeline.JoinContextFactory`3.<>c__DisplayClass7_0.<<CreateJoinContext>g__Join|0>d.MoveNext()
Finally we found that ASB Sdk Microsoft.Azure.ServiceBus.Management.ManagementClient doesn't allow to create topics with slashes in path when tokens from MSI used. This code below return the same error:
try
{
var address = "sb://[name].servicebus.windows.net";
var tokenProvider = new TokenProvider.CreateManagedIdentityTokenProvider();();
var _managementClient = new ManagementClient(address.ToString(), tokenProvider);
var topicDefinition = new TopicDescription("myNewTopic/22222");
await _managementClient.CreateTopicAsync(topicDefinition);
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
Since MT uses special naming convention to setup messaging topology, we get topic path with namespace of particular message type. If we have message MassTransitTest.Message1 it will be converted to topic MassTransitTest/Message1 (with slash). To fix this we setup our own IEntityNameFormatter
public class MyEntityNameFormatter : IEntityNameFormatter
{
readonly IMessageNameFormatter _formatter;
public MyEntityNameFormatter()
{
_formatter = new ServiceBusMessageNameFormatter();
}
public string FormatEntityName<T>()
{
var entityName = _formatter.GetMessageName(typeof(T)).ToString().Replace("/",".");
return entityName;
}
}
and then
var bus = Bus.Factory.CreateUsingAzureServiceBus(configurator =>
{
...
configurator.MessageTopology.SetEntityNameFormatter(new MyEntityNameFormatter());
...
This fixed our issue. (We tried use ~ instead of . but got some validation errors, so decided use dots)
I have been able to reproduce the same error using Azure Service Bus SDK code directly in a .NET Core (3.0) ASP.NET application hosted in an AppService with Managed Identity.
string serviceBusNamespace = "busnamespace_here";
string queueName = "with_service_name/test"; // NOT working with RBAC
// string queueName = "testrbac"; // Works with RBAC - no /
var msiTokenProvider = TokenProvider.CreateManagedIdentityTokenProvider();
var qc = new QueueClient(new Uri($"sb://{serviceBusNamespace}.servicebus.windows.net/").ToString(), queueName, msiTokenProvider);
var message = new Message(Encoding.UTF8.GetBytes($"Test {DateTime.Now.ToShortTimeString()}"))
{
ContentType = "application/text",
Label = "Scientist",
MessageId = Guid.NewGuid().ToString()
};
try
{
await qc.SendAsync(message);
}
catch (Exception ex)
{
return View(ex.ToString());
}
I found out that the error seems to be caused by the presence of a / in the queue name. It's a character that is allowed in the Service Bus but it doesn't seems to works quite nicely with RBAC Service Bus feature.
The same code works well if you use a SAS Policy instead of Managed Identity/Client Secret.
Here is my test Service Bus in image (using Service Bus Explorer) :
Mass Transit
I know Mass Transit can use entity path with slash character in it. Does that means we can't use RBAC to access those entities ?
I wasn't able to find what is the root cause.

Working C# code converted to Powershell results in SocketException

I have the following C# console app which successfully calls an HTTP Post endpoint:
class Program
{
static void Main(string[] args)
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("https://DomainOne.azure-api.net");
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "8b17badbbfe44e9e933453a8b4d8fc85");
StringContent stringContent = new StringContent("\"hi\"", System.Text.Encoding.UTF8, "application/json");
Task<HttpResponseMessage> task = httpClient.PostAsync("integration/api/Result/CompanyOne", stringContent);
HttpResponseMessage response = task.Result;
var content = response.Content.ReadAsStringAsync().Result;
}
}
This is the equivalent Powershell script I'm trying to use:
$httpClient = New-Object 'System.Net.Http.HttpClient'
$httpClient.BaseAddress = New-Object 'System.Uri'('https://DomainOne.azure-api.net')
$httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "8b17badbbfe44e9e933453a8b4d8fc85");
$stringContent = New-Object 'System.Net.Http.StringContent'('"hi"', [System.Text.Encoding]::UTF8, 'application/json')
$task = $httpClient.PostAsync('integration/api/Result/CompanyOne', $stringContent)
$response = $task.Result
$content = $response.Content.ReadAsStringAsync().Result
However the $task object contains the following:
System.AggregateException: One or more errors occurred.
---> System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send.
---> 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.EndReceive(IAsyncResult asyncResult)
at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)
--- End of inner exception stack trace ---
at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- End of inner exception stack trace ---
The endpoint is hosted in our dev Azure environment behind API Management, and the action method/controller looks like this:
[ApiController]
[Route("api/[controller]")]
public class ResultController : ControllerBase
{
[Route("{providerName}")]
[HttpPost]
public Task<bool> ReceiveMessage(HL7Message message)
{
return Task.FromResult(true);
}
}
Here are the protocol settings in Azure API Management:
Why am I getting the SocketException in Powershell but not in C#, and how can I get it to work in Powershell?
Based on Rick Rainey's helpful comment, you can force the TLS version by adding the line of code below before the HTTP call:
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
I believe this to be a limitation of the .NET version being used. Any version below .NET 4.6 will default to using a TLS version that is not 1.2.

Error: The specified registry key does not exist. Trying to connect to TFS 2012 using network credentials.

var tfsUri = new Uri(credentials.ProjectCollectionUrl);
var user = new NetworkCredential(credentials.Username, credentials.Password);
var tfs = new TfsTeamProjectCollection(tfsUri, user);
tfs.EnsureAuthenticated();
The webapp is deployed on azure. It works locally but breaks on the server.
StackTrace:
* at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str)
at Microsoft.Win32.RegistryKey.CreateSubKeyInternal(String subkey, RegistryKeyPermissionCheck permissionCheck, Object registrySecurityObj, RegistryOptions registryOptions)
at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions options)
at Microsoft.VisualStudio.Services.Common.TokenStorage.RegistryTokenStorageHelper.GetRootKey(String subkeyName)
at Microsoft.VisualStudio.Services.Common.TokenStorage.RegistryTokenStorage.RetrieveToken(VssTokenKey tokenKey)
at Microsoft.VisualStudio.Services.Common.TokenStorage.VssTokenStorage.Retrieve(VssTokenKey tokenKey)
at Microsoft.TeamFoundation.Client.TfsClientCredentialStorage.RetrieveToken(Uri serverUrl, VssCredentialsType credentialType)
at Microsoft.TeamFoundation.Client.CookieCredential.OnCreateTokenProvider(Uri serverUrl, HttpWebResponse response)
at Microsoft.TeamFoundation.Client.IssuedTokenCredential.CreateTokenProvider(Uri serverUrl, HttpWebResponse response, IssuedToken failedToken)
at Microsoft.TeamFoundation.Client.TfsClientCredentials.TryGetTokenProvider(Uri serverUrl, IssuedTokenProvider& provider)
at Microsoft.TeamFoundation.Client.Channels.TfsHttpRequestHelpers.PrepareWebRequest(HttpWebRequest webRequest, Guid sessionId, String operationName, CultureInfo cultureInfo, TfsRequestSettings settings, TfsClientCredentials credentials, IdentityDescriptor impersonate, IssuedToken& currentToken, IssuedTokenProvider& tokenProvider)
at Microsoft.TeamFoundation.Client.Channels.TfsHttpRequestHelpers.CreateSoapRequest(Uri requestUri, Guid sessionId, String soapAction, String operationName, CultureInfo cultureInfo, TfsRequestSettings settings, TfsClientCredentials credentials, IdentityDescriptor impersonate, IssuedToken& currentToken, IssuedTokenProvider& tokenProvider)
at Microsoft.TeamFoundation.Client.Channels.TfsHttpWebRequest.CreateWebRequest()
at Microsoft.TeamFoundation.Client.Channels.TfsHttpWebRequest.SendRequest()
at Microsoft.TeamFoundation.Client.Channels.TfsHttpRequestChannel.Request(TfsMessage message, TimeSpan timeout)
at Microsoft.TeamFoundation.Client.Channels.TfsHttpClientBase.Invoke(TfsClientOperation operation, Object[] parameters, TimeSpan timeout, Object[]& outputs)
at Microsoft.TeamFoundation.Framework.Client.Registration.GetRegistrationEntries(String toolId)
at Microsoft.TeamFoundation.Framework.Client.RegistrationProxy.GetRegistrationEntries(String toolId)
at Microsoft.TeamFoundation.Framework.Client.RegistrationService.RefreshMemoryCache()
at Microsoft.TeamFoundation.Framework.Client.RegistrationService.RefreshCachesIfNeeded(Boolean direct)
at Microsoft.TeamFoundation.Framework.Client.RegistrationService.GetRegistrationEntries(String toolId)
at Microsoft.TeamFoundation.Framework.Client.PreFrameworkServerDataProvider.FindServiceLocation(String serviceType, String toolId)
at Microsoft.TeamFoundation.Framework.Client.PreFrameworkServerDataProvider.LocationForCurrentConnection(String serviceType, Guid serviceIdentifier)
at Microsoft.TeamFoundation.Client.TfsConnection.EnsureProviderConnected()
at Microsoft.TeamFoundation.Client.TfsConnection.EnsureAuthenticated()
We're not sure what causes it to break.
You can't use the old API for TFS on Azure as you need to have Team Explorer installed on the server.
However, if you use the new Nuget packages for the TFS API (Supports new Rest API on TFS 2015, and old client API for 2012, 2013, and 2015)...
http://www.nuget.org/packages/Microsoft.TeamFoundationServer.ExtendedClient/
This will let you connect to TFS from Azure without Team Explorer...
You cannot use TFS Api on Azure Webapp as it requires Team Explorer installed. Refer to this link from MSDN for details: https://msdn.microsoft.com/en-us/library/bb130146.aspx

Calling EWS services through Managed API by using Oauth (ADAL azure active directory library) 401 Unauthorized

I am developing a Provider hosted app in sharepoint for calling EWS services. I am using managed api.
below is my code,
ClientCredential cc = new ClientCredential("********-****-****-****-********e042", "b/2i******n07QKJ********0uhVVvv*****BUs=");
AuthenticationContext authenticationContext = new AuthenticationContext("https://login.windows.net/mydomain.onmicrosoft.com/");
AuthenticationResult result = authenticationContext.AcquireToken("https://outlook.office365.com/", cc);
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
service.Credentials = new OAuthCredentials(result.AccessToken);
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
CalendarView calView = new CalendarView(DateTime.Today, DateTime.Today.AddHours(24));
Mailbox m = new Mailbox("xxxx#xxxxxxxx.onmicrosoft.com");
FolderId CalendarFolderId = new FolderId(WellKnownFolderName.Calendar, m);
FindItemsResults<Appointment> master = service.FindAppointments(CalendarFolderId, calView);
The error that i am getting is 401 unauthorized..
following is the stack trace,
The remote server returned an error: (401) Unauthorized.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.Net.WebException: The remote server returned
an error: (401) Unauthorized.
Source Error: An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.
Stack Trace:
[WebException: The remote server returned an error: (401) Unauthorized.]
System.Net.HttpWebRequest.GetResponse() +6540964
Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.Microsoft.Exchange.WebServices.Data.IEwsHttpWebRequest.GetResponse() +29
Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request) +34
[ServiceRequestException: The request failed. The remote server returned an error: (401) Unauthorized.]
Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request) +149
Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(IEwsHttpWebRequest& request) +407
Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute() +36
Microsoft.Exchange.WebServices.Data.ExchangeService.FindItems(IEnumerable`1 parentFolderIds, SearchFilter searchFilter, String queryString, ViewBase view, Grouping groupBy, ServiceErrorHandling errorHandlingMode) +263
Microsoft.Exchange.WebServices.Data.ExchangeService.FindAppointments(FolderId parentFolderId, CalendarView calendarView) +62
SharePointApp2Web.Pages.Default.Page_Load(Object sender, EventArgs e) +1004
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
System.Web.UI.Control.OnLoad(EventArgs e) +92
System.Web.UI.Control.LoadRecursive() +54
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772
Any thoughts on this will be helpful.
thanks in advance

Azure ACS with HTTPS and multiple instances Error

I just followed the following instructions here.
And found a couple blog entries here and here to be rather helpful.
But I am still getting weird issues with my ASP.NET MVC3 app running on Azure on an HTTPS end point. I have the HTTPS certificate loaded and it has deployed consistently on a single role instance for quite some time without any issue. However, just recently I started deploying multiple instances and ran into the 'Key not valid for use in specified state' and the 'Value cannot be null. Parameter name: certificate' erors.
But I have a new one now:
'Unable to read beyond the end of the stream.'
Looks pretty vanilla. It doesn't become obvious that its an issue with the move from DPAPI to the RSA cookie transform until you look at the stack trace.
[EndOfStreamException: Unable to read beyond the end of the stream.]
System.IO.MemoryStream.InternalReadInt32() +12750266
Microsoft.IdentityModel.Web.RsaEncryptionCookieTransform.Decode(Byte[] encoded) +369
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +189
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) +862
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) +109
Microsoft.IdentityModel.Web.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +356
Microsoft.IdentityModel.Web.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +123
Microsoft.IdentityModel.Web.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +61
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +270
I have added the following code to global.asax:
void OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs e)
{
//
// Use the <serviceCertificate> to protect the cookies that are sent to the client.
//
List<CookieTransform> sessionTransforms = new List<CookieTransform>(
new CookieTransform[] {
new DeflateCookieTransform(),
new RsaEncryptionCookieTransform(e.ServiceConfiguration.ServiceCertificate) });
SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
}
As well as this code:
void WSFederationAuthenticationModule_RedirectingToIdentityProvider(object sender, RedirectingToIdentityProviderEventArgs e)
{
// In the Windows Azure environment, build a wreply parameter for the SignIn request
// that reflects the real address of the application.
HttpRequest request = HttpContext.Current.Request;
Uri requestUrl = request.Url;
StringBuilder wreply = new StringBuilder();
wreply.Append(requestUrl.Scheme); // e.g. "http" or "https"
wreply.Append("://");
wreply.Append(request.Headers["Host"] ?? requestUrl.Authority);
wreply.Append(request.ApplicationPath);
if (!request.ApplicationPath.EndsWith("/")) wreply.Append("/"); e.SignInRequestMessage.Reply = wreply.ToString();
}
I recently worked on similar problem and the potential reason was combination of older SDK and ACS. If you try using SDK 1.6 and ACSv2 setting, i hope this problem will not occur and if you still see the problem, I would be glad to work with you to root cause it.

Resources