Skip to content

[Task] Add Plugin Authentication and Authorization Hooks #12

Description

@rian-be

Summary

Extend the AuthKit plugin contract with explicit hooks for configuring authentication schemes and authorization policies.

The goal is to allow plugins to participate in the host security pipeline through strongly typed ASP.NET Core abstractions while preserving deterministic configuration, plugin isolation, backward compatibility, and compatibility with the AuthKit security scheme contract.

This task introduces explicit integration points for:

  • authentication configuration through AuthenticationBuilder;
  • authorization configuration through AuthorizationOptions.

Plugins must be able to contribute security configuration without silently replacing unrelated host or plugin configuration.

Goal

Provide first class plugin APIs for:

  • registering authentication schemes;
  • configuring authentication handlers;
  • contributing authorization policies;
  • and integrating plugin defined security requirements with the AuthKit host.

The implementation must use the existing ASP.NET Core authentication and authorization infrastructure.

No custom authentication, authorization, or DI framework should be introduced.

Background

Plugins may implement functionality that requires their own authentication schemes or authorization policies.

Without explicit contract hooks, plugins must rely on:

  • host configuration code;
  • implicit registration;
  • direct modification of host startup logic;
  • or plugin workarounds.

This creates coupling between plugins and the AuthKit host.

The plugin contract should provide explicit hooks that allow plugins to configure security infrastructure using the same standard abstractions used by the host.

This is particularly important because AuthKit already defines security scheme abstractions through:

AuthKitSecuritySchemeDescriptor
AuthKitSecuritySchemeType
AuthKitApiKeyLocation

Authentication integration must remain consistent with those contracts where applicable.

Scope

B11. ConfigureAuthentication

Add an authentication configuration hook:

void ConfigureAuthentication(
    AuthenticationBuilder builder);

The plugin receives the host's actual AuthenticationBuilder.

The plugin may register authentication schemes and handlers using standard ASP.NET Core APIs.

B12. ConfigureAuthorization

Add an authorization configuration hook:

void ConfigureAuthorization(
    AuthorizationOptions options);

The plugin receives the host's actual AuthorizationOptions.

The plugin may add authorization policies and related configuration using standard ASP.NET Core authorization APIs.


B11. Plugin Authentication Configuration

Proposed Contract

Conceptually:

public interface IAuthKitPlugin
{
    void ConfigureAuthentication(
        AuthenticationBuilder builder)
    {
    }
}

The exact implementation should follow the existing IAuthKitPlugin style and target framework capabilities.

The hook must be optional for existing plugins.

Host Authentication Builder

The host must pass the actual AuthenticationBuilder used to configure application authentication.

Plugins must configure the same authentication system used by the host.

The host must not create:

Plugin AuthenticationBuilder

separate from the application's authentication configuration.

The expected model is:

Host AuthenticationBuilder
        │
        ├── Host schemes
        │
        ├── Plugin A schemes
        │
        ├── Plugin B schemes
        │
        └── Plugin C schemes

All supported authentication schemes must become part of the same application authentication infrastructure.

Authentication Scheme Registration

Plugins may register authentication schemes using standard APIs.

For example:

public void ConfigureAuthentication(
    AuthenticationBuilder builder)
{
    builder.AddScheme<AuthenticationSchemeOptions, MyHandler>(
        "MyPlugin",
        _ => { });
}

The plugin must not need to modify the host startup code directly.

Scheme Names

Authentication scheme names must be treated as globally significant within the ASP.NET Core authentication configuration.

The host must define collision behavior.
A plugin must not silently replace another scheme.

For example:

Plugin A → "CustomScheme"
Plugin B → "CustomScheme"

must not result in an accidental silent override.

The preferred behavior is an explicit configuration error unless the contract explicitly supports replacement.

The implementation should provide enough diagnostic information to identify:

  • the conflicting scheme name;
  • the plugin registering it;
  • and the existing owner where available.

Existing Host Schemes

Plugins must not silently replace existing host authentication schemes.

This includes host defaults such as:

DefaultAuthenticateScheme
DefaultChallengeScheme
DefaultForbidScheme

unless the host explicitly allows plugin to configure those defaults.

A plugin registering an additional scheme must not automatically become the default authentication scheme.
Default scheme selection remains an explicit host decision.

Authentication Configuration Order

Authentication hook invocation must be deterministic.

The order must not depend on:

  • filesystem ordering
  • assembly load order
  • dictionary enumeration
  • or undefined plugin discovery order.

The host must document the selected ordering mechanism.

Possible deterministic ordering strategies include:

  • explicit plugin priority;
  • explicit plugin order;
  • stable plugin identifier ordering.

The implementation must choose one consistent strategy.

Duplicate Invocation

The host must ensure that ConfigureAuthentication is not accidentally invoked multiple times for the same plugin configuration lifecycle.

Repeated plugin discovery or configuration must not register duplicate authentication schemes.

If the host supports rebuilding the application, each independent host instance may configure its own authentication system normally.


Relationship with the AuthKit Security Scheme Contract

Authentication configuration and the plugin security scheme descriptor are related but not identical.

A plugin declaring:

AuthKitSecuritySchemeType.Basic

does not automatically imply that the host should register new ASP.NET Core authentication handler unless the plugin or host configuration explicitly requires one.

Similarly, registered ASP.NET Core authentication scheme does not automatically define public plugin security descriptor.

The host must define how the two concepts are connected where integration is required.
The implementation must not silently infer unsupported mappings.

Examples:

MutualTls ≠ automatically any arbitrary ASP.NET authentication handler
Custom ≠ automatically Bearer
Session ≠ automatically ApiKey + Cookie

Any mapping between:

AuthKitSecuritySchemeType

and ASP.NET Core authentication configuration must be explicit.

Unknown or unsupported security scheme values must be rejected according to the Section F contract.

Authentication Failure Handling

Authentication configuration failures must be explicit.

The host must not:

  • silently skip plugin authentication scheme
  • silently rename conflicting scheme
  • silently replace an existing scheme
  • or silently map plugin defined scheme to another authentication mechanism.

If authentication configuration cannot be applied, application startup must fail according to the normal host configuration failure behavior.


B12. Plugin Authorization Configuration

Proposed Contract

Conceptually:

public interface IAuthKitPlugin
{
    void ConfigureAuthorization(
        AuthorizationOptions options)
    {
    }
}

The hook must be optional for existing plugins.

Host Authorization Options

The plugin must receive the actual AuthorizationOptions instance used by the AuthKit host.

The expected configuration model is:

Host AuthorizationOptions
        │
        ├── Host policies
        │
        ├── Plugin A policies
        │
        ├── Plugin B policies
        │
        └── Plugin C policies

The host must not create independent authorization policy containers for individual plugins unless explicitly required by the architecture.

Policy Registration

Plugins may register policies using standard ASP.NET Core APIs.

For example:

public void ConfigureAuthorization(
    AuthorizationOptions options)
{
    options.AddPolicy(
        "MyPlugin.Read",
        policy =>
        {
            policy.RequireAuthenticatedUser();
        });
}

The resulting policy must be available through the application's standard authorization infrastructure.

Policy Names

Authorization policy names are globally significant.
The host must define deterministic collision behavior.

A plugin must not silently overwrite a policy registered by:

  • the host;
  • another plugin;
  • or another configuration component.

For example:

Plugin A → "Admin"
Plugin B → "Admin"

must result in explicit, deterministic behavior.

The preferred behavior is rejection of conflicting ownership unless explicit replacement is supported by the contract.

Plugin Policy Namespacing

Plugins should use namespaced policy names where practical.

For example:

PluginName.PolicyName

Examples:

DevTokens.Read
DevTokens.Write
ExamplePlugin.Admin

The contract may define recommended naming convention.

The convention must not silently rewrite plugin provided policy name unless automatic namespacing is explicitly part of the contract.

Default and Fallback Policies

Plugins must not silently replace:

DefaultPolicy
FallbackPolicy

These policies affect the entire host.

Changing them should remain an explicit host-level decision.
If plugin configuration of global defaults is supported in the future, it should require explicit contract semantics.

This task should not implicitly grant plugins authority to modify global defaults.

Authorization Requirements

Plugins may use standard authorization requirements and handlers.
This task does not introduce custom authorization model.

Plugins should integrate through existing ASP.NET Core abstractions such as:

IAuthorizationRequirement
AuthorizationHandler<TRequirement>
AuthorizationPolicyBuilder

Required services should be registered through the existing plugin service configuration process.

Authorization Configuration Order

ConfigureAuthorization invocation must be deterministic.
Plugin discovery order must not become an accidental authorization configuration contract.

The selected ordering mechanism should be consistent with other plugin configuration hooks where possible.

Duplicate Invocation

The host must prevent accidental repeated invocation of authorization configuration.

The same plugin must not unintentionally register the same policy multiple times during one application configuration lifecycle.


Authentication and Authorization Pipeline Compatibility

B11 and B12 configure services.
They do not directly define middleware ordering.

The resulting host pipeline should continue to use the standard ASP.NET Core sequence:

Routing
    ↓
Authentication
    ↓
Authorization
    ↓
Endpoints

Pipeline placement itself is handled by B3–B5.

The authentication and authorization hooks introduced here must remain compatible with that pipeline.
A plugin requiring authenticated requests must not depend on an undefined middleware order.

Plugin Endpoint Integration

Plugin endpoints registered through B3 may use standard authorization metadata.

For example:

endpoints.MapGet("/plugin/data", handler)
    .RequireAuthorization("MyPlugin.Read");

The policy must already be available through the host authorization configuration before application execution begins.

A missing or invalid policy reference must produce normal explicit ASP.NET Core configuration/runtime behavior.

The host must not silently remove authorization metadata from plugin endpoints.


Backward Compatibility

This task is additive.

Existing plugins must continue to:

  • compile
  • load
  • configure services
  • and operate

without implementing either:

ConfigureAuthentication
ConfigureAuthorization

Default interface implementations may be used where appropriate.

For plugins that do not need custom authentication or authorization configuration, the hooks should safely perform no action.
Existing host authentication and authorization behavior must remain unchanged.

Adding these hooks must not:

  • change the host's default authentication scheme;
  • change existing authorization policies;
  • change default or fallback policies;
  • or modify existing plugin security behavior.

Existing Plugins

Existing plugins, including DevTokens, must continue to compile and load without modification.

A plugin that currently relies on an existing host authentication mechanism must not be forced to migrate solely because these hooks are introduced.


Plugin Isolation

Authentication and authorization configuration must preserve plugin isolation where possible.

The host must prevent or explicitly reject:

Plugin A replacing Plugin B's authentication scheme
Plugin A replacing Plugin B's authorization policy
Plugin A silently changing host defaults

Global security infrastructure remains shared, but modifications must be explicit and deterministic.

Diagnostic errors should identify the responsible plugin.


Error Handling

Failures must be explicit.

The host must reject or surface:

  • duplicate authentication scheme names;
  • duplicate authorization policy names;
  • invalid authentication configuration;
  • invalid authorization configuration;
  • unsupported security scheme mappings;
  • and unexpected plugin configuration failures.

The host must never silently:

Ignore scheme
Ignore policy
Rename scheme
Rename policy
Replace another plugin's configuration
Change the default authentication scheme
Map one security mechanism to another

unless such behavior is explicitly defined by the contract.


XML Documentation

All new public members must include complete XML documentation.

At minimum:

ConfigureAuthentication
ConfigureAuthorization

must document:

  • when the hook is invoked;
  • which host object is supplied;
  • that the object represents the actual host configuration;
  • that existing plugins are not required to implement the hook;
  • and that plugin configuration must not assume ownership of global defaults.

Testing Strategy

Tests should use dedicated sample plugins.

Authentication Test Plugin

The plugin should register unique authentication scheme:

TestPluginAuth

Tests should verify:

  • the scheme is registered;
  • the scheme is available through the host authentication system;
  • existing host schemes remain present;
  • duplicate scheme registration fails explicitly;
  • configuration is not invoked twice.

Authorization Test Plugin

The plugin should register a unique policy:

TestPlugin.Read

Tests should verify:

  • the policy is available through IAuthorizationPolicyProvider;
  • existing policies remain present;
  • duplicate policy registration fails explicitly;
  • configuration is not invoked twice.

Endpoint Integration

A test plugin may expose an endpoint requiring the plugin defined policy.

The integration test should verify:

Unauthenticated request
        ↓
Authorization challenge / failure

Authorized request
        ↓
Endpoint access

The exact authentication behavior depends on the test authentication handler.


Validation

B11. Authentication

  • ConfigureAuthentication(AuthenticationBuilder) exists.
  • Plugin receives the actual host authentication builder.
  • Plugins can register authentication schemes.
  • Registered schemes participate in the host authentication infrastructure.
  • Existing host schemes remain unchanged.
  • Plugin schemes do not automatically become default schemes.
  • Authentication scheme collisions are handled explicitly.
  • Invocation order is deterministic.
  • Duplicate invocation is prevented.
  • Unsupported security scheme mappings are explicitly rejected.
  • Authentication failures are surfaced explicitly.

B12. Authorization

  • ConfigureAuthorization(AuthorizationOptions) exists.
  • Plugin receives the actual host authorization options.
  • Plugins can register authorization policies.
  • Registered policies are available through standard ASP.NET Core authorization.
  • Existing host policies remain unchanged.
  • Policy collisions are handled explicitly.
  • Plugins cannot silently replace global default/fallback policies.
  • Invocation order is deterministic.
  • Duplicate invocation is prevented.
  • Authorization failures are surfaced explicitly.

Integration

  • Plugin authentication schemes work with plugin endpoints.
  • Plugin authorization policies can protect plugin endpoints.
  • Authentication and authorization remain compatible with the host middleware pipeline.
  • B11–B12 remain compatible with B3–B5.
  • Security scheme mappings remain compatible with Section F.

Compatibility

  • Existing plugins compile without modification.
  • Existing plugins load without modification.
  • Existing host authentication behavior remains unchanged.
  • Existing host authorization behavior remains unchanged.
  • DevTokens continues to compile and load successfully.
  • PluginContractValidator passes.

Documentation

  • All new public APIs have complete XML documentation.
  • Authentication scheme collision behavior is documented.
  • Authorization policy collision behavior is documented.
  • Default/fallback policy restrictions are documented.
  • Relationship with Section F security schemes is documented.

Build and Tests

  • dotnet build AuthKit.Plugins.Abstractions succeeds.
  • Build completes with zero warnings.
  • Relevant unit tests pass.
  • Authentication integration tests pass.
  • Authorization integration tests pass.
  • Duplicate scheme tests pass.
  • Duplicate policy tests pass.
  • Plugin endpoint security tests pass.
  • Failure path tests pass.

Acceptance Criteria

  • Plugins can configure authentication through ConfigureAuthentication.
  • Plugins can configure authorization through ConfigureAuthorization.
  • Both hooks receive the actual host security configuration objects.
  • Plugin authentication schemes integrate with the standard ASP.NET Core authentication infrastructure.
  • Plugin authorization policies integrate with the standard ASP.NET Core authorization infrastructure.
  • Existing host schemes and policies remain compatible.
  • Plugins cannot silently overwrite another plugin's security configuration.
  • Authentication scheme collisions are handled explicitly.
  • Authorization policy collisions are handled explicitly.
  • Plugins do not automatically modify default authentication schemes.
  • Plugins do not silently modify global default or fallback authorization policies.
  • Security scheme mappings remain explicit and compatible with Section F.
  • Authentication and authorization failures are surfaced explicitly.
  • Existing plugins remain backward compatible.
  • PluginContractValidator passes.
  • DevTokens continues to compile and load successfully.

Non Goals

This task does not include:

  • creating new authentication mechanisms
  • redesigning AuthKitSecuritySchemeType, AuthKitApiKeyLocation
  • defining new OpenAPI security schemes
  • endpoint mapping
  • middleware positioning
  • lifecycle hooks
  • hosted services
  • configuration binding
  • or introducing custom authentication or authorization framework.

New security scheme definitions and transport locations belong to Section F.
Endpoint and pipeline configuration belong to B3–B5.

Parent

Part of:

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1Core operationadditiveAdditive, non-breaking changearea/abstractionsAuthKit.Plugins.Abstractions contractcontractChanges the plugin contractsub-taskChild task of an epic

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions