Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get LetsEncrypt working in ASP.Net Core Razor Pages?

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.

like image 618
Rob Avatar asked Nov 01 '25 19:11

Rob


1 Answers

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;
        }
    }
}
like image 179
Rob Avatar answered Nov 03 '25 23:11

Rob