Welcome to the navigation

Pariatur, velit duis occaecat ut aliqua, mollit veniam, fugiat cupidatat qui laborum, incididunt exercitation do dolore anim ut magna ipsum elit, aliquip tempor culpa dolore. Mollit aliquip et fugiat proident, sed enim duis ea ex reprehenderit cupidatat velit in ut nostrud in consectetur sit deserunt anim aute ut in commodo

Yeah, this will be replaced... But please enjoy the search!

Speeding Up Local Development with a Fake OpenID Authentication Handler

Setting up OpenID authentication can be painful in development environments – especially when the identity server isn’t publicly accessible or you’re still waiting on client configuration.

To solve this, we created a local authentication scheme that behaves like OpenID but doesn’t require any network connection or external setup. It lets developers instantly sign in as a fake user with predefined roles – perfect for local testing and remote development.

Here’s the simplified implementation:

// usings
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;

internal class LocalAuthenticationSchemeOptions : AuthenticationSchemeOptions { }

internal class LocalAuthenticationSchemeHandler(
    IOptionsMonitor options,
    ILoggerFactory logger,
    UrlEncoder encoder)
    : AuthenticationHandler(options, logger, encoder)
{
    protected override async Task HandleAuthenticateAsync()
    {
        var claims = new[]
        {
            // add any claim you need, these are for Optimizely CMS
            new Claim(ClaimTypes.Role, "Admins"),
            new Claim(ClaimTypes.Role, "CmsAdmins"),
            new Claim(ClaimTypes.Role, "CmsEditors"),
            new Claim(ClaimTypes.Name, "John Doe")
        };

        var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Local"));
        var ticket = new AuthenticationTicket(principal, Scheme.Name);

        return await Task.FromResult(AuthenticateResult.Success(ticket));
    }
}

For Optimizely you'll need to ensure that the claims added correspond with what configs you have in you appsettings, see https://docs.developers.optimizely.com/content-management-system/docs/virtual-roles.

And we wire it up conditionally during startup:

if (environment.IsDevelopment())
{
    services.AddAuthentication("LocalAuthentication")
        .AddScheme<LocalAuthenticationSchemeOptions, LocalAuthenticationSchemeHandler>(
            "LocalAuthentication",
            opts => { });
}
else
{
    // Your OpenID-implementation, may be services.AddAuthentication...
    services.AddOpenIdServicesConfiguration(configuration, logger);
}

This setup means:

  • Local devs can log in instantly, without OpenID.

  • Full control over user identity and roles — test as any role.

  • No dependency on external servers, making remote/offline dev possible.

  • Production remains secure, since the handler is only active in Development mode.

It’s a small addition, but it dramatically simplifies authentication workflows during development. Instead of waiting for OpenID configuration or tunneling into internal networks, developers can jump straight into building features.