Custom Shield

Create your own authentication mechanism by implementing IShieldAuth.

Implement IShieldAuth

[Service(typeof(IShieldAuth))]
public class ApiKeyAuth : IShieldAuth
{
    private readonly IVault<ApiKeyVault> _keys;

    public ApiKeyAuth(IVault<ApiKeyVault> keys)
    {
        _keys = keys;
    }

    public async Task<AuthResult> HandleAuthAsync(IAuthContext context)
    {
        string apiKey = "";

        if (context is HttpAuthContext http)
            apiKey = http.HttpContext.Request.Headers["X-Api-Key"].ToString();

        if (string.IsNullOrEmpty(apiKey))
            return new AuthResult(AuthorizationResult.Failed(), null!);

        var key = await _keys.Where(k => k.Key == apiKey).FirstOrDefaultAsync();
        if (key == null)
            return new AuthResult(AuthorizationResult.Failed(), null!);

        var details = new AuthDetails(apiKey, key.OwnerId, "", "", TimeSpan.FromHours(1));
        return new AuthResult(AuthorizationResult.Success(), details);
    }
}

Create a Shield Alias

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
public class ApiKeyShieldAttribute : ShieldAttribute
{
    public ApiKeyShieldAttribute() : base(typeof(ApiKeyAuth)) { }
}

Use It

// On a portal (works on WebSocket, TCP, UDP)
[Portal("/game")]
[ApiKeyShield]
public class SecurePortal : AltruistPortal { ... }

// On an HTTP controller
[ApiController]
[Route("/api/external")]
[ApiKeyShield]
public class ExternalApiController : ControllerBase { ... }

// On a single method
[ApiKeyShield]
[Gate("admin-action")]
public async Task OnAdminAction(AdminPacket p, string clientId) { ... }

The IAuthContext

Your HandleAuthAsync receives an IAuthContext. Check which transport the request came from:

public async Task<AuthResult> HandleAuthAsync(IAuthContext context)
{
    if (context is HttpAuthContext http)
    {
        // HTTP / WebSocket — access HttpContext, headers, cookies
        var token = http.HttpContext.Request.Headers["Authorization"].ToString();
    }
    else
    {
        // TCP / UDP — access raw token from context
        var token = context.Token;
    }
}

Note:

See Authentication & Authorization for the built-in JWT and session shield system.