ASP.NET - Help Testing & Debugging PKI Authentication - asp.net

I am working on an ASP.NET WebForms application, and I have been asked to switch from Windows Form Authentication to PKI Certificate Authentication; something I know very little about.
After reviewing various web posts and their code snippets, I thought I knew enough to at least begin sniffing a PKI Certificate (or any client certificate for that matter). Specifically I am using:
X509Certificate2 cert = new X509Certificate2(Page.Request.ClientCertificate.Certificate);
X500DistinguishedName dn = cert.SubjectName;
So I put a breakpoint on the 2nd line, hit F5 from Visual Studio. Debugging starts, but 'cert' is always null. I then realize that I have no Personal certs on my computer, so I download the Firefox add-on Key-Manager, create a dummy certificate, and try again with the same result, 'cert' is always null.
So then, I start screwing around with the command-line tool makecert, but still 'cert' is always null.
I am using IIS Express 7.5 for debugging purposes, tried both http and https.
What do I need to do to attach the personal cert to any web requests, and have them get picked up by my ASP.NET application?

Do you have IIS express setup to require client certs?
Please look here for a similar question/answer:
https://serverfault.com/questions/309690/how-to-configure-iis-express-to-ask-for-client-certificate
http://www.iis.net/ConfigReference/system.webServer/security/authentication/iisClientCertificateMappingAuthentication

Related

.NET Core 2.2 with Identity Server 4 SameSite Cookie Changes Issue

I have a Single page web application with consists of the following
Angular 8 Front End
.Net Core Web Api Back End
.Net Core Identity Server Authentication Server
I recently started to see a few warnings in my console which reads - "A cookie associated with a cross-site resource at "" was set without the 'SameSite' attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with 'SameSite=None' and 'Secure'.
So based upon this a did a little bit of research and landed on the following article, which happens to explain everything that is going on in detail.
Explanation of Cookie Issue
I read the article over several times and think I have a grasp of it, but still I am struggling on one simple aspect of it. There is a few areas where they ask you to add some code to your "Project". My question is (being still somewhat of a newbie with Identity Server and its inner workings), is what is the "Project" they are referring to. I am not exactly sure where to put the code they provide in order to fix the issue.
For me its not so obvious on where exactly to put the provided code. I have 2 Visual Studio solutions - one representing my authentication server (Identity Server) and one for my Web Api. Which of these solutions' Startup.cs files do I add the code solution?
If I add it to my Identity Server project, my confusion is that I am not using any "Cookie Based Authentication" so there exists nowhere in my identity server project which I have a place that sets a cookie and I know part of the solution, mentioned in the article, is to add a cookie which is both "Secure" and is set to "Same-Site=None". Where in the project do I create this type of cookie?
One more thing I did notice is that once the cookies are set they are not being deleted when a logout is performed.
Keep in mind that these issues are only occuring on a MacOS running Google Chrome. If I run my application on a Windows PC, I still see the warnings, but I am able to log out and clear all existing cookies
You will get below console warring in Google Chrome and your Identity server failed to redirect to Client that could be React App or Angular App for Chrome version 80.
A cookie associated with a resource at was set with SameSite=None but without Secure. It has been blocked, as Chrome now only delivers cookies marked SameSite=None if they are also marked Secure. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5633521622188032.
To Fix this , you need to do changes mention in below link -
https://www.thinktecture.com/en/identity/samesite/prepare-your-identityserver/
NOTE : For .Net Core 2.2 , set SameSite = (SameSiteMode)(-1) , For .Net Core 3.0 or above , set SameSite = SameSiteMode.Unspecified
Also , for Chrome 80 version , add this extra condition -
if ( userAgent.Contains("Chrome/8"))
{
return true;
}
IdentityServer will always create cookie when you login.
You can read more here - http://docs.identityserver.io/en/3.1.0/topics/signin.html
It mean identityserver use cookie to authenticated user
You can configure same site cookie as follow
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie("Cookies", options =>
{
options.Cookie.SameSite = SameSiteMode.Lax;
});

IdentityModel.OidcClient library doesn't seem to work with UWP

We are using ASP.NET Identity with IdentityServer4. We've added a Client to use with Azure AD. This works great within a web page, that part is working.
Our end goal is a UWP app, so we found the IdentityModel.OidcClient which has a UWP sample. This sample has two browser classes. We configured HTTPS, but the WabBrowser class now refuses to connect to the site at all. If I change the config to hit https://demo.identityserver.io then it works, but all the other config is the same, so I'm not sure what the problem could be. It shows an error message in the pop up browser that it could not connect.
I looked at the SystemBrowser class, but this logs in fine, then the browser window does not close, and even if we close it, the code doesn't move on to get back a result. Looking at the source, this is not surprising, it calls:
Launcher.LaunchUriAsync(new Uri(options.StartUrl));
and that's all. The RedirectUri is not passed in, and mechanism appears to exist to use it. So, the behaviour we see appears to be the extent of what the class can do.
Looking at the console .NET Core sample, it has a SystemBrowser class that works. I updated the UWP sample to use the Fall Creators Update and was able to bring in the ASP.NET Core dlls needed to compile this code. It sets up a class like this:
public LoopbackHttpListener(int port, string path = null)
{
path = path ?? String.Empty;
if (path.StartsWith("/")) path = path.Substring(1);
_url = $"http://127.0.0.1:{port}/{path}";
_host = new WebHostBuilder()
.UseKestrel()
.UseUrls(_url)
.Configure(Configure)
.Build();
_host.Start();
}
and I can confirm this gets called only once, but even if I hard code an unused IP address, I get an error that the IP is in use.
So, at this stage, the sample that exists for UWP works for the demo server but not for ours (I suspect an HTTPS issue, but that's not the error I get), and importing code that works for a Core sample, does not work either. I've spent a couple of days on this and would appreciate a nudge in the right direction.
So, to recap, the WabBrowser seems the best bet but, for my localhost IdentityServer I get this:
and if I try to use a .NET Core library that works elsewhere, it thinks a port is in use. I suspect I need to work out why WabBrowser can't connect to my local site. I have turned off Fiddler. I can browse to my https URL and get a disco document, in the browser, at https://localhost:44305/.well-known/openid-configuration.
There are extra steps necessary to enable localhost in the Web Authentication Broker -
https://msdn.microsoft.com/en-us/library/windows/desktop/jj658959%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
This website gave me the fix. Here is a synopsis:
Remove loopback isolation
For security and reliability reasons, UWP applications are not allowed to send requests to the loopback interface. While Visual Studio automatically creates exemptions for debugged apps, this feature won't be helpful in this case, as the authentication broker always executes in a separate process.
If you see this (cryptic) error message in your Windows event logs, then you're likely facing this issue:
AuthHost encountered a navigation error at URL: [...] with StatusCode: 0x800C0005.
One option to fix it is to use the loopack exemption utility developed by Eric Lawrence. It's natively included in Fiddler 4 but can also be downloaded as a standalone software. To allow the authentication broker to communicate with the loopback interface, exempt the applications starting with microsoft.windows.authhost and save your changes:
If everything was properly configured, you should now see the login/consent page returned by your server.

The authentication endpoint Kerberos was not found on the configured Secure Token Service

I've encountered a challenge regarding internet-facing deployment installation for CRM using a AD FS server. After the setup is complete, users are able to access the CRM server - but when trying to run custom pages the following error message is prompted:
"The authentication endpoint Kerberos was not found on the configured Secure Token Service!"
I've found several solutions on the internet for this issue:
First I found a KB article from Microsoft providing a possible
solution, this involves updating MEX endpoints by running a provided
PowerShell script.
(https://support.microsoft.com/en-us/help/2828015/configuring-ad-fs-2.1-with-microsoft-dynamics-crm-2011).
But this doesn't seem to be the issue.
Another solution could be to update the CRM rollup version (currently have version 14 installed, latest is version 18) - this is something that I want to avoid as it might lead to further issues.
Have anybody else encountered a similar issue, and in that case how did you solve it?
I have just spent last few days to figure this exact same error message and it turned out that it was the "Domain" attribute in crm connection string. Copied my answer to my own question at the Microsoft Dynamics CRM community forum here:
"Well, I found the culprit - it was the Domain attribute in the connection string:
For connecting from outside the domain, it does not like to have a Domain in the connection string:
Connection string format 1 (without Domain attribute): "Authentication Type=Passport;Server=https://devcrm.myco.com;Username=devuser#myco.com;Password=pwd" - this works both inside and outside the domain "myco.com"
Connection string format 2 (with Domain attribute): "Authentication Type=Passport;Server=https://devcrm.myco.com;Domain=myco;Username=devuser#myco.com;Password=pwd" - this only works inside the domain myco.com but NOT outside (exception: The authentication endpoint Kerberos was not found on the configured Secure Token Service!)

The key is in the Xrm.Client.CrmConnection.ClientCredential:
If Domain is NOT specified in the connection string, when connecting from outside domain, Xrm.Client.CrmConnection.ClientCredentials.UserName is populated whereas the ClientCredentials.Windows.ClientCredentials.UserName is empty.
But if the Domain is specified, Xrm.Client.CrmConnection.ClientCredentials.UserName becomes null and Xrm.Client.CrmConnection.ClientCredentials.Windows.ClientCredentials.UserName populated, which led to the service trying to authenticate user as a Windows AD user so of course it would fail when running app from outside Windows domain. And it explains why the same app works inside the domain even with Domain specified in the connection string.
For more detail, refer here for my original post asking for help in Dynamics CRM Forum

Why won't OAuth work on web server?

I have an ASP.Net web application running on Windows Server 2012, and need to make calls to social networking sites using oauth to generate some of the page content. Everything works on my development machine, but I can't even get a single response back ("unable to connect to the remote server" error).
I disabled the firewall to test that. No luck. I created a console application to test it that way. A simple HttpWebRequest will get the html for any page I throw at it, but not any oauth request. I've used different libraries to try to achieve this, including Linq2Twitter, Spring.Social, and HigLabo. All work locally, but not on the server. I've found nothing useful in the server event log.
Can anyone give me some clues what might be happening?
EDIT: Here's some code I'm using with the HigLabo library to try to retrieve the user timeline.
using HigLabo.Net.Twitter;
var cl = new TwitterClient(consumerKey, consumerSecret, accessToken, accessTokenSecret);
var rr = cl.GetHomeTimeline();
foreach (var r in rr)
{
//Console.WriteLine(r.CreatedAt + ":" + r.Text);
}
I'm aware that accessToken & accessTokenSecret aren't/shouldn't be necessary for a simple timeline read, but this is just to make sure it works first.
This turned out to be a firewall issue, as had been suspected. But not the server firewall. This was a problem with the ISP. They had an internal firewall that was blocking all traffic to/from the social network sites. They were able to resolve it quickly with a phonecall, but it was not a coding or configuration error on my part.

Certificate Trust Lists and IIS7

I need to generate a CTL for use with IIS7.
I generated a CTL file using MakeCTL (on Win2k3 SDK) and put only my own RootCA certificate in the CTL.
However, when I then use adsutil.vbs to set my website to use this CTL, I get:
ErrNumber: -2147023584 (0x80070520)
Error Trying To SET the Property: SslCtlIdentifier
I'm using adsutil.vbs like this:
cscript adsutil.vbs set w3svc/2/SslCtlIdentifier
where is the friendly name of the CTL
The problem is, I am not able to set a friendly name. At the end of the wizard it says "Friendly Name: ".
In IIS6 I can create a CTL with a friendly name (showing in Certificates MMC) but if I export it from there, when I import it, it no longer has a friendly name.
Can anyone show me how to do it please?
This should work on IIS 7.0 but probably not on IIS 7.5.
Let us know if this page is helpful please - http://www.rethinker.net/Blog/Post/14/How-to-Create-and-Use-a-CTL-for-IIS-7-0
I'm experiencing exactly the same problem and am having the same trouble finding an answer.
There appears to be no documented way to create a friendly name for Certificate Trust Lists using MakeCTL. And the only documented way to add a CTL to IIS7 uses the adsutil script Neil references above, yet it requires a friendly name. I assume we could dig into a programatic way to do this but I'm not looking to get that deep.
The core of this problem is that IIS7 seems to have lost favor for CTL's, else it would have some UI support for them. Are people using some alternative to CTL's in combination with Client Side Certificates?
I find it odd this isn't a bigger problem for IIS7.
Update:
I finally came back to this and have figured out the Friendly Name issue. To get a friendly name assigned you must store the CTL in the Certificate Store rather than to a file (I had always used the file approach previously). So, using MakeCTL in the wizard mode (no arguments) and choosing to 'Certificate Store' on the 'Certificate Trust List Storage' page results in a new page that let's you specify a Friendly Name.
So I now have a CTL in the 'Intermediate Certification Authorities' certificate store of LocalMachine. Now I am trying to use 'netsh http add sslcert' to assign the CTL to my site.
Before I could use this command I had to remove the existing SSL cert that was assigned to my site for server authentication. Then in my netsh command I specify the thumbprint of that very same SSL cert I removed, plus a made up appid, plus 'sslctlidentifier=MyCTL sslctlstorename=CA'. The resulting command is:
netsh http add sslcert ipport=10.10.10.10:443 certhash=adfdffa988bb50736b8e58a54c1eac26ed005050 appid={ffc3e181-e14b-4a21-b022-59fc669b09ff} sslctlidentifier=MyCTL sslctlstorename=CA
(the IP addr is munged), but I am getting this error:
SSL Certificate add failed, Error: 1312 A specified logon session does not exist. It may already have been terminated.
I am sure the error is related to the CTL options because if I remove them it works (though no CTL is assigned of course).
Can anyone help me take this last step and make this work?
UPDATE 01-07-2010: I never resolved this with IIS 7.0 and have since migrated our app to IIS 7.5 and am giving this another try. I installed IIS6 Compatibility on my test server and tried the steps documented here using adsutil.vbs. I immediately ran into this same error that Niel did above:
ErrNumber: -2147023584 Error trying to SET the Property: SslCtlIdentifier
when running this command:
adsutil.vbs set w3svc/1/SslCtlIdentifier MyFriendlyName
I then went on to try the next adsutil.vbs command documented and it failed with the same error.
I have verified that the CTL I created has a Friendly Name of MyFriendlyName and that it exists in the 'Intermediate Certification Authorities\Certificate Trust List' store of LocalComputer.
So once again I am at a dead standstill. I don't know what else to try. Has anyone ever gotten CTL's to work with IIS7 or 7.5? Ever? Am I beating a DEAD horse. Google turns up nothing but my own posts and other similar stories.
Update 6/08/10 - I can now confirm that KB981506 resolves this issue. There is a patch associated with this KB that must be applied to Server 2008 R2 machines to enable this functionality. Once that is installed all works flawlessly for me.
The question is about IIS7, but for anyone looking for this information - from IIS8 you no longer need to use CTLs, but rather use "Client Authentication Issuers" in the certificate store.
This is documented in more detail: http://technet.microsoft.com/en-us/library/hh831771.aspx

Resources