IReadOnlyDictionary<string, AppSurfaceDevAuthPersona> Personas { get; }
Source
Gets the configured local-development personas.
Collection of seeded local-development personas for AppSurface DevAuth.
AppSurfaceDevAuthPersonaCollection Add(string id, Action<AppSurfaceDevAuthUserBuilder> configure)
Adds a local-development persona.
id
configure
The same collection for chaining.
IReadOnlyDictionary<string, AppSurfaceDevAuthPersona> Personas { get; }
Source
Gets the configured local-development personas.
Maps AppSurface DevAuth local-only control and status endpoints.
IEndpointRouteBuilder MapAppSurfaceDevAuth(this IEndpointRouteBuilder endpoints)
Maps the AppSurface DevAuth control page, status JSON, select persona, and clear persona endpoints.
endpoints
The same endpoint route builder for chaining.
Map this after building the app and before relying on the persona lab in a local proof host. The method validates the same materialized options used by the authentication handler, reserves the configured path prefix, and rejects existing endpoints whose route templates are equivalent to DevAuth control routes even when parameter names differ. Control endpoints stay loopback-only by default, honor AppSurfaceDevAuthOptions.AllowedEnvironmentNames
, and set no-store headers on every response. The control-page GET accepts an optional returnUrl
query value. A safe rooted local value is propagated to every select and clear form action, and successful mutations return through a local redirect. Missing or rejected values are omitted, so mutations render the control page normally.
Task<IResult> SelectPersonaAsync(string personaId, HttpContext httpContext, IHostEnvironment environment, IOptions<AppSurfaceDevAuthOptions> options, IDataProtectionProvider dataProtectionProvider)
Validates selection, queues the protected cookie and awaits optional request-scoped host activation before choosing the existing safe navigation target. Activation failures propagate to the host without rollback.
AppSurfaceDevAuthStatus BuildStatus(HttpContext httpContext, IHostEnvironment environment, AppSurfaceDevAuthOptions options, IDataProtectionProvider dataProtectionProvider)
Builds safe DevAuth status from the selected persona cookie for endpoint and marker rendering.
string DisplayPersonaName(AppSurfaceDevAuthPersona persona)
Returns a safe display name for a configured persona.
string DisplayStatusPersonaName(AppSurfaceDevAuthStatus status)
Returns a safe display name for the current status.
string DisplayStatusSubject(AppSurfaceDevAuthStatus status)
Returns a safe subject value for the current status.
string BuildMutationUrl(string pathPrefix, string action, string? returnUrl)
Builds a DevAuth mutation action URL and optionally appends a URI-escaped return URL.
pathPrefix
action
pathPrefix
.returnUrl
The bare mutation action when returnUrl
is null
; otherwise the mutation action with one URI-escaped returnUrl
query value.
string NormalizeLocalReturnUrl(string? value)
Normalizes a local marker return URL and falls back to the site root for unsafe values.
Marker metadata applied to endpoints mapped by AppSurface DevAuth.
Renders an explicit AppSurface DevAuth state marker for host pages.
Use this helper from pages or layouts where the selected fake persona should stay visible while navigating the app. The returned HTML contains only safe persona display values and POST-only controls that target the mapped DevAuth endpoints. DevAuth does not automatically inject this marker into host output, and this helper returns an empty string when the current environment is not in AppSurfaceDevAuthOptions.AllowedEnvironmentNames
. With default styles, the marker is a fixed bottom-right overlay above 640 CSS pixels and participates in normal document flow at widths up to and including 640 CSS pixels. The host owns the viewport metadata, render location, outer spacing, and any containing layout; render the marker after persistent application chrome and before main content so the narrow-screen marker reserves space instead of covering that content.
string Render(HttpContext httpContext, IHostEnvironment environment, IOptions<AppSurfaceDevAuthOptions> options, IDataProtectionProvider dataProtectionProvider, Action<AppSurfaceDevAuthMarkerOptions>? configure = null)
Renders a local DevAuth marker using the current request state.
httpContext
environment
options
dataProtectionProvider
configure
HTML that can be embedded in a host page, or an empty string when the current environment is not allowed. With default styles, the returned marker is fixed above 640 CSS pixels and in flow at 640 CSS pixels or below.
Prepares host-owned local fixtures when a configured DevAuth persona is explicitly selected.
Opt in with one unkeyed scoped registration using AddScoped
. DevAuth resolves the optional handler from the selection request's HttpContext.RequestServices
after queuing the protected persona cookie, and awaits it before redirecting or rendering the control page. No registration preserves the default behavior. Ordinary requests, control/status GETs, clearing and rejected selections do not resolve or invoke this service. Compose multiple preparation steps within one implementation. The host owns fixture identity, persistence, idempotence, concurrency, deadlines and recovery; repeated selections can invoke activation again. Cookie delivery and fixture writes are not atomic. Resolution failures, activation errors and cancellation propagate to the host pipeline without normal success navigation or framework rollback. See the package README's persona-selection activation guide for registration and recovery examples.
ValueTask ActivateAsync(AppSurfaceDevAuthPersona persona, HttpContext httpContext, CancellationToken cancellationToken)
Completes preparation of the local fixtures required by the explicitly selected persona.
persona
httpContext
cancellationToken
HttpContext.RequestAborted
token. Observe it cooperatively during preparation. DevAuth also checks it before invocation and after normal completion. A task that completes only when the required fixtures are ready.
Throw when required preparation fails. Do not write, start or redirect the response: DevAuth owns successful navigation and the host's exception pipeline owns failures. Do not retain the context, modify configured persona metadata or start background work that outlives the request. Cancellation can occur after writes; readiness must be checked by host pages and retry safety must be implemented by host persistence.
Authenticates the configured DevAuth scheme from the local persona cookie.
The handler reads only the protected persona id cookie, resolves that id against seeded personas, and returns AuthenticateResult.NoResult()
for blank, tampered, stale, or unknown state. It does not issue challenges, sign users in, or validate production identity tokens.
Task<AuthenticateResult> HandleAuthenticateAsync()
Attempts to authenticate the selected local persona.
Success with a claims principal for a known protected persona id, or no result when no trustworthy persona is selected.
string ProtectPersonaId(string personaId)
Protects a persona id with the same data-protection purpose as the endpoint cookie writer.
personaId
A protected cookie payload containing only the persona id.
Controls how the AppSurface DevAuth marker renders inside a local or proof host page.
The marker is an explicit opt-in snippet for pages where fake auth state should be visible. It never injects itself into host HTML. Consumers can disable the default inline styles and provide their own classes when the marker needs to match a local design system. The default styles use a fixed desktop overlay above 640 CSS pixels and normal document flow at widths up to and including 640 CSS pixels. The host remains responsible for viewport metadata, render location, outer spacing, containing layout, and any CSS overrides.
string CssClassPrefix { get; set; }
Source
Gets or sets the CSS class prefix used for every marker element.
The prefix replaces every package-emitted marker selector, including descendant selectors in the default inline styles. Changing it does not disable the package's responsive behavior. Use the new prefix for host overrides, or set IncludeDefaultStyles
to false
when the host will provide the complete skin.
string? AdditionalCssClass { get; set; }
Source
Gets or sets an extra CSS class appended to the marker root element.
Use this host-owned class for outer spacing or a deliberate placement override. Package styles are emitted with the configured CssClassPrefix
, so placement overrides may need higher specificity or later source order. The host owns overlap prevention whenever it overrides the package placement rules.
bool IncludeDefaultStyles { get; set; }
Source
Gets or sets a value indicating whether the marker includes package-provided default styles.
When enabled, the package renders a fixed bottom-right overlay above 640 CSS pixels and an in-flow marker at widths up to and including 640 CSS pixels. Set this to false
when the host wants to own all marker styling and responsive placement. The host must supply its own styles in that case.
bool ShowPersonaControls { get; set; }
Source
Gets or sets a value indicating whether persona select and clear controls are rendered in the marker.
When enabled, controls use POST-only DevAuth endpoints and include a safe local return URL so the browser returns to the host page after changing personas.
bool StartExpanded { get; set; }
Source
Gets or sets a value indicating whether the marker starts expanded.
The default is collapsed so the DevAuth state remains visible with a smaller desktop footprint. Set this to true
when a proof page should show the persona controls immediately. At narrow widths the default-styled expanded marker remains in normal flow and pushes following content instead of overlaying it.
string? ReturnUrl { get; set; }
Source
Gets or sets the explicit local URL to return to after a marker persona mutation.
This host-owned target takes precedence over the selected persona's configured landing URL. Leave it unset to let a selected persona landing URL win; when that persona has no landing URL, the marker returns to the current request path and query. The marker normalizes blank, non-rooted, external, protocol-relative, backslash-containing, and control-character values to the site root before constructing its mutation actions.
Detects sensitive-looking local persona ids and preview values without rejecting innocent words such as monkey
or mailbox
.
DevAuth diagnostics and control pages must not render obvious secrets, tokens, passwords, keys, credentials, or email-shaped values. This helper treats separators, PascalCase, and camelCase as token boundaries so names such as apiKey
, passwordHash
, access_token
, and secret-token
are hidden.
bool ContainsSensitiveToken(string value)
Determines whether a value looks too sensitive to expose in DevAuth diagnostics or route-visible persona ids.
value
true
when the value contains an email marker or sensitive word boundary.
Validates and resolves DevAuth-local navigation targets.
Request-supplied targets fail closed by being omitted, while configured persona landing URLs fail fast during registration. The two policies share the same local-path rules but intentionally have different failure behavior.
bool IsSafe(string? value)
Gets a value indicating whether a candidate is a safe rooted local path.
string? GetSafeOrNull(string? value)
Returns the safe candidate or null
when a request-supplied target is unusable.
string NormalizeOrRoot(string? value)
Returns a safe marker target, falling back to the site root for the legacy marker-option contract.
string ValidateConfigured(string? value)
Validates a configured persona landing URL.
AppSurfaceDevAuthException
ASDEV007
when the configured value is not a safe rooted local path. string? ResolveSelectTarget(string? explicitTarget, string? personaLandingUrl, string? fallbackTarget)
Resolves a select-persona navigation target in precedence order.
explicitTarget
personaLandingUrl
fallbackTarget
The first safe target in precedence order, or null
when selection should render the control response.
Builds a seeded local-development persona for AppSurface DevAuth.
AppSurfaceDevAuthUserBuilder DisplayName(string displayName)
Sets the display name shown on the DevAuth control page.
displayName
The same builder for chaining.
AppSurfaceDevAuthUserBuilder LandingUrl(string landingUrl)
Sets the safe local page where this persona starts when no explicit host return target is supplied.
landingUrl
/viewer
or /dashboard?tab=proof
.The same builder for chaining.
AppSurfaceDevAuthException
ASDEV007
when landingUrl
is not a safe rooted local path.
This is local-proof navigation metadata, not an authorization policy, claim, cookie payload, or route-access check. A safe explicit returnUrl
supplied by the host takes precedence over this configured fallback.
AppSurfaceDevAuthUserBuilder Subject(string subject, string claimType = AppSurfaceDevAuthDefaults.SubjectClaimType)
Sets the stable subject claim for the local persona.
subject
claimType
sub
.The same builder for chaining.
AppSurfaceDevAuthUserBuilder Claim(string type, string value)
Adds a safe local-development claim to the persona.
type
value
The same builder for chaining.
Claims added here are local test inputs. They are not durable identity, tenant authority, or permission truth. Keep secrets, tokens, passwords, raw emails, and production identity payloads out of DevAuth personas.
AppSurfaceDevAuthPersona Build()
Builds the immutable persona that will be stored in AppSurfaceDevAuthOptions.Users
.
A persona with a default display name of the persona id when no display name was supplied.
The configured subject claim is prepended when Subject(string, string)
was called. Any previously added claim with the same subject claim type is replaced so the persona has one stable subject value. Registration validation rejects personas that were built without an explicit subject.
string NormalizePersonaId(string id)
Validates and returns a route-safe local persona id.
id
admin
, viewer
, or qa.local_1
.The original id when it is safe for route values and local cookie payloads.
AppSurfaceDevAuthException
ASDEV006
when the id is blank, a URI dot segment, contains unsupported characters, or includes a sensitive-looking token segment such as secret
, token
, key
, or email
. Use this before accepting route-supplied persona ids. The validation is intentionally strict because persona ids are visible in the local selection URL and are the only payload stored in the protected persona cookie.
string Id { get; }
Source
Gets the local persona id.
Registers AppSurface Development-by-default authentication for ASP.NET Core hosts with explicit local/proof environment opt-in.
IServiceCollection AddAppSurfaceDevAuth(this IServiceCollection services, IHostEnvironment environment, Action<AppSurfaceDevAuthOptions> configure)
Adds the AppSurface DevAuth named authentication scheme and startup safety validation.
services
environment
configure
The same service collection for chaining.
ArgumentException
AppSurfaceDevAuthOptions.AllowedEnvironmentNames
is empty or contains blank names. AppSurfaceDevAuthException
DevAuth is fake local authentication. It registers a normal ASP.NET Core authentication handler, but it must not be used as a production identity provider, user store, OIDC replacement, or durable app-user mapping layer. DevAuth activates only when the trimmed host environment name matches AppSurfaceDevAuthOptions.AllowedEnvironmentNames
case-insensitively. The default allow-list contains Development
; add proof environments only for intentional local/proof hosts.
AppSurfaceDevAuthException CreateNonDevelopmentException(string environmentName, AppSurfaceDevAuthOptions options)
Creates the stable AppSurfaceDevAuthDiagnostics.NonDevelopmentEnvironment
exception.
environmentName
(unknown)
. options
An exception that tells consumers to run DevAuth only in an allowed proof environment or remove it.
void ValidateOptions(AppSurfaceDevAuthOptions options)
Validates the materialized DevAuth options before endpoint mapping and startup safety checks run.
options
ArgumentException
AppSurfaceDevAuthOptions.SchemeName
, AppSurfaceDevAuthOptions.PathPrefix
, or AppSurfaceDevAuthOptions.CookieName
is blank, or when AppSurfaceDevAuthOptions.AllowedEnvironmentNames
is empty or contains blank names. AppSurfaceDevAuthException
ASDEV003
when no personas are configured, ASDEV004
when a persona lacks its configured subject claim, or ASDEV005
when the path prefix is not an absolute path without a trailing slash. bool IsMissingSubjectClaim(AppSurfaceDevAuthPersona persona)
Determines whether a seeded persona is missing the non-blank subject claim required by Auth.AspNetCore mapping.
persona
true
when the persona lacks its configured subject claim.
Options for AppSurface Development-by-default authentication with explicit local/proof environment opt-in.
AppSurfaceDevAuthPersonaCollection Users { get; }
Source
Gets the seeded local-development personas.
string SchemeName { get; set; }
Source
Gets or sets the authentication scheme registered for DevAuth.
string PathPrefix { get; set; }
Source
Gets or sets the local-only path prefix for the control page and status endpoints.
string CookieName { get; set; }
Source
Gets or sets the cookie name that stores the selected local persona id.
bool UseAsDefaultSchemeForLocalProof { get; set; }
Source
Gets or sets a value indicating whether DevAuth may become the default scheme for local proof apps.
Leave this disabled for package consumers that already have real authentication. Enable it only in throwaway local proof hosts where DevAuth is intentionally the whole authentication stack.
bool AllowDevAuthOverrideForLocalProof { get; set; }
Source
Gets or sets a value indicating whether DevAuth may coexist with other registered authentication schemes.
This is a loud local-only override for demos that intentionally compose real and fake schemes. It must not be used to hide production authentication conflicts.
bool RequireLoopbackControlRequests { get; set; }
Source
Gets or sets a value indicating whether control endpoints reject non-loopback requests.
ISet<string> AllowedEnvironmentNames { get; }
Source
Gets environment names where DevAuth is allowed to activate.
The set defaults to Environments.Development
and compares names case-insensitively. DevAuth trims names when checking the active host environment. Add only local or proof environments that should expose fake personas; this allow-list is activation policy for fake auth, not a production safety boundary.
ISet<string> DisplayClaimTypes { get; }
Source
Gets claim types that may appear in the local-only control page claims preview.
The authentication handler still issues every seeded persona claim. This allowlist affects only the HTML preview. Sensitive claim names such as tokens, secrets, passwords, keys, and emails are never rendered even when added here.
Defines default names and paths for AppSurface development authentication.
Performs DevAuth startup validation after the host service provider has been built.
Registration validates the caller-supplied environment early, but this hosted service re-checks the real environment resolved from dependency injection and inspects the final authentication defaults and schemes. It rejects environments outside the DevAuth activation allow-list and real authentication scheme conflicts unless the consumer explicitly enabled the local-proof override. This service is internal infrastructure for AppSurfaceDevAuthServiceCollectionExtensions
.
Task StartAsync(CancellationToken cancellationToken)
Validates that DevAuth is running in an allowed environment and is not silently coexisting with real authentication.
cancellationToken
A completed task when the final host configuration is safe for local DevAuth.
ArgumentException
AppSurfaceDevAuthOptions.AllowedEnvironmentNames
allow-list. AppSurfaceDevAuthException
ASDEV001
outside configured proof environments or with ASDEV002
when real schemes/defaults are present without the explicit override. Task StopAsync(CancellationToken cancellationToken)
Stops the validator.
cancellationToken
A completed task because the validator does not own background work.
Exception thrown when AppSurface DevAuth detects unsafe or invalid development-auth configuration.
string DiagnosticCode { get; }
Source
Gets the stable AppSurface DevAuth diagnostic code.
Stable AppSurface DevAuth diagnostic codes and safe metadata keys.
Defines DevAuth marker tokens that static exporters must treat as private development-auth evidence.
DevAuth renders these tokens only on local development surfaces. Static export auditors consume the same constants so marker renames are compiler-checked across the renderer and artifact-audit boundary.
Represents a seeded local-development persona that can be selected by AppSurface DevAuth.
string Id { get; }
Source
Gets the stable local persona id used by the DevAuth selection cookie.
string DisplayName { get; }
Source
Gets the display name shown on the local-only DevAuth control page.
string? LandingUrl { get; }
Source
Gets the optional safe local page used after selecting this persona when the host did not supply an explicit return target.
This value is navigation metadata for local proof flows only. It is not an authorization policy, issued claim, cookie payload, status-JSON field, or guarantee that the selected persona can access the configured route.
string SubjectClaimType { get; }
Source
Gets the claim type used to expose the stable local subject.
string Subject { get; }
Source
Gets the stable local subject value for this persona.
IReadOnlyList<Claim> Claims { get; }
Source
Gets safe local-development claims issued for this persona.
Centralizes DevAuth environment activation checks.
bool IsEnvironmentAllowed(IHostEnvironment environment, AppSurfaceDevAuthOptions options)
Determines whether DevAuth may activate in the current host environment.
environment
options
true
when the environment name is in the DevAuth activation allow-list.
void ValidateAllowedEnvironmentNames(AppSurfaceDevAuthOptions options)
Validates the configured DevAuth activation allow-list.
options
ArgumentException
string FormatAllowedEnvironmentNames(AppSurfaceDevAuthOptions options)
Formats configured allowed environment names for safe diagnostics.
options
A comma-separated, display-safe list of configured environment names.