RichardSoeteman.NET

Implement Umbraco Delivery API Enabled check

Published 16 August 2024

This week I implemented some API endpoints for SEOChecker so people can retrieve redirects in their headless environments. Of course I want to use the same settings Umbraco uses to enable the Delivery API and an API key to restrict access. Instead of re-inventing the wheel I wanted to see how easy it was to re-use (most) of the standard functionality. 

Validate API Credentials in the controller

Implementing the validation in the controller was actually pretty straight forward. All I needed was to inject the IApiAccessService in my controller. This service has the HasPublicAccess method which validates if the credentials for the delivery API are met.

    [ApiVersion("1.0")]
    [HttpGet("/seochecker/api/v1/redirects/getall")]
    [ProducesResponseType(200)]
    [ProducesResponseType(401)]
    [MapToApiVersion("1.0")]
    public ActionResult<IEnumerable<RedirectModel>> GetAll()
    {
        if (!apiAccessService.HasPublicAccess())
        {// not enabled or API key is wrong
            return StatusCode(StatusCodes.Status401Unauthorized);
        }
        return Ok("Return whatever you like");
    }
Adding API key to the Swagger definition

In the sample above  when public access is set to false in appsettings.config it will compare the value from Api-Key HttpHeader with the configured value in appsettings.config. Of course you want to have this option in your swagger definition as well. To achieve that I've implemented this operationfilter. 

public class DocumentationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
            AddApiKey(operation);
    }

    private void AddApiKey(OpenApiOperation operation) =>
        operation.Parameters.Add(new OpenApiParameter
        {
            Name = "Api-Key",
            In = ParameterLocation.Header,
            Required = false,
            Description = "API key specified through configuration to authorize access to the API.",
            Schema = new OpenApiSchema { Type = "string" }
        });

}
Adding the operation filter to the Swagger definition

Last part is to add the DocumentationFilter to the Swagger options

public class ConfigureSwaggerGenOptions : IConfigureOptions<SwaggerGenOptions>
{
    public void Configure(SwaggerGenOptions options)
    {
        //Only when API is updated
        options.SwaggerDoc(
            "seochecker",
            new OpenApiInfo
            {
                Title = "SEOChecker Headless Api",
                Version = "Latest",
                Description = "Headless Operations for SEOChecker"
            });
        options.OperationFilter<DocumentationFilter>();
    }
}
End result

When you go to the Swagger url you see a nice form where you can use the end point and specify the API-Key (when needed) and that was everything needed to get this to work.

image