I am working on a simple site which has front-end and back-end server. Both servers are using the SAME SSL certificate. The SSL cert has DNS entries for FQDN and URL.
DNS=test.sample.com
DNS=FQDN01.dev.sample.com
DNS=dataservices.sample.com
DNS=FQDN02.dev.sample.com
Tech Stack
Front end = ASP.NET Core
Back End = .NET Core
IIS 10.
Windows 2016
When I call the data services from front-end it throws 404 error.
Then I removed certs from both the servers and added a new certificate which has only FQDN and no DNS for URL endpoint. Configured my code to call the data services using FQDN and magic - it started working!!!
Question - Are there any issues from .NET Core to use the same certificate on both servers? I am not IIS Admin or SME. Not sure how the bindings work. Any help will be greatly appreciated.
This is the snippet which calls the dataservices from front-end:
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
handler.ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => {
return true;
};
Client = new HttpClient(handler);
BaseUri = AppConfiguration.Configuration["DataServices:ServerConnection"];
Related
I need to implement solution Desktop Client + Application server (Web Service) in .NET.
The Client shall Authenticate against Active Directory (Kerberos Single Sign On) and forward its verified Active Directory identity to Web Service (NET Web API or WCF).
Web-service should verify that the Client is signed against Active Directory. Both computers (Client and server) are running in one AD domain.
I suppose that this can be implemented using WCF (see code here), but today NET Web API is preferred over Windows Communication Foundation. It is possible to implement it in ASP Web API as well?
Similar question not answered is here.
Yes, it is possible. The answer is here: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/integrated-windows-authentication
The API can use Windows authentication. The authentication is handled by IIS, as long as you have your web.config setup right, as described in that article.
From your application, you just need to tell it to pass the Windows credentials by using the UseDefaultCredentials property:
HttpClientHandler handler = new HttpClientHandler() {
UseDefaultCredentials = true
};
HttpClient client = new HttpClient(handler);
Is there a way to configure Fiddler 4.6 to capture traffic from one instance of IISExpress running on my Dev machine to a second IISExpress instance running on the same Dev machine?
I am using VS 2017 with one web site that is accessing some Web API methods on a second site running on another instance of IISExpress.
All of the browser to server traffic is captured fine, but I need to go from site to site to test some API calls.
The question is not so clear, but if you wants to communicate one IIS with another, you need to add a proxy like in the example:
var httpClientHandler = new HttpClientHandler
{
Proxy = new WebProxy("http://localhost:8888", false),
UseProxy = true
}
For more info take a look at the Fiddler docs
I have created a self-hosted WCF RESTful service with basic http authentication that runs over https with a self-signed SSL certificate. Everything works fine. Users access the service operations via a web browser.
The problem is that my customer now wants the service users to authenticate with BOTH basic authentication (user name + password) AND a certificate. I have not been able to achieve this.
I have seen that it could be possible to have multiple authentication schemes in WCF 4.5. I have looked into this but to no avail.
I have also come across this post (see the last answer), but when I tried it I got this error:
"An exception occurred: HTTPS listener factory was configured to require a client certificate and the authentication scheme 'Basic'. Only one form of authentication can be required at once."
My configuration is done in code, and here is what it looks like (this is the version that works):
Uri baseAdress = new Uri("https://localhost:8446/");
WebServiceHost host = new WebServiceHost(typeof(RestService));
WebHttpBinding wb = new WebHttpBinding();
wb.Security.Mode = WebHttpSecurityMode.Transport;
wb.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
host.AddServiceEndpoint(typeof(IRestService), wb, baseAdress);
host.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();
host.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
host.Description.Endpoints[0].Behaviors.Add(new WebHttpBehavior { HelpEnabled = true });
host.Open();
Thanks for any tips,
Multi auth on a single endpoint is for web hosted scenarios (not selfhost). You can configure this in web host by saying clientCredentialType='InheritFromHost' and set all the auth schemes that you want to set for that particular endpoint in vdir authentication. Check out this documentation for title "Multiple authentication support".
Multiple Authentication Support
Support has been added to support multiple authentication modes, as supported by IIS, on a single WCF endpoint when using the HTTP transport and transport security. IIS allows you to enable multiple authentication modes on a virtual directory, this feature allows a single WCF endpoint to support the multiple authentication modes enabled for the virtual directory where the WCF service is hosted.
I've seen about 1000 posts on StackOverflow, blogs, and other sites, but none have been able to shed light on the problem I'm having.
Setup:
WCF self-hosted service (NOT IIS) using .NET Framework 3.5 (sorry, can't upgrade), WebHttpBinding
A single endpoint using WebGet in the interface
NO .config files -- everything is being created programmatically
The service is bound to a custom port and NOT sharing a port with any other service or website
Deployment targets:
XP SP3, 2003, Vista, 7, 8, 2008
Problem: On Vista, 7, 8, 2008 I have no problems. I'm getting the service up and running on HTTP as well as HTTPS with a self-signed certificate bound to localhost as well as the machine name on a custom port.
BUT on XP, I can only get things working on HTTP, so I know the service itself is working properly. On HTTPS, I'm not able to make a connection because of an SSL failure.
If I hit the URL directly in a browser, I see an SSL exception.
In IE, it gives a warning that the certificate is not trusted. When I allow the exception, it gets to the service and executes. If I add https://localhost to trusted sites, I no longer see the warning and can hit the URL without issue.
When I hit the same URL in Chrome, I get an Error 107 ERR_SSL_PROTOCOL_ERROR and I cannot bypass it.
In Firefox, I get a ssl_error_rx_record_too_long error and it also cannot be bypassed.
I've gone through several permutations of certificates and methods of assigning them to the service (httpcfg, etc.), all with the same results (or worse). So, instead of going back and forth trying to figure out what I've done and picking apart my existing settings, I have 2 questions:
Is it even possible to create a trusted certificate on XP for localhost WITHOUT IIS and...
What's the best way to bind it to a self-hosted WCF service with everything being done programmatically? I repeat this because other attempts to get assistance on these issues invariably leads to folks telling me what to put in a config file.
Things to keep in mind: I already have this all working fine on Windows versions > XP/2003 under SSL with self-signed certificates, so I know the fundamentals are somewhat sound. I just can't seem to get the certificate set up under XP for localhost.
My answer is based on an assumption that if you were making WCF call from client code, you will get "Could not establish trust relationship for the SSL/TLS secure...." exception.
If that's true, I would recommend that you implement custom ICertificatePolicy and use it while making the WCF call. Here's a sample implementation.
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace Foo.bar
{
public class MyCertificatePolicy : ICertificatePolicy
{
public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
{
//Due an Invalid Certificate used in the site, we must return true to all invalid SSL Request. Alternately, write the logic to validate the server certificate
return true;
}
public static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
//Due an Invalid Certificate used in the site, we must return true to all invalid SSL Request
return true;
}
}
}
In my case i do it like this:
ServiceHost host = new ServiceHost(typeof(MyRequests), baseAddresses);
Then setup my metadata:
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpsGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
For Windows authentication and message secutiry i create and setup my ws binding:
WSHttpBinding b = new WSHttpBinding(SecurityMode.Message);
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
b.MaxReceivedMessageSize = Int32.MaxValue;
// auth setup
X509ClientCertificateAuthentication myAuthProperties =
host.Credentials.ClientCertificate.Authentication;
myAuthProperties.IncludeWindowsGroups = true;
// add endpoint
ServiceEndpoint endpnt = host.AddServiceEndpoint(typeof(IMyRequests), b, "MyService");
//GO!
host.Open();
I hope this will be helpful.
I need to call a WCF service programmatically. The service may be hosted with either NTLM or Kerberos authentication and needs to work under either. That is, if connecting to the service via Kerberos fails, then it should fall back to NTLM.
Here's the code I'm using for Kerberos auth (if relevant, the service is hosted in SharePoint 2010 and is being called from a web part):
public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
var binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
url = url.EndsWith("/") ? url + SiteMembershipAddress : url + "/" + SiteMembershipAddress;
var endpoint = new EndpointAddress(url);
var proxy = new SiteMembershipSvc.SiteMembershipServiceClient(binding, endpoint);
proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
return proxy;
}
Calling a method on the proxy when run in an NTLM environment gives the error:
The HTTP request is unauthorized with
client authentication scheme
'Negotiate'. The authentication header
received from the server was 'NTLM'.
Note: The URL may be in another web application on another server. I can't check what authentication the web part's web app runs under and assume it is the same as where the WCF service is hosted.
How can I (automatically or manually) ensure authentication falls back from Kerberos back to NTLM on failure?
Update:
As mentioned, the authentication error occurs when a web method is called. However I don't want to wait that long as there are several web methods in the service called from several places. I'd like to test the authentication at the point where the proxy is configured (in the code snippet above).
I've tried using proxy.Open() but that doesn't seem to cause the failure.
This is a bit off a curveball, but why is it falling back to NTLM. I've had significant difficulty with security in active directory and WCF all related to service principal names (SPNs).
Kerberos will fail if you are running the service as something other than Network Service unless you have an SPN declared in the domain for your service. To set the SPN you need the windows server administrative kit, which has the command setspn.
setspn -A HTTP\machinename domain\service_account
This will then allow Kerberos to share client credentials to your service within the domain.
Please do some reading, as you could break kerberos for any other services running on the same box depending on your setup.
(I recognize the original post is very old.)
Can you use something other than BasicHttpBinding (like WsHttpBinding)? According to this article, BasicHttpBinding is the one exception to the binding objects, in that it does not automatically negotiate. This is why allowNTLM has no effect.
I had the same error msg which I posted about here and solved it by creating a dynamic endpoint like so:
public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url)
{
//create endpoint
EndpointAddress ep = new EndpointAddress(new Uri(string), EndpointIdentity.CreateUpnIdentity("MyDomain\WCFRunAsUser"));
//create proxy with new endpoint
SiteMembershipSvc.SiteMembershipServiceClient service = new SiteMembershipSvc.SiteMembershipServiceClient("wsHttp", ep);
//allow client to impersonate user
service.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
//return our shiny new service
return service;
}
I was running the WCF service as a specific Active Directory user rather than the default NETWORK_SERVICE.
Try setting:
proxy.ClientCredentials.Windows.AllowNTLM = true;
According to this, AllowNTLM is now obsolete - i'm not sure what the correct alternative is.
I guess you are using the full dns name of the server as the address of the service. Try using the NETBIOS name or the IP address. That should force it to use NTLM.
If you know what protocol the server is using you can configure your app to use either the full name or the ip.
Hope that works for you.
If your Kerberos fail it will automatically default to NTLM, you don't have to do anything special.
http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part1.html
http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part2.html
http://www.windowsecurity.com/articles/Troubleshooting-Kerberos-SharePoint-environment-Part3.html
I haven't been able to find a way to do this automatically. Instead I've added UI to the application where the type of authentication must be chosen.