I'm developing (as a totally no-C#-guy) a web app which communicates with an external data source over OData (server B, some windows 2k12 machine).
The web app runs (is about to run) on an IIS (server A, another windows 2k12 machine), the OData source is a Dynamics NAV 2015 service (the first mentioned windows 2k12 machine, server B).
I'm developing it in VS2013 and if I'm running this locally (meaning: without publishing it, only running it within the local express IIS) it works without any problems at all.
But as soon as I publish it to the target IIS (server A) I'm getting:
An error occurred while processing this request. ---> >System.Data.Services.Client.DataServiceClientException: Unauthorized
at System.Data.Services.Client.QueryResult.ExecuteQuery()
at System.Data.Services.Client.DataServiceRequest.Execute[TElement]>(DataServiceContext context, QueryComponents queryComponents)
--- End of inner exception stack trace ---
This is esentially the piece of code which deals with the OData call:
ODataOrders.NAV odata = new ODataOrders.NAV(new Uri(serviceUri));
System.Net.NetworkCredential nc = new
System.Net.NetworkCredential(_oDataUsername, _oDataUserPassword, _oDataDomain);
odata.Credentials = nc;
DataServiceQuery<ODataOrders.Orders> query =
odata.CreateQuery<ODataOrders.Orders>("Orders");
orderList = query.Execute().ToList(); // "Unauthorized" is being thrown here
It looks like the credentials are being sent/accepted if running from local IIS. And if running from the target (production) server A, the credentials are being somehow lost/overwritten? I really don't know now...
Server A and Server B are in the same domain. My development environment isn't - I can even connect from home through VPN to my work domain and launch my local IIS and still be able to get that request done (the request goes through my local IIS and reaches the Dynamics NAV service so the data is being actually fetched).
Any help would be appreciated...
EDIT
It's Dynamics NAV 2015 CU11.
After some serious hours of reading, programming and trying I've stumbled upon a post here which gave me an idea.
And guess what? It worked - somehow...
Instead of:
System.Net.NetworkCredential(_oDataUsername, _oDataUserPassword, _oDataDomain);
I submitted only:
System.Net.NetworkCredential(_oDataUsername, _oDataUserPassword);
I turns out somehow the domain caused the call not to be authorized (401 error).
Related
Am a new starter to Astra Datastax, Apache Cassandra database. We have created a simple asp.net core API to consume the database from Astra DataStax using a secure connect bundle(Zip file with certs and other information). It is working in the local as expected, however, when publishing to azure app service it is not working, but throw's the below error.
An unhandled exception was thrown by the application. Exception: System.AggregateException: One or more errors occurred. (There was an error fetching the metadata information from the Cloud Metadata Service (https://yourdb.db.astra.datastax.com:31977/metadata). Please make sure your cluster is not parked or terminated. See inner exception for more details.) ---> Cassandra.NoHostAvailableException: There was an error fetching the metadata information from the Cloud Metadata Service
we have checked the DB which is working(Not parked or terminated) and no issues when connecting from local.
Here is the code we are using to connect to the DB to establish a session.
private async Task<ISession> ConnectToAstra(string username, string password, string keyspace, string secureConnectBundlePath)
{
var session = await Cluster.Builder()
.WithCloudSecureConnectionBundle(secureConnectBundlePath)
.WithCredentials(username, password)
.WithQueryOptions(new QueryOptions().SetConsistencyLevel(ConsistencyLevel.LocalQuorum))
.Build()
.ConnectAsync(keyspace);
return session;
}
Note: We have validated the path of the bundle after publishing in Azure App service and also tried moving the Secure bundle to wwwroot folder as well, but no luck.
Any help/guidance will help us to move forward.
Cheers!!
The error you posted indicates that your app is not able to reach any of the Astra nodes so it couldn't get the cluster metadata such as schema and topology.
This is most likely a network connectivity issue with your app and your Astra instance. Note that VPC peering is only available on Classic Astra databases and it is not available for dev and test databases.
If you provide more info on what you mean by "no issues when connecting from local", it will give us additional insight and I'll be happy to update my answer. Cheers!
I have a problem in the following code where I used an MSMQ queue:
Message m;
if (t! = TimeSpan.Zero)
{
m = q.Receive (t);
}
plus
{
m =
q.Receive ();
}
What I am doing is consuming a web service that uses this code. The problem is that if I test it locally using the Visual Studio debugger it works. But when I send the message using the service that is deployed in the IIS, when the Receive () method is executed it returns a TimeOut error, apparently due to the lack of permissions.
System.Messaging.MessageQueueException (0x80004005): The timeout for the requested operation has expired
Investigating I think it could be because when using debugger the user who accesses the queue is the one who encounters the session started on the computer. And when the consumption from the service URL the user who accesses is the IIS / DefaultAppPool. But I'm not sure, and I can't make it work, if anyone has any idea of how qualitative the solution would be, I appreciate it in advance.
I am working on Windows Server 2016 with .NetFramework 4.8.
I have the WCF client shown below:
public static string Execute(string a)
{
WebHttpBinding b = new WebHttpBinding();
b.Security.Mode = WebHttpSecurityMode.Transport;
WebChannelFactory<IAnimalService> f = new WebChannelFactory<IAnimalService>(b, new Uri(a));
f.Endpoint.Behaviors.Add(new WebHttpBehavior());
IWebService client = f.CreateChannel();
return client.SayHello("moo");
}
I am testing the client (in a console host) against its counterpart service from 2 different computers (A, B) and and i get different outcome. Here are the similarities and differences between A and B:
Both A and B are Windows Server 2012 R2 have multiple network interfaces. And each of them have one interface connected to the Internet (so as to reach the service in question).
When running on machine A, everything works as expected i get expected response ("cow says 'moo'") in the client.
When running on machine B, i get different behaviours:
Via the web-browser (firefox), i can get to the service by constructing a request in the address bar. I can see the request going on the external network interface. And everything works as in 2 above.
Via the app (i.e. code above), i get the exception below and more over, when looking at the request in wireshark, it does not go on the external network interface. The exception comes the fact that on that network interface there is a proxy and the proxy is rejecting the request (X-Squid-Error -> ERR_ACCESS_DENIED 0).
Exception:
Unhandled Exception: System.ServiceModel.Security.MessageSecurityException: The HTTP request was forbidden with client authentication scheme
'Anonymous'. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden.
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
--- End of inner exception stack trace ---
I also consulted the routing table on machine B and it shows that request should have gone on the external network interface. I have assumed that the internal routing table would be consulted by the lower layer of the TCP-IP stack in order to forward the packet to the correct (network) medium.
So, I am wondering if someone would have an idea how i could get my client to pick the correct interface on machine B. I am not sure how to go about to troubleshoot the problem further. So any kind of advice/tips on how to get to the bottom of this situation on machine B would be most welcomed.
Try to use this snippet in you config file, so you will be able to use your default credentials to autenticate in the proxy server.
<system.net>
<defaultProxy useDefaultCredentials="true" />
</system.net>
It would appear that by default, the binding seeks to look for the default proxy setting on machine B. Adding the following binding configuration solved the problem:
b.UseDefaultWebProxy = false;
In the spirit of full disclosure, I'm uncertain whether this is a MassTransit/RabbitMQ issue or an IIS authentication/authorization issue, but now that you've been warned, here goes. I have an ASP.NET MVC web application on a web server. It's using the MassTransit.RabbitMQ 3.4 NuGet package to try to establish a connection to an application server with Rabbit 3.6.5 / Erlang 18.0 installed. When the connection is trying to establish, IIS is throwing a 401.2:
HTTP Error 401.2 - Unauthorized
You are not authorized to view this page due to invalid authentication headers.
I've disabled security on the app server, so my connection code from the web app looks like this:
return Bus.Factory.CreateUsingRabbitMq(cfg =>
{
if (virtualHost == "/")
{
virtualHost = string.Empty;
}
cfg.Host(new Uri($"rabbitmq://{hostName}/{virtualHost}"), h =>
{
h.Username("qatemp");
h.Password("qatemp");
});
});
I have set up the "qatemp" user on the app server and granted full access to all virtual hosts. Note that I DO have a working C# console app that can successfully connect to the app server via the same code as above, so hence my concern that this is an IIS-specific issue. Can anyone shed any light on this? IIS is set up for windows authentication and that part seems to be working ok...I think.
Thanks,
Andy
All,
I have a WCF web service (let's called service "B") hosted under IIS using a service account (VM, Windows 2003 SP2). The service exposes an endpoint that use WSHttpBinding with the default values except for maxReceivedMessageSize, maxBufferPoolSize, maxBufferSize and some of the time outs that have been increased.
The web service has been load tested using Visual Studio Load Test framework with around 800 concurrent users and successfully passed all tests with no exceptions being thrown. The proxy in the unit test has been created from configuration.
There is a sharepoint application that use the Office Sharepoint Server Search service to call web services "A" and "B". The application will get data from service "A" to create a request that will be sent to service "B". The response coming from service "B" is indexed for search. The proxy is created programmatically using the ChannelFactory.
When service "A" takes less than 10 minutes, the calls to service "B" are successfull. But when service "A" takes more time (~20 minutes) the calls to service "B" throw the following exception:
Exception Message: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail
Inner Exception Message: The message could not be processed. This is most likely because the action 'namespace/OperationName' is incorrect or because the message contains an invalid or expired security context token or because there is a mismatch between bindings. The security context token would be invalid if the service aborted the channel due to inactivity. To prevent the service from aborting idle sessions prematurely increase the Receive timeout on the service endpoint's binding.
The binding settings are the same, the time in both client server and web service server are synchronize with the Windows Time service, same time zone.
When i look at the server where web service "B" is hosted i can see the following security errors being logged:
Source: Security
Category: Logon/Logoff
Event ID: 537
User NT AUTHORITY\SYSTEM
Logon Failure:
Reason: An error occurred during logon
Logon Type: 3
Logon Process: Kerberos
Authentication Package: Kerberos
Status code: 0xC000006D
Substatus code: 0xC0000133
After reading some of the blogs online, the Status code means STATUS_LOGON_FAILURE and the substatus code means STATUS_TIME_DIFFERENCE_AT_DC. but i already checked both server and client clocks and they are syncronized.
I also noticed that the security token seems to be cached somewhere in the client server because they have another process that calls the web service "B" using the same service account and successfully gets data the first time is called. Then they start the proccess to update the office sharepoint server search service indexes and it fails. Then if they called the first proccess again it will fail too.
Has anyone experienced this type of problems or have any ideas?
Regards,
--Damian
10 mins is the default receive timeout. If you have an idled proxy for more than 10mins, the security session of that proxy is aborted by the server. Enable logging and you will see this in the diagnostics log of the server. The error message you reported fits for this behavior.
Search your system diagnostic file for "SessionIdleManager". If you find it, the above is your problem.
Give it a whirl and set the establishSecurityContext="false" for the client and the server.
Don't call the service operation in a using statement. Instead use a pattern such as...
client = new ServiceClient("Ws<binding>")
try
{
client.Operation(x,y);
client.Close();
}
catch ()
{
client.Abort();
}
I don't understand why this works but I would guess that when the proxy goes out of scope in the using statement, Close isn't called. The service then waits until receiveTimeout (on the binding) has expired and then aborts the connection causing subsequent calls to fail.
What I believe is happening here is that your channel is timing out (as you suspect).
If I understand correctly, it is not the calls to service A that are timing out, but rather to service B, before you call your operation.
I'm guessing that you are creating your channel before you call service A, rather than just in time (i.e. before calling service B). You should create the channel (proxy, service client) just before you use it like:
AResponse aResp = null;
BResponse bResp = null;
using (ServiceAProxy proxyA = new ServiceAProxy())
{
aResp = proxyA.DoServiceAWork();
using (ServiceBProxy proxyB = new ServiceBProxy())
{
bResp = proxyB.DoOtherork(aResp);
}
}
return bResp;
I believe however, that once you get over that problem (service B timing out), you'll realize that the sharepoint app's proxy (that called service A) will timeout.
To solve that, you may wish to change your service model from a request-response, to a publish-subscribe model.
With long-running services, you'll want your sharepoint app to subscribe to service A, and have service A publish its results when it is ready to do so - regardless of how long it takes.
Programming WCF Services (O'Reilly) by Juval Lowey, has a great explanation, and IDesign (Juval's company) published a great set of coding standards for WCF, as well as the code for a great Publish-Subscribe Framework.
Hope this helps,
Assaf.
I actually triggered this error just now by doing something silly. I have a unit test that modifies the system date in order to test some time-based features. And I guess the apparent time difference between when I created the context and when I called my method (because of the changes to the system date), caused something to expire.