Cassia using impersonation and wcf - wcf

I am trying to use Cassia with a WCF web service I keep getting "An existing connection was forcibly closed by the remote host". When I try it on a test console application it works fine. This is the code I am using from a sample I found. Anyone ever do this?
public List<ITerminalServicesSession> getTermminalServerSessions(string serverName)
{
ConnectionDetails connection = new ConnectionDetails();
connection.Domain = "DOMAIN";
connection.Server = serverName;
connection.Username = "USER";
connection.Password = "PASSWORD";
using (ImpersonationHelper.Impersonate(connection))
{
using (var server = GetServer(connection.Server))
{
server.Open();
return server.GetSessions().ToList();
}
}
}

Related

How to access a file server share from an ASP.NET Core web API application published in IIS within the same domain?

I need access to files that are in a files server in my LAN from my Angular app.
I assume that I need to publish my Angular app in the same network, that is, in my IIS Server inside the same LAN
Now on my local machine, I try to access my shared folder \192.168.100.7\OfertasHistoric" but I donĀ“t know how to do it.
When I try this
[HttpGet("directorio")]
public async Task<ActionResult<string[]>> GetDirectoryContents()
{
string[] files = Directory.GetFiles(#"\\192.168.100.7\ofertashistorico");
return files;
}
I get this error
System.IO.DirectoryNotFoundException: Could not find a part of the path '/Users/kintela/Repos/Intranet-WebAPI/Intranet.API/\192.168.100.7\ofertashistorico'
It seems that the path that you give to the GetFiles method only searches from the current directory where the project is located downwards and I don't know how to indicate a different one.
I also do not know how to manage the issue of the credentials necessary to access said resource
Any idea, please?
Thanks
I am using below code and it works for me. Please check it.
Steps:
Navigate to the path like : \\192.168.2.50\ftp
Delete \ftp, the address in folder explorer should be \\192.168.2.50, find the folder you want, right click and map network drive.
You can try it with this address ftp:\\192.168.2.50, it will pop up a window. Input you usename and password, then you can check the files.
Test Result
Sample code
[HttpGet("directorio")]
public IActionResult GetDirectoryContents()
{
string networkPath = #"ftp:\\192.168.2.50";
string userName = #"Administrator";
string password = "Yy16";
#region FtpWebRequest
var networkCredential = new NetworkCredential(userName, password);
var uri = new Uri(networkPath);
var request = (FtpWebRequest)WebRequest.Create(uri);
request.Credentials = networkCredential;
request.Method = WebRequestMethods.Ftp.ListDirectory;
try
{
using (var response = (FtpWebResponse)request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
}
}
}
catch (WebException ex)
{
Console.WriteLine("Access to the path '" + networkPath + "' is denied. Error message: " + ex.Message);
}
#endregion
return Ok();
}

Call Azure API from WebJob/ Shared code between WebJob and web api

I have a web api in an ASE and an associated web job. I am trying to call this web api from the web job but it always fails with winhttpexception: a security error has occurred. I have put in all the tls related settings but still getting the error.
Any suggestions on the error?
Also is there a way to share code between WebJob and web api?
I was able to resolve the issue by setting the below in my code.This resolved the Security Error.
using(var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender,certificate,chain,sslPolicyErrors) => true
})
You could create a console app and publish it as Azure WebJobs. For username and password you could click Get Publish Profile in your Azure webapp overview to get them.
Then you could use the following code in Console App to call your Azure Webapi.
string userName = "$xxxxxx";
string userPassword = "xxxxxxxxxxxxx";
string webAppName = "xxxxxx";
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{userName}:{userPassword}"));
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Basic " + base64Auth);
var baseUrl = new Uri($"https://{webAppName}.azurewebsites.net/api/values");
var result = client.GetAsync(baseUrl).Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsStringAsync();
readTask.Wait();
var value = readTask.Result;
Console.WriteLine(value.ToString());
}
}
Console.WriteLine("run successfully");
Output as below:

CRM OrganizationServiceProxy authentication issue

We have an issue where our web app calls to CRM via Microsoft.Xrm.Sdk OriganizationServiceProxy are failing to authenticate. The issue appears to be environment specific i.e. the calls work on our DEV web server but fail when the app is promoted to our System Test environment. The code that fails is as follows:
using (var serviceProxy = this.serviceFactory.Impersonate(userProvider.PrincipalUserName).ServiceProxy)
{
var countResult = serviceProxy.RetrieveMultiple(new FetchExpression(query));
int? count = 0;
var entity = countResult.Entities.FirstOrDefault();
if (entity != null)
{
count = (int?)((AliasedValue)entity["activity_count"]).Value;
}
return count.Value;
}
The error that appears in our logs is:
System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---> System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)
--- End of inner exception stack trace ---
I have double checked the apppool identity of the IIS site and CRM settings. Is there anything obvious here that we may have missed?
I found the connection to CRM Online was taking the longest time so I create one instance to pass round of the OrganizationServiceProxy with explicit credentials that I can easily switch between environments.
IServiceManagement<IOrganizationService> management = ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(CrmUrl));
ClientCredentials credentials = new ClientCredentials();
credentials.UserName.UserName = CrmUserName;
credentials.UserName.Password = CrmPassword;
AuthenticationCredentials authCredentials = management.Authenticate(new AuthenticationCredentials { ClientCredentials = credentials });
SecurityTokenResponse securityTokenResponse = authCredentials.SecurityTokenResponse;
OrganizationServiceProxy orgProxy = new OrganizationServiceProxy(management, securityTokenResponse);
orgProxy.EnableProxyTypes();
_xrmService = new XrmServiceContext(orgProxy)

How to delegate Facebook SecurityToken to WCF service

I have the following components:
WPF Application,
Identity Server,
WCF Web Service,
WPF Application uses WebBrowser control to authenticate using Thintecture Identity Server using WS-Federation. Identity Server has enabled Home Realm Discovery and allow authentication using Facebook, Live ID and Google. After authentication I get ReqquestSecurityTokenResponse message, which I convert into SecurityToken.
After getting this SecurityToken I want to call WebService. I think I need create ActAsToken issued again by Thintecture Identity Server, but I can't configure it.
var serviceAddress = "http://localhost:7397/Service1.svc";
var token3 = token2.ToSecurityToken();
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message);
binding.Security.Message.IssuedKeyType = System.IdentityModel.Tokens.SecurityKeyType.SymmetricKey;
binding.Security.Message.IssuerAddress = new EndpointAddress("https://dev3.example.com/Identity/issue/wsfed");
binding.Security.Message.IssuerBinding = new WS2007HttpBinding();
var factory = new ChannelFactory<IService1Channel>(binding,
new EndpointAddress(
new Uri(serviceAddress),
new DnsEndpointIdentity("dev3.example.com")));
factory.Credentials.SupportInteractive = false;
var proxy = factory.CreateChannelWithActAsToken(token3);
{
try
{
var output = proxy.GetData(1);
MessageBox.Show(output);
proxy.Dispose();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
But I get exceptions.
WebService is configured using Identity and access... VS extension.
Is this scenario possible?
you don't need an ActAs - you can use the CreateChannelWithIssuedToken method to create your WCF proxy.
You also need to configure bearer keys on the WCF service and client (instead of SymmetricKey).

Self-Hosted WCF Custom binding, Binary message, HTTPS transport WITHOUT certificate

I have some self-hosted WCF services using CustomBinding for HTTP protocol on a specific port.
I use BinaryMessageEncodingBindingElement and HttpTransportBindingElement so far without problem.
Now I need to secure a bit more by using HTTPS but with NO cert. I switched to HttpsTransportBindingElement and set RequireClientCertificate to false.
I have no cert installed on that port. I checked by running "netsh http show sslcert".
And I get follow error when I try to add my service to a WPF app (browsing with Chrome I get "This webpage is not available"):
There was an error downloading 'https://localhost:8080/myhost/myservice.svc'.
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
Metadata contains a reference that cannot be resolved: 'https://localhost:8080/myhost/myservice.svc'.
An error occurred while making the HTTP request to 'https://localhost:8080/myhost/myservice.svc'.
This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case.
This could also be caused by a mismatch of the security binding between the client and the server.
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
If the service is defined in the current solution, try building the solution and adding the service reference again.
Here goes my binding:
private System.ServiceModel.Channels.Binding GetHttpBinding(String pName)
{
System.ServiceModel.Channels.BindingElementCollection elements = new System.ServiceModel.Channels.BindingElementCollection();
System.ServiceModel.Channels.BinaryMessageEncodingBindingElement binaryMessageEncoding = new System.ServiceModel.Channels.BinaryMessageEncodingBindingElement();
binaryMessageEncoding.MessageVersion = System.ServiceModel.Channels.MessageVersion.Default;
binaryMessageEncoding.ReaderQuotas.MaxArrayLength = this._maxArrayLength;
binaryMessageEncoding.ReaderQuotas.MaxBytesPerRead = this._maxBytesPerRead;
binaryMessageEncoding.ReaderQuotas.MaxDepth = this._maxDepth;
binaryMessageEncoding.ReaderQuotas.MaxNameTableCharCount = this._maxNameTableCharCount;
binaryMessageEncoding.ReaderQuotas.MaxStringContentLength = this._maxStringContentLength;
elements.Add(binaryMessageEncoding);
if (this._applyHttps)
{
System.ServiceModel.Channels.HttpsTransportBindingElement transport = new System.ServiceModel.Channels.HttpsTransportBindingElement()
{
MaxBufferSize = this._maxBufferSize,
MaxReceivedMessageSize = this._maxReceivedMessageSize,
AllowCookies = false,
BypassProxyOnLocal = false,
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
MaxBufferPoolSize = this._maxBufferPoolSize,
TransferMode = TransferMode.Buffered,
UseDefaultWebProxy = true,
ProxyAddress = null,
RequireClientCertificate = false
};
elements.Add(transport);
}
else
{
System.ServiceModel.Channels.HttpTransportBindingElement transport = new System.ServiceModel.Channels.HttpTransportBindingElement()
{
MaxBufferSize = this._maxBufferSize,
MaxReceivedMessageSize = this._maxReceivedMessageSize,
};
elements.Add(transport);
}
System.ServiceModel.Channels.CustomBinding custB = new System.ServiceModel.Channels.CustomBinding(elements);
custB.Name = pName;
custB.SendTimeout = new TimeSpan(0, 2, 0);
return custB;
}
And I configure the service host with this method:
private void ConfigureBinaryService(ServiceHost pHost, Type pType, String pServiceName)
{
pHost.AddServiceEndpoint(pType, this.GetHttpBinding(pType.Name), String.Empty);
pHost.AddServiceEndpoint(pType, this.GetNetTcpBinding(pType.Name), String.Empty);
pHost.Description.Endpoints[0].Name = pType.Name + "_BasicBin";
pHost.Description.Endpoints[1].Name = pType.Name + "_TCP";
pHost.OpenTimeout = new TimeSpan(0, 2, 0);
pHost.CloseTimeout = new TimeSpan(0, 2, 0);
System.ServiceModel.Description.ServiceMetadataBehavior metadataBehavior = pHost.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>();
if (metadataBehavior == null)
{
metadataBehavior = new System.ServiceModel.Description.ServiceMetadataBehavior();
pHost.Description.Behaviors.Add(metadataBehavior);
}
if (this._applyHttps)
metadataBehavior.HttpsGetEnabled = true;
else
metadataBehavior.HttpGetEnabled = true;
metadataBehavior.MetadataExporter.PolicyVersion = System.ServiceModel.Description.PolicyVersion.Policy15;
if (this._applyHttps)
pHost.AddServiceEndpoint(System.ServiceModel.Description.ServiceMetadataBehavior.MexContractName
, System.ServiceModel.Description.MetadataExchangeBindings.CreateMexHttpsBinding(), "mex");
else
pHost.AddServiceEndpoint(System.ServiceModel.Description.ServiceMetadataBehavior.MexContractName
, System.ServiceModel.Description.MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
pHost.AddServiceEndpoint(System.ServiceModel.Description.ServiceMetadataBehavior.MexContractName
, System.ServiceModel.Description.MetadataExchangeBindings.CreateMexTcpBinding(), this._NetTcpComm + #"/" + pServiceName + #"/mex");
pHost.Description.Endpoints[2].Name = pType.Name + "_mex_BasicBin";
pHost.Description.Endpoints[3].Name = pType.Name + "_mex_TCP";
foreach (var item in pHost.Description.Endpoints[0].Contract.Operations)
item.Behaviors.Find<System.ServiceModel.Description.DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = System.Int32.MaxValue;
foreach (var item in pHost.Description.Endpoints[1].Contract.Operations)
item.Behaviors.Find<System.ServiceModel.Description.DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = System.Int32.MaxValue;
System.ServiceModel.Description.ServiceDebugBehavior debugBehavior =
pHost.Description.Behaviors.Find<System.ServiceModel.Description.ServiceDebugBehavior>();
if (debugBehavior == null)
{
debugBehavior = new System.ServiceModel.Description.ServiceDebugBehavior();
pHost.Description.Behaviors.Add(debugBehavior);
}
debugBehavior.IncludeExceptionDetailInFaults = true;
}
When this._applyHttps is false, my service is accessible both by browser and reference in WPF project.
So I ask for help for the first time after enjoying for so long all your help without asking directly. What am I missing? As it's not hosted under IIS should I still need a cert to install on the server side only for the specific port?
Thanks guys in advance! And if someone has already answered this case I'm sorry for not finding it...
So like I had guessed I just needed to create a self-signed cert for the server side only and bind it to the port with netsh command.
No cert needed on client side meaning a quasi HTTPS WITHOUT CERT.
Note: I had it work on my computer. I will try to update this post once deployed in real environment and if I had to address any mistake.
And I know at some point we will go full cert on client side.
One stone at a time.