For ASP.Net MVC or Web Forms, with certain Routing configs, you'll end up treating this URL as something for the Routing Engine to hand off to the MVC/Forms Handler, not a static file return. The result will be a 404 or a 503. The solution is surprisingly very simple:
If you haven't already, place the Challenge file:
- Create the necessary dirs -
.well-known
is tricky mostly because Microsoft is lazy, but you can either do it from cmdline or create the folder as .well-known.
and Windows Explorer will notice the workaround and remove the trailing period for you.
- Inside
\.well-known\acme-challenge
place the challenge file with the proper name and contents. You can go about this part any way you like; I happen to use Git Bash like echo "oo0acontents" > abcdefilename
Then make a Web.Config file in the acme-challenge dir with these contents:
<?xml version = "1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clear />
<mimeMap fileExtension = ".*" mimeType="text/json" />
</staticContent>
<handlers>
<clear />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule"
resourceType="Either" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>
Source: https://github.com/Lone-Coder/letsencrypt-win-simple/issues/37
Done. The file will start returning instead of 404/503 allowing the Challenge to complete - you can now Submit and get your domain validated.
Aside: The above code snippet sets the content-type to json, a historical requirement that is no longer relevant to letsencrypt. The current requirement is there is no requirement - you can send a content-type of pantsless/elephants and it'll still work.
More for Asp.Net
I like to redirect all HTTP requests back to HTTPS to ensure users end up on a secure connection even if they didn't know to ask. There are a lot of easy ways to do that, until you're using LetsEncrypt - because you're going to break requests for .well-known. You can setup a static method in a class, like this:
public static class HttpsHelper
{
public static bool AppLevelUseHttps =
#if DEBUG
false;
#else
true;
#endif
public static bool Application_BeginRequest(HttpRequest Request, HttpResponse Response)
{
if (!AppLevelUseHttps)
return false;
switch (Request.Url.Scheme)
{
case "https":
return false;
#if !DEBUG
case "http":
var reqUrl = Request.Url;
var pathAndQuery = reqUrl.PathAndQuery;
// Let's Encrypt exception
if (pathAndQuery.StartsWith("/.well-known"))
return false;
// http://stackoverflow.com/a/21226409/176877
var url = "https://" + reqUrl.Host + pathAndQuery;
Response.Redirect(url, true);
return true;
#endif
}
return false;
}
}
Now that can do a great job of redirecting to HTTPS except when LetsEncrypt comes knocking. Tie it in, in Global.asax.cs:
protected void Application_BeginRequest(object sender, EventArgs ev)
{
HttpsHelper.Application_BeginRequest(Request, Response);
}
Notice that the bool returned is discarded here. You can use it if you like to decide whether to end the request/response immediately, true meaning, end it.
Finally, if you like, you can use the AppLevelUseHttps variable to turn off this behavior if need-be, for example to test if things are working without HTTPS. For example, you can have it set to the value of a Web.Config variable.
%2E
? – rnevius