ASP.NET Core / Intermediate: Data, Identity, and Asynchronous Work / Lesson 9
Authentication Schemes and Trust
Validate identity through a configured scheme while keeping claims construction, endpoint protection, and browser security distinct.
On this page
Lesson goals
- Explain authentication handlers, schemes, and principal construction.
- Distinguish cookies, bearer tokens, challenge, and forbid.
- Avoid trusting client-supplied identity fields.
Claims require a trusted construction path
Authentication establishes identity through a configured handler and scheme. A ClaimsPrincipal object is the result consumed by later authorization, not proof by its mere existence. Creating claims from an arbitrary header or request body would let the client invent authority unless a trusted validation process establishes them.
A scheme defines the handler and options used for authentication-related actions. Multiple schemes need deliberate default/selection policy. Merely adding authentication does not require every endpoint to be protected; authorization metadata and middleware/fallback policy determine access requirements. Keep identity validation and permission decisions separate.
An in-memory principal tests representation, not token trust
The complete program creates an explicitly synthetic authenticated identity and reads a claim. It demonstrates ClaimsIdentity behavior and supplies useful fixtures for policy tests. It does not validate a JWT, cookie, issuer, signature, expiry, or audience, and it does not authenticate an actual user. A test fixture must not be reused as production credential validation.
Set the authentication type deliberately in a synthetic identity so tests do not accidentally depend on IsAuthenticated defaults. Test claims and role/name claim mapping when authorization relies on them. A string named admin in an untrusted payload is not equivalent to a trusted role claim.
using System;
using System.Security.Claims;
var identity = new ClaimsIdentity(new[] { new Claim("scope", "reports.read") }, authenticationType: "synthetic");
var principal = new ClaimsPrincipal(identity);
Console.WriteLine($"authenticated={principal.Identity?.IsAuthenticated} scope={principal.FindFirst("scope")?.Value}");
authenticated=True scope=reports.read
The assigned authentication type makes the fixture authenticated; no credential is validated.
A bearer setup needs complete trusted options
The non-runnable excerpt illustrates a named bearer scheme with invented authority/audience. It requires the appropriate package, host setup, issuer policy, and integration tests; no package or remote metadata is fetched here. Token validation must check the documented trust and lifetime requirements, not merely decode a tokenβs JSON payload.
Cookies represent a different client interaction and need appropriate protection, transport, lifetime, signing/encryption keys, and browser handling. In ASP.NET Core 10, known API endpoints using cookie authentication return 401/403 rather than automatically redirecting to login/access-denied pages under the documented behavior. Interactive pages still have their own contract.
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://issuer.example.invalid";
options.Audience = "example-api";
});
This fragment is not executed; no package, issuer metadata, token, or remote identity service is contacted.
Challenge and forbid communicate different failures
A challenge asks an unauthenticated caller to authenticate according to the selected scheme, while forbid addresses an authenticated caller lacking authorization. The resulting HTTP behavior is scheme and endpoint dependent. Do not replace both with a generic success body or rely on a redirect as proof that an API is protected.
CORS is a browser cross-origin response policy, not authentication or authorization. Cookie-based requests also need a CSRF/antiforgery design where applicable because browsers can attach credentials automatically. A bearer API has different client/token-storage risks. Choose the supported mechanism from the actual client and threat model.
Test the trust boundary through supported integration
Test absent, malformed, expired, wrong-issuer/audience, and valid credentials using an approved isolated identity fixture, not real accounts. Test scheme selection, claim mapping, challenge/forbid, cookie/API behavior, and sensitive-log redaction. A direct principal fixture is useful for authorization units but cannot replace these authentication checks.
Keep signing/encryption material and real tokens out of source, images, URLs, logs, and examples. Record key rotation, revocation/lifetime, proxy/TLS, and deployment assumptions. The course performs no login, external identity call, token issuance, or configured authentication flow; unexecuted setup remains marked false.
Common errors and fixes
A decoded token payload is treated as authenticated identity.
- Why it happens
- Parsing was confused with signature/trust/lifetime validation.
- How to fix it
- Use the configured supported authentication handler and trust policy.
- Prevent it next time
- Test invalid issuer, audience, signature, and expiry.
Adding authentication is assumed to protect every endpoint.
- Why it happens
- Identity establishment and authorization requirements were conflated.
- How to fix it
- Apply explicit endpoint or fallback authorization policy.
- Prevent it next time
- Test an endpoint with no intended anonymous access.
CORS is used as an API access-control mechanism.
- Why it happens
- Browser response policy was mistaken for authorization.
- How to fix it
- Enforce server-side identity and permission checks.
- Prevent it next time
- Test callers outside browser CORS behavior conceptually.
Check your understanding
1. Why can a ClaimsPrincipal fixture with IsAuthenticated=True not prove that a real token is valid?
Show worked solution
The fixture was constructed by test code and contains no cryptographic or issuer/lifetime evidence. It can verify how authorization handles known claims, but authentication needs the configured handler and trusted options under an isolated integration test. Keep that scope visible and never build production identity directly from client-supplied claims without validation.
2. A browser can call an API from an allowed origin. What identity/security questions remain?
Show worked solution
Whether credentials are present and validated, which authorization applies, how tokens/cookies are stored and sent, whether CSRF protection is needed, and whether transport/proxy trust is correct. CORS permission does not answer them. Test public and protected endpoint behavior through the actual supported client/auth scheme rather than equating origin allowance with user authority.
Key takeaways
- Claims need a trusted authentication path.
- Scheme, endpoint metadata, and authorization determine 401/403/redirect behavior.
- CORS and CSRF defenses solve different browser problems from authentication.