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:
| Service | Lifetime | Resolves to |
|---|---|---|
TraxPrincipal | Scoped | The principal read from HttpContext.User with TryGetTraxPrincipal. Throws TraxPrincipalNotAvailableException when there is none. |
TraxCaller | Scoped | The caller context, which reports null instead of throwing. |
IHttpContextAccessor | Singleton |
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
ClaimsPrincipalcame from a scheme that is not a Trax scheme, so it has notrax:principal-idclaim.
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"));