Skip to main content

Extending Authentication Strategies

The framework allows adding custom authentication strategies through a registry-based approach. This follows the Open-Closed Principle, enabling you to add new auth methods without modifying the framework core.

1. Implement the Strategy​

Your strategy must implement the AuthenticationProtocol from framework_m_core.interfaces.authentication.

from collections.abc import Mapping
from framework_m_core.interfaces.auth_context import UserContext


class MyCustomAuth:
def supports(self, headers: Mapping[str, str]) -> bool:
return "x-custom-token" in headers

async def authenticate(self, headers: Mapping[str, str]) -> UserContext | None:
token = headers.get("x-custom-token")
if token == "secret":
return UserContext(id="user-1", email="user@example.com")
return None

2. Create a Factory​

Strategies are registered via a Factory function. This function receives the entire auth configuration block and any global dependencies (like jwt_secret).

from typing import Any
from framework_m_standard.adapters.auth.strategies import AuthStrategyRegistry


def custom_auth_factory(config: dict[str, Any], **deps: Any) -> MyCustomAuth:
return MyCustomAuth()


# Register the strategy
AuthStrategyRegistry().register("my-custom", custom_auth_factory)

3. Configure in config.toml​

Once registered, you can enable your strategy and set its priority in the auth.strategies list. The order in the list determines the priority in the AuthChain ("first match wins").

[auth]
# Priority: Check custom token first, then fallback to Bearer JWT
strategies = ["my-custom", "bearer"]

4. Dynamic Loading (Alternative)​

If you don't want to manually call register(), you can provide the fully qualified path to your strategy class or factory in the configuration:

[auth]
strategies = ["my_app.auth.MyCustomAuth", "bearer"]

The framework will automatically attempt to import and instantiate it.