Reference

AddTraxPrincipalAccessor

Package Trax.Api.AuthNamespace Trax.Api.AuthSource TraxAuthServiceCollectionExtensions.cs, TraxPrincipalNotAvailableException.cs

NO WARRANTY. Trax auth is plumbing, not a security product. You are solely responsible for securing systems that use it. See API Security.

Extension method on IServiceCollection, declared on TraxAuthServiceCollectionExtensions, that registers the current request's TraxPrincipal and TraxCaller as injectable services. Every AddTrax*Auth call runs it.

Signature

public static IServiceCollection AddTraxPrincipalAccessor(this IServiceCollection services);
 
public sealed class TraxPrincipalNotAvailableException : InvalidOperationException
{
    public TraxPrincipalNotAvailableException();
    public TraxPrincipalNotAvailableException(string message);
}

Returns

The same IServiceCollection.

Behavior

AddTraxPrincipalAccessor registers, each with TryAdd so the first registration wins and repeated calls do nothing:

ServiceLifetimeResolves to
TraxPrincipalScopedThe principal read from HttpContext.User with TryGetTraxPrincipal. Throws TraxPrincipalNotAvailableException when there is none.
TraxCallerScopedThe caller context, which reports null instead of throwing.
IHttpContextAccessorSingleton

Within one scope every injection returns the same instance.

When TraxPrincipal throws

TraxPrincipalNotAvailableException, an InvalidOperationException, is thrown when TraxPrincipal is resolved and:

  • the request is anonymous: no scheme produced a principal;
  • there is no HttpContext: the scheduler, a background service, a test that does not set up the accessor;
  • the request's ClaimsPrincipal came from a scheme that is not a Trax scheme, so it has no trax:principal-id claim.

Its default message reads: No authenticated Trax principal is available on the current execution context. Injecting TraxPrincipal requires an authenticated HTTP request. For junctions that also run from the scheduler or background services, inject IHttpContextAccessor and probe TryGetTraxPrincipal instead.

A junction of a train gated by [TraxAuthorize] is constructed only after the authorization check passed. Over GraphQL an anonymous caller of such a train gets a TRAX_AUTHORIZATION error (Not authorized.), not the exception.

When no scheme is registered

The mediator checks at startup that every junction's constructor arguments resolve, and TraxPrincipal resolves only once something registered it. A host whose AddTrax*Auth calls are all conditional and none ran refuses to start, naming the junction that needs Trax.Api.Auth.TraxPrincipal. Calling AddTraxPrincipalAccessor() unconditionally lets it start; every gated train then refuses every caller until a scheme is configured.

Example

services.AddAuthentication(); // UseAuthentication() needs it when no scheme was registered
services.AddTraxPrincipalAccessor();
 
if (builder.Environment.IsDevelopment())
    services.AddTraxApiKeyAuth(keys => keys.Add("member-key-do-not-use-in-production", id: "member", "Member"));

See also