How and why to take the long way for installing ADFS

I use several applications in my LAN - a bug/issue/ticket tracker, a knowledge base, Git and Mercurial servers, a continuous integration server… Administering users across each of them can be a lot of work, especially if it's unnecessary: and I do have a Windows domain and an Active Directory server which is usually supposed to be the central point for user authentication. If your applications can authenticate against an Active Directory, user centralization is just a matter of configuring them - well, each of them, which could be easy but also it could not be. The Orchard Core software I intend to use outright doesn't support AD authentication other than Azure AD, but it does support OpenID, so one way to integrate it would be to install the AD Federation Services. This then opens up several authentication possibilities, from OpenID through OAuth to SAML and I don't know what else… It raises its compatibility, and if you ask me it should come preinstalled with AD.


But not only that it doesn't, it requires you to take five steps back in order just to start, and first couple of these steps deal with SSL certificates: if your service is public you probably have no choice but to buy a commercial certificate and be done with it. But for an intranet - especially with several web applications - it may be worth it to implement your own local certification authority. This is not as hard as it seems if you do it the right way, and as a result you will be able to create your own certificates easily for any purpose. (If you don't, it will be hard).


And this was the main purpose of this post, to record the dos and don'ts of such an endeavor. I won't go into much details here, instead I'll provide links to pages with instructions on how things are done with comments and guidance as to what worked for me and what didn't and especially for the things that you must do and those that aren't mandatory, since much of the documentation deals with all the available options, not stating exactly what the procedure would be for an "ordinary" basic setup. I did this with a Windows 2019 server, but I think that for anything involving Windows 2012 or newer the procedures should be similar.


Certificate Authority


Installing a certificate authority (CA), I think, was quite uneventful as I don't remember what I did: this probably means I had no big problems. I think the official Microsoft guide would suffice for this. One detail you may want to pay attention to is the validity of your root certificate, I set it to hundreds of years… Which might be bad practice, but for an intranet I don't think it's too big of a problem: if someone manages to steal your root certificate, they will probably use it immediately and having it expire after five years won't matter much. On the other hand, when it expires after five years, you'll have a lot of work renewing all the certificates you issued and reconfiguring apps to use them (which, admittedly, may not be a lot of work if you have a couple of intranet apps).


The root certificate's private key should be exportable (it may well be so by default?) and you should probably export it for backup. Also, make it SHA2 (or SHA256, whatever) if you can - this also should be the default on newer Windows. Newer software like the Chrome browser complain (with NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM) if you use a SHA1 certificate for SSL - not that it would matter in this case since this is a root certificate and you can produce an SHA2 SSL certificate off an SHA1 root - but it's better to be up to date from the start.



Since this is a self-signed root certificate that nobody knows of, you should accept it as a trusted root on all of the computers that will access your intranet sites - that way, when you generate SSL certificates for your sites, they will be automatically accepted because they come from a trusted root. For this, you need to export the root certificate without the private key, distribute it to your intranet users and make them install it into their Trusted Root Certification Authorities store (or, of course, do it for them).


Some of the guides say that you have to get the certificates right the first time since it isn't possible to change anything afterwards. From what I've seen, this is not true and I think you can generate a new root certificate and delete the old one: but, if you generated SSL certificates using the old root, you'll need to regenerate all of them.


Generating SSL certificates


I found this guide that describes the full procedure including setting up the certificate template:


You need to create the template only once and with that, creating a SSL certificate is trivial, just as described on the page: none of that IIS nonsense with creating a request and then accepting it.


If you want your certificates to last longer than the default two years, read the solution here:


With this, to create a certificate you just need to fill in its attributes. For SSL certificate, this means setting the common name and one or more DNS alternative names and not much else. When creating a certificate for a single web app, just use its domain qualified name (for example, myapp.mydomain.local) for both and you're done. One interesting thing that you could also do is issue a wildcard certificate (like *.mydomain.local) which can then be used for each of the sites. You do this in exactly the same way, just use the same wildcard name for common and alternative name.


Creating a certificate for the AD FS service is similarly straightforward, just issue a certificate for your federation service address (for example, fs.mydomain.local). You may also want to add "certauth.fs.mydomain.local" to the alternative names, I'm not sure when one needs it (I don't think I did - it's for certificate authentication) but one of the final steps in ADFS installation displays a warning if you don't. Depending on further requirements - if you need one for token signing etc. - you might need to issue additional certificates with different characteristics. The service certificate seems to be the only one required for AD FS installation.


Installing Active Directory Federation Services


On Windows 2016 and newer, ADFS does not work through IIS but cooperates with it. This means that some ADFS paths (like, fs.yourdomain.local/adfs/fs/federationserverservice.asmx) will be reachable through any of the IIS virtual sites… I don't know if that would work for ADFS: Since I have several web applications, I assigned multiple IP addresses to the server and limited IIS to use only a couple of them (one should suffice). So it might be a good idea to add a separate IP for ADFS and add this to your DNS. But don't let IIS bind to it. Also note that, in order to use an SSL certificate for a IIS site, you need to check "Require Server Name Indication" in the site's binding dialog. Otherwise, the selected certificate will be used across all sites in the IIS, including ADFS which will present a wrong certificate when accessing the FS site.


When you have the SSL certificate for your ADFS service, you can proceed to install the ADFS. I followed this guide (more or less, I skipped the powershell gMSA part since it didn't work and I didn't even know what it was):


Here's how you change the FS service certificate:


A neat trick - to display all the URLs that ADFS registered, run this from the command prompt:


netsh http show urlacl


To check if ADFS is running:


And that's it… The ADFS is only installed and it isn't configured for anything, we covered the configuration for Orchard Core in another post. But now you have a way to integrate your AD authentication with a greater number of applications and do all kinds of wonderful (and overtly complicated) authentication schemes until your brain melts.

Finding ASP.Net Core Error Logs on IIS

I don't think there are many IT tasks more frustrating than troubleshooting Microsoft technologies on Windows. These things are simply not made so that anyone knows what's going on, and the really brutal stuff happens when you combine Windows, IIS and Asp.Net Core. Correct me if I'm wrong, but by default it's not configured to report any errors anywhere, unless you run it in a console. And if you want to troubleshoot a deployment that isn't working, be prepared to spend hours finding out what the hell has happened. NOT fixing the error, just identifying it.

There's a myriad of places where logged messages could appear, and this seems to depend on the error type: if you knew what's going on you'd probably be able to guess where the message is, but in that case you wouldn't need the error logs in the first place. And if you ask Google, you'll find sites that list these options for you. I'll try to list them here:

  • IIS access log - useless for this as it lists successful requests
  • HTTPERR - for errors, but in my IIS it's empty even if my web app falls apart. It's in C:\Windows\System32\LogFiles\HTTPERR
  • Event Log - they say that Asp.Net errors appear in the Application section here. But Asp.Net Core doesn't seem to respect that.
  • Detailed error page - this doesn't seem to exist anymore (even though it can be turned on in IIS configuration). Some sites suggest that the only solution is to implement our own!
  • Adding a custom logger - serilog works great, but I need to change the source code to use it. Why would that be necessary? I was unable to find a way to just configure logging to save messages to a file - it can do this to console, but to a file, it seems, not. There isn't even a standard config entry for the log file name, you have to add your own configuration logic.
  • Failed request tracing - this, in fact, does produce some results but again it also hides a lot. It seems to be good for errors in the IIS pipeline, but when my Asp.Net Core application broke, the trace showed a warning (!) that a component in the pipeline returned a 500 internal server error. But what error exactly, it didn't say.
  • Stdout error loging in web.config - finally something useful, it can be turned on without modifying the code and it helped me see the actual error, after 4-5 hours of fighting the damn thing (note that you need to create the log folder yourself and possibly give the web app permissions to write to it). But this is seemingly just part of the solution, I'm guessing it works only if Asp.Net Core works. If not, see above.
Subscribe to this RSS feed