Creating a Custom Shield

Learn how to implement your own authentication mechanism in Altruist using Shields.

Custom Shield Authentication

Altruist introduces the Shield system, a flexible way to handle authentication and authorization for sockets.
This guide will show you how to create a custom Shield authentication by implementing IShieldAuth.

What is a Shield?

A Shield is similar to ASP.NET's [Authorize] but designed for sockets and real-time interactions.
You can apply it at the class level or method level, just like [Authorize] in a standard .NET API.

[Shield(typeof(MyCustomAuth))]
public class MyPortal : AltruistGamePortal<Spaceship> {...}

Or use a custom Shield alias:

[MyCustomShield]
public void SecureMethod(MyPacket packet, string clientId) { ... }

🛠 Step 1: Implement Your Authentication Logic

The IShieldAuth interface allows you to define a custom authentication method.

public class MyCustomAuth : IShieldAuth
{
    private readonly ITokenValidator _tokenValidator;

    public MyCustomAuth(ITokenValidator tokenValidator)
    {
        _tokenValidator = tokenValidator;
    }

    public Task<AuthorizationResult> HandleAuthAsync(HttpContext context)
    {
        var token = context.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");

        if (string.IsNullOrEmpty(token) || !_tokenValidator.ValidateToken(token))
        {
            return Task.FromResult(AuthorizationResult.Failed());
        }

        return Task.FromResult(AuthorizationResult.Success());
    }
}

What this does:

  • Extracts the JWT token from the request.
  • Validates it using the ITokenValidator.
  • Returns Success if the token is valid, otherwise Failed.

Step 2: Create a Token Validator

A token validator ensures your authentication mechanism works correctly.

public class JwtTokenValidator : ITokenValidator
{
    private readonly JwtSecurityTokenHandler _tokenHandler;
    private readonly TokenValidationParameters _validationParams;

    public JwtTokenValidator(IConfiguration configuration)
    {
        _tokenHandler = new JwtSecurityTokenHandler();

        _validationParams = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = configuration["Jwt:Issuer"],
            ValidAudience = configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(configuration["Jwt:SecretKey"]!)
            )
        };
    }

    public bool ValidateToken(string token)
    {
        try
        {
            _tokenHandler.ValidateToken(token, _validationParams, out _);
            return true;
        }
        catch
        {
            return false;
        }
    }
}
  • This uses standard JWT validation
  • Supports issuer/audience checking
  • Ensures token validity

🔗 Step 3: Register It in Altruist

To make the authentication available in the application, register it using an extension method.

public static class WebAppExtensions
{
    public static WebApplicationBuilder AddJwtAuth(
        this WebApplicationBuilder builder,
        Action<JwtBearerOptions>? configureOptions = null,
        Action<AuthorizationOptions>? authorizationOptions = null)
    {
        builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                configureOptions?.Invoke(options);
            });

        builder.Services.AddAuthorization(options =>
        {
            authorizationOptions?.Invoke(options);
        });

        builder.Services.AddScoped<ITokenValidator, JwtTokenValidator>();
        builder.Services.AddScoped<IShieldAuth, JwtAuth>();

        return builder;
    }
}

Now, when setting up your WebApp, simply call:

.WebApp(setup =>
{
    setup.AddJwtAuth(configure => configure.RequireHttpsMetadata = false);
})

Step 4: Create a Shield Alias

Instead of writing [Shield(typeof(JwtAuth))] everywhere, create an alias!

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

🔹 Now you can just use:

[JwtShield]
public class SecurePortal : AltruistGamePortal<Spaceship> {...}

or

[JwtShield]
public void MySecureMethod(MyPacket packet, string clientId) { }

Note:

JWT token validation is not the safest authentication method — it was used here for demonstration purposes. Feel free to implement a more optimized solution for high-quality authentication. Or stay tuned for future high-quality Altruist solutions!