How do I get ASP.Net Core Razor Pages to comply with what letsencrypt.com requires for "handshaking?" I had tried using a solution that works with MVC but the way the Route was done didn't work in Razor Pages.
I started with this excellent tutorial from the Royal Jay site. Adding a Route to the web app is where my solution diverges from a normal MVC application. Being that you have to get a new SSL certificate every 3 months, I made this solution configurable so that changing the key end up being pretty easy.
In my appsettings.json file, I added the following entry for LetsEncrypt:
"LetsEncrypt": {
    "Key": "the entire key from your letsencrypt initial session goes here"
  }
The entry here is the entire key that you receive back from the letsencrypt-auto executable (it's the second red-underlined section in the Royal Jay tutorial).
In order to pass the configuration property through to the page that will handle the handshake from LetsEncrypt, I created a new interface and small class that will hold the key:
Interface:
using System;
using System.Collections.Generic;
using System.Text;
namespace Main.Interfaces
{
    public interface ILetsEncryptKey
    {
        string GetKey();
    }
}
Class:
using Main.Interfaces;
namespace Main.Models
{
    public class LetsEncryptKey : ILetsEncryptKey
    {
        private readonly string _key;
        public LetsEncryptKey(string key) => _key = key;
        public string GetKey() => _key;
    }
}
Then in the startup.cs file, I've added these lines into the ConfigureServices section:
    var letsEncryptInitialKey = Configuration["LetsEncrypt:Key"];
    services.AddMvc().AddRazorPagesOptions(options =>
    {
        options.Conventions.AddPageRoute("/LetsEncrypt", $".well-known/acme-challenge/{letsEncryptInitialKey.Split('.')[0]}");
    });
    services.AddSingleton<ILetsEncryptKey>(l => new LetsEncryptKey(letsEncryptInitialKey));
Now the only thing we have left to do is to create the page that will handle the handshake request and return the response.
LetsEncrypt.cshtml.cs:
using Main.Interfaces;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPages.Pages
{
    public class LetsEncryptModel : PageModel
    {
        private readonly ILetsEncryptKey _letsEncryptKey;
        public LetsEncryptModel(ILetsEncryptKey letsEncryptKey)
        {
            _letsEncryptKey = letsEncryptKey;
        }
        public ContentResult OnGet()
        {
            var result = new ContentResult
            {
                ContentType = "text/plain",
                Content = _letsEncryptKey.GetKey()
            };
            return result;
        }
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With