Roadmap › .NET Full Stack Developer Interview — End to End › Module: End-to-End Request Flow
Lessons in this course (10)

4. Authentication end to end — JWT, refresh tokens, CORS

Intermediate★ Must knowLesson 4 of 10

Typical flow (token-based, SPA + API):

  1. User logs in (own endpoint, or an identity provider such as Microsoft Entra ID / Auth0 / Duende IdentityServer using OAuth 2.0 + OpenID Connect with PKCE).
  2. The SPA receives an access token (short-lived JWT, e.g. 15–60 min) and often a refresh token (long-lived, rotated).
  3. An HTTP interceptor adds Authorization: Bearer <access token> to API calls.
  4. The API validates signature, issuer, audience and expiry; builds ClaimsPrincipal; [Authorize] and policies check roles/claims.
  5. On 401, the SPA uses the refresh token to get a new access token, or redirects to login.
csharp
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(o =>
    {
        o.Authority = builder.Configuration["Auth:Authority"];   // identity provider
        o.Audience  = builder.Configuration["Auth:Audience"];
    });
builder.Services.AddAuthorization(o => o.AddPolicy("CanApprove", p => p.RequireRole("Manager")));

app.UseCors("spa");
app.UseAuthentication();
app.UseAuthorization();
typescript
// Angular functional interceptor
export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = inject(AuthService).accessToken();
  return next(token ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }) : req);
};
QuestionShort answer
Where to store tokens in the browser?Best: keep tokens out of JS (BFF pattern + HttpOnly, Secure, SameSite cookie). If in JS, keep the access token in memory, not localStorage (XSS can read it).
Authentication vs authorizationAuthentication = who you are (401 if missing/invalid). Authorization = what you may do (403 if not allowed).
What is CORS?A browser rule: a page from origin A may call origin B only if B returns Access-Control-Allow-Origin for A. It is not a server security feature — Postman ignores it.
JWT contentsHeader (alg), payload (claims: sub, exp, aud, iss, roles), signature. Base64Url-encoded, not encrypted — never put secrets in it.