WCF Discovery with multithreading - The caller was not authenticated by the service - multithreading

I try to implement WCF Discovery service using multithreading.
static void InvokeService()
{
var Services = discoveryClient.Find(new FindCriteria(typeof(WCFDiscoveryContract.IService1)));
discoveryClient.Close();
ServiceClient.ServiceReference1.Service1Client client = new ServiceClient.ServiceReference1.Service1Client();
client.Endpoint.Address = Services.Endpoints[0].Address;
var loanResponses = new MultiThreadedServiceCall<IService1, int, string>()
.CallMethod((service, request) => service.GetData(request))
.AttachService(new ServiceClient.ServiceReference1.Service1Client())
.GetResults(111);
string ss = client.GetData(1);
Console.WriteLine("Data is " + ss);
}
When i discover a service hosted in the same machine, it is working fine with the output.
But when i use the service hosted in another machine in the same network, it throws error in the following line.
string ss = client.GetData(1);
Error is
SecurityNegotiationException was unhandled
The caller was not authenticated by the service.
The request for security token could not be satisfied because authentication failed.
I use wsHttpBinding.
Please note wcf discovery service is working fine for service hosted in another machine.

Related

Azure App Service cannot connect to Azure Redis when calling from Web Browser

I have a REST API services application that is using Asp.net core, and hosted on Azure App Service.
I am adding Azure Redis as a cache mechanism.
I tested the application on my local machine using local redis and it is working fine.
I deployed the Web service To Azure App Service, and test it.
When I try to test the services using Postman, it is working fine, and it is populating the cache, and reading from the cache.
But when I run the Front-end application which is a JavaScript Single Page Application that is calling the back-end services.
I am not querying Redis from the front-end. but from the backend .net application.
The calls to the services fail with this error
Timeout performing EVAL, inst: 1,
clientName: <.....>, serverEndpoint: Unspecified/my-redis.redis.cache.windows.net:6380,
keyHashSlot: 15126 (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts)
As I said, I am calling the same EndPoint (which is my App service), with the same parameters, from Postman, and it is working.
But from the browser, it is not working
This is my configuration and code:
In the Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDistributedRedisCache(options => {
options.Configuration = Configuration.GetConnectionString("AzureCache");
options.InstanceName = "master";
});
}
And in the controller (ProductController)
using Microsoft.Extensions.Caching.Distributed;
public class ProductController: ControllerBase
{
IDistributedCache _cashe;
IDataRepository _repo;
public ProductController (IDistributedCache cache, IDataRepository repo)
{
_cache = cache;
_repo = repo;
}
[HttpGet]
public Async Task<IActionResult> GetProductions([FormBody] DataRequest request)
{
string data = _cache.GetString(request.AsKey());
if (data == null)
{
data = _repo.getData(request);
_cache.SetString(request.AsKey());
}
return Ok(data);
}
}
}
The client side code is as follows:
const request = axios.post('https://mydata.myserver.azure.com', reqBody, headers);
request.then(res => {
.... process the data
});
P.S: the error mentioned an article online.
I read the article and nothing jumped out. All my services are less than 5k in size except one, which is between 250k and 300k, and all calls are failing for me.
Error itself describing 'Please take a look at this article for some common client-side issues'. Could you share your client side code through which you are making call?

LDAP Authentication Fails in Azure App Service

I have created a Java web app and deployed it on Azure App Service. In the app, we are providing users with a Login Page and upon submitting the credentials the users are authenticated using LDAP. This is working when deployed locally.
When I deploy this to Azure as WebApp, the authentication doesn't happen and the application gives an error. I am trying to authenticate like below. The LDAPContext is always returned as null in Azure.
The Authentication/Authorization settings in Azure Portal is turned OFF.
LdapContext ctx = null;
String dn= "uid=" + username + ",ou=users,ou=xxxx,o=xxxxx";
String ldapURL = "ldap://ldap.example.com:389";
Hashtable<String, String> environment =new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapURL);
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, dn);
environment.put(Context.SECURITY_CREDENTIALS, password);
ctx = new InitialLdapContext(environment,null);
Server Side: Check the inbound Security rule for Which Ip address are can access the LDAP
If you pass the LDAP domain name in code . Try pass empty value that place
Try to give Auth type is Basic or Negotiate or Anonymous etc . these are in .Net Frame work same way try some other type in Java may be . So try like that
ldap://ldap.example.com - For this example.com is domain name

Service to service authentication in Azure without ADAL

I configured azure application proxy for our on-premise hosted web service and turned on Azure AD authentication. I am able to authenticate using ADAL but must find a way to get the token and call web service without ADAL now (we are going to use this from Dynamics 365 online and in sandbox mode I can't use ADAL). I followed some examples regarding service to service scenario and I successfully retrieve the token using client credentials grant flow. But when I try to call the app proxy with Authorization header and access token, I receive an error "This corporate app can't be accessed right now. Please try again later". Status code is 500 Internal server error.
Please note the following:
I don't see any error in app proxy connectors event log.
I added tracing on our on-premise server and it seems like the call never comes there.
If I generate token with ADAL for a NATIVE app (can't have client_secret so I can't use client credentials grant flow), I can call the service.
I created an appRole in manifest for service being called and added application permission to the client app.
This is the way I get the token:
public async static System.Threading.Tasks.Task<AzureAccessToken> CreateOAuthAuthorizationToken(string clientId, string clientSecret, string resourceId, string tenantId)
{
AzureAccessToken token = null;
string oauthUrl = string.Format("https://login.microsoftonline.com/{0}/oauth2/token", tenantId);
string reqBody = string.Format("grant_type=client_credentials&client_id={0}&client_secret={1}&resource={2}", Uri.EscapeDataString(clientId), Uri.EscapeDataString(clientSecret), Uri.EscapeDataString(resourceId));
HttpClient client = new HttpClient();
HttpContent content = new StringContent(reqBody);
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
using (HttpResponseMessage response = await client.PostAsync(oauthUrl, content))
{
if (response.IsSuccessStatusCode)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(AzureAccessToken));
Stream json = await response.Content.ReadAsStreamAsync();
token = (AzureAccessToken)serializer.ReadObject(json);
}
}
return token;
}
AzureAccessToken is my simple class marked for serialization.
I assume it must be something I haven't configured properly. Am I missing some permissions that are required for this scenario?
Any help is appriciated.

webapi to IoTHub not working from Azure deployment

was: "Iot Hub diagnostics azure deployed app"
Strange issue. I have a very simple 4.5.2 based webapi application that acts as a field gateway; that is each method connects to IoT Hub on behalf of the consumer which are actual devices capable of only posting to HTTP endpoints.
When I run the code from my local development machine everything works as expected and my IoT Hub receives the data. so, then, I published the webapi application to azure and ran the same methods but there is no activity to the IoT Hub detected at all. weird. I went so far as to debug the application code in azure and everything is working without error. There's no external configuration to mess things up at the moment, its all in the code.
Is there are logical explanation for this behavior?
I'm new to IoT Hub so maybe this is a simple thing. Where can I turn on verbose diagnostics? Since I have code that I believe to be working where can I see the next logical information? Are there permissions of some sort that may be preventing the data to pass through?
WebApi method(s) basically call this code which is contained in a separate assembly
public static void SendTempData(string Name, string value)
{
var telemetryDataPoint = new
{
deviceId = HOME_TEMP_DEVICE,
DeviceName = Name,
TValue = value
};
var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
var task = Task.Run(() =>
{
deviceClient = DeviceClient.Create(iotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey(HOME_TEMP_DEVICE, HOME_TEMP_DEVICE_KEY), TransportType.Mqtt);
var message = new Message(Encoding.ASCII.GetBytes(messageString));
deviceClient.SendEventAsync(message);
});
WaitForTask(ref task);
CheckForFail(task);
}
private static void WaitForTask(ref Task task)
{
while (task.Status != TaskStatus.RanToCompletion)
{
if ((task.IsCanceled) || (task.IsFaulted))
break;
System.Diagnostics.Debug.WriteLine("Thread ID: {0}, Status: {1}", Thread.CurrentThread.ManagedThreadId, task.Status);
}
}
Bottom line is I have no visibility. Is there some verbose setting I can enable to see why IoTHub never sees a connection or data?

Windows Azure WCF Security

I've a wcf service deployed to the cloud. Could anyone guuide me through best practices on how I can secure the end point in azure please?
Thanks.
In my opinion, the easiest approach is to use the AppFabric Access Control Service (ACS) to generate a Secure Web Token (SWT) that you pass to the WCF service via an authorization HTTP header. In the service method, you can then read and validate the SWT from the header.
It's pretty straightforward, particularly if you create proxies dynamically rather than using Service References.
This is how I get the SWT from ACS:
private static string GetToken(string serviceNamespace, string issuerKey, string appliesto)
{
WebClient client = new WebClient();
client.BaseAddress = String.Format("https://{0}.accesscontrol.windows.net", serviceNamespace);
client.UseDefaultCredentials = true;
NameValueCollection values = new NameValueCollection();
values.Add("wrap_name", serviceNamespace);
values.Add("wrap_password", issuerKey);
values.Add("wrap_scope", appliesto);
byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
string response = System.Text.Encoding.UTF8.GetString(responseBytes);
string token = response
.Split('&')
.Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase))
.Split('=')[1];
return token;
}
issuerKey, as it was referred to in ACS v1 is now the Password from the Service Identity in ACS v2.
To call the service:
string accessToken = GetToken(serviceNamespace, issuerKey, appliesto);
string authHeaderValue = string.Format("WRAP access_token=\"{0}\"", HttpUtility.UrlDecode(accessToken));
// TInterface is the service interface
// endpointName refers to the endpoint in web.config
ChannelFactory channelFactory = new ChannelFactory<TInterface>(endpointName);
TInterface proxy = channelFactory.CreateChannel();
OperationContextScope scope = new OperationContextScope(proxy as IContextChannel);
WebOperationContext.Current.OutgoingRequest.Headers.Add(HttpRequestHeader.Authorization, authHeaderValue);
// Call your service
proxy.DoSomething();
On the service-side, you extract the token from the header and validate it. I can find out the code for that, if this looks like the approach you want to take.
Try this blog post by Alik Levin as a good starting point.
A typical, broadly interoperable approach would be to use HTTP Basic Authentication over an SSL connection. The approach for running this in Azure is really very similar to how you would achieve this on a traditional Windows server.
You can implement an IIS Http Module and provide your own implementation of a BasicAuthenticationModule - this can work however you want but calling in to ASP.NET Membership (a call to ValidateUser) would be a common approach. The store for that can be hosted in SQL Azure.
You can then surface this to WCF by implementing IAuthorizationPolicy and adding this to your authorizationPolicies WCF config element.
The Patterns and Practices team have a walkthrough of this with complete code at
http://msdn.microsoft.com/en-us/library/ff649647.aspx. You can ignore the brief Windows Forms discussion - being web services, their choice of client is irrelevant.

Resources