← Back to Articles         
CORS in Production

CORS in Production

Published on 01 Oct 2026     8 min read Angular
CORS

CORS in Production and CORS with Cookies/Credentials

These two topics are closely related. The key production rule is:

Allow only the frontend origins that actually need browser access to your API, and use AllowCredentials() only when cross-origin cookies/credentials are genuinely required.


1. How Should CORS Be Configured in Production?

Recommended Approach

Suppose your production architecture is:

Angular
https://www.jntech.in

        ↓

ASP.NET Core API
https://api.jntech.in

These are different origins because the hosts differ:

www.jntech.in
     ≠
api.jntech.in

Therefore CORS applies.

Configure the API to explicitly allow:

https://www.jntech.in

rather than allowing every origin.


Full Production Example

appsettings.json

{
  "AllowedOrigins": [
    "https://www.jntech.in"
  ]
}

Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var allowedOrigins =
    builder.Configuration
        .GetSection("AllowedOrigins")
        .Get<string[]>()!;

builder.Services.AddCors(options =>
{
    options.AddPolicy(
        "ProductionCors",
        policy =>
        {
            policy
                .WithOrigins(allowedOrigins)
                .AllowAnyHeader()
                .AllowAnyMethod();
        });
});

var app = builder.Build();

app.UseHttpsRedirection();

app.UseCors("ProductionCors");

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

This means:

https://www.jntech.in
          ↓
        Allowed


https://unknown-site.com
          ↓
      Not allowed

Development vs Production

You may have different frontend origins in different environments.

Development

Angular:
http://localhost:4200

API:
https://localhost:7001

Production

Angular:
https://www.jntech.in

API:
https://api.jntech.in

You can configure them separately.

appsettings.Development.json

{
  "AllowedOrigins": [
    "http://localhost:4200"
  ]
}

appsettings.Production.json

{
  "AllowedOrigins": [
    "https://www.jntech.in"
  ]
}

Then the same Program.cs reads:

var allowedOrigins =
    builder.Configuration
        .GetSection("AllowedOrigins")
        .Get<string[]>()!;

This is cleaner than hard-coding environment-specific URLs.


Multiple Production Frontends

Suppose you have:

Public Angular:
https://www.jntech.in

Admin Angular:
https://admin.jntech.in

Configure:

{
  "AllowedOrigins": [
    "https://www.jntech.in",
    "https://admin.jntech.in"
  ]
}

ASP.NET Core:

policy
    .WithOrigins(allowedOrigins)
    .AllowAnyHeader()
    .AllowAnyMethod();

Should Production Use AllowAnyOrigin()?

For an API intended only for your known frontend applications, generally prefer:

.WithOrigins(
    "https://www.jntech.in"
)

rather than:

.AllowAnyOrigin()

because AllowAnyOrigin() permits browser access from any origin.

Use the least-privilege principle:

Allow only what is required.

Can Angular and API Avoid CORS Entirely?

Yes, depending on deployment architecture.

Suppose both are served through:

https://www.jntech.in

For example:

https://www.jntech.in/
        ↓
Angular


https://www.jntech.in/api/products
        ↓
ASP.NET Core

From the browser's perspective:

Scheme = https
Host   = www.jntech.in
Port   = 443

for both.

Therefore:

Same Origin
    ↓
No cross-origin CORS requirement

A reverse proxy/API gateway can be used to expose both under the same public origin.


Production CORS Checklist

For production:

  • Use HTTPS.
  • Prefer explicit WithOrigins(...).
  • Keep origins in environment-specific configuration.
  • Allow only required methods and headers where practical.
  • Don't use CORS as authentication.
  • Continue protecting endpoints with [Authorize].
  • Add AllowCredentials() only when browser credentials/cookies must cross origins.
  • Don't combine wildcard origin with credentialed CORS.

2. How Does CORS Work When Credentials/Cookies Are Used?

This becomes especially important with the refresh-token design we discussed.

Suppose:

Angular
https://www.jntech.in

        ↓

ASP.NET Core
https://api.jntech.in

ASP.NET Core stores the refresh credential in an:

HttpOnly
Secure
Cookie

Now Angular needs the browser to include cookies in appropriate cross-origin requests.


Full ASP.NET Core Configuration

Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddCors(options =>
{
    options.AddPolicy(
        "AngularApp",
        policy =>
        {
            policy
                .WithOrigins(
                    "https://www.jntech.in"
                )
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials();
        });
});

var app = builder.Build();

app.UseHttpsRedirection();

app.UseCors("AngularApp");

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

The important addition is:

.AllowCredentials()

This tells the CORS middleware that credentialed cross-origin requests from the explicitly allowed origin are permitted.


Angular Configuration

Angular must also request credential handling when needed:

this.http.post(
  'https://api.jntech.in/api/auth/refresh',
  {},
  {
    withCredentials: true
  }
);

The important part is:

withCredentials: true

Both Sides Must Agree

For cross-origin cookie usage:

Angular
withCredentials: true

          +

ASP.NET Core
AllowCredentials()

          +

Explicit trusted origin
WithOrigins(...)

          ↓

Credentialed CORS request

Example Login Flow

Angular sends:

login(
  username: string,
  password: string
) {
  return this.http.post(
    'https://api.jntech.in/api/auth/login',
    {
      username,
      password
    },
    {
      withCredentials: true
    }
  );
}

ASP.NET Core authenticates the user and creates a refresh-token cookie.

Response.Cookies.Append(
    "refreshToken",
    refreshToken,
    new CookieOptions
    {
        HttpOnly = true,
        Secure = true,

        SameSite =
            SameSiteMode.Strict,

        Expires =
            DateTimeOffset.UtcNow
                .AddDays(7)
    });

The cookie is:

HttpOnly
    ↓
Angular JavaScript cannot read it directly

Secure
    ↓
Sent only over HTTPS

Cookie SameSite behavior depends on whether the browser considers the frontend/API relationship same-site or cross-site, so choose Strict, Lax, or None based on the actual deployment topology rather than applying one setting universally.


Refresh Flow

Later the access token expires:

API Request
    ↓
401 Unauthorized

Angular calls:

this.http.post(
  'https://api.jntech.in/api/auth/refresh',
  {},
  {
    withCredentials: true
  }
);

Angular doesn't need to read the refresh token.

Instead:

Angular
   ↓
POST /refresh
withCredentials: true
   ↓
Browser
   ↓
Automatically attaches eligible cookie
   ↓
ASP.NET Core
   ↓
Reads refresh token
   ↓
Validates it
   ↓
Issues new access token

This is one advantage of an HttpOnly refresh cookie.


Why Can't Angular Read an HttpOnly Cookie?

Because:

HttpOnly = true

instructs the browser not to expose the cookie value to normal JavaScript APIs.

Therefore Angular cannot simply do:

const refreshToken =
  document.cookie;

and retrieve an HttpOnly refresh-token value.

That's intentional.

Angular JavaScript
      X
      │
      │ cannot directly read
      ▼
HttpOnly Refresh Cookie


Browser
      │
      │ automatically sends
      ▼
ASP.NET Core

Why Can't We Use AllowAnyOrigin() + AllowCredentials()?

This configuration is invalid/insecure:

policy
    .AllowAnyOrigin()
    .AllowCredentials();

Why?

Because you're effectively saying:

Any website
     +
Credentialed requests

Credentialed CORS requires a specific allowed origin rather than wildcard *.

Use:

policy
    .WithOrigins(
        "https://www.jntech.in"
    )
    .AllowCredentials();

Response Headers

For a credentialed CORS request, the API can respond with headers such as:

Access-Control-Allow-Origin: https://www.jntech.in
Access-Control-Allow-Credentials: true

Notice:

Access-Control-Allow-Origin: *

is not used for this credentialed request.

Instead:

Access-Control-Allow-Origin: https://www.jntech.in

explicitly identifies the permitted origin.


Preflight with Credentials

Suppose Angular sends a request requiring preflight.

The browser may first send:

OPTIONS /api/auth/refresh

Origin: https://www.jntech.in

Access-Control-Request-Method: POST

Access-Control-Request-Headers: content-type

ASP.NET Core evaluates:

Origin allowed?
      ↓
POST allowed?
      ↓
Headers allowed?
      ↓
Credentials allowed?

If the policy allows it, the browser proceeds with the actual request.


CORS Credentials vs JWT Bearer Token

There is an important distinction.

Bearer Token

Angular explicitly adds:

Authorization: Bearer <JWT>

using an interceptor.

Angular JavaScript
       ↓
reads access token
       ↓
adds Authorization header

HttpOnly Cookie

Angular cannot read the cookie.

Angular
       ↓
withCredentials
       ↓
Browser
       ↓
automatically attaches eligible cookie

So a common hybrid design is:

Access Token
     ↓
Angular memory
     ↓
Authorization: Bearer


Refresh Token
     ↓
HttpOnly Secure Cookie
     ↓
Browser manages it

Important: CORS and Cookies Are Not Enough

Using:

.AllowCredentials()

doesn't mean your cookie setup is automatically secure.

You still need to consider:

HTTPS

Secure = true

HttpOnly

HttpOnly = true

SameSite

Choose an appropriate setting:

SameSite = ...

CSRF

Because browsers automatically attach cookies, cookie-authenticated operations may require CSRF protection depending on the architecture.

Authentication/Authorization

Sensitive API endpoints still need:

[Authorize]

or:

[Authorize(Roles = "Admin")]

Complete Production Architecture

Angular
https://www.jntech.in
        │
        │
        ├──── Access Token
        │     Authorization: Bearer
        │
        │
        └──── withCredentials
        │
        ▼
Browser
        │
        │ HttpOnly Refresh Cookie
        ▼
ASP.NET Core
https://api.jntech.in
        │
        ▼
CORS
        │
        ├── Origin allowed?
        ├── Method allowed?
        ├── Header allowed?
        └── Credentials allowed?
        │
        ▼
Authentication
        │
        ▼
Authorization
        │
        ▼
Controller

AllowAnyOrigin() vs AllowCredentials()

Configuration Meaning
AllowAnyOrigin() Any origin
WithOrigins(...) Specific origins
AllowCredentials() Allow credentialed CORS requests
AllowAnyOrigin() + AllowCredentials() Invalid combination
WithOrigins(...) + AllowCredentials() Appropriate pattern when cross-origin credentials are needed

Key Points

  • In production, explicitly allow trusted frontend origins.
  • Prefer WithOrigins() over AllowAnyOrigin() for APIs intended for known applications.
  • Store production origins in configuration.
  • Use HTTPS.
  • CORS may not be necessary when Angular and the API are exposed through the exact same origin.
  • For cross-origin cookie usage, configure AllowCredentials().
  • Angular may need withCredentials: true.
  • Credentialed CORS requires explicit origins.
  • Don't combine AllowAnyOrigin() with AllowCredentials().
  • HttpOnly prevents JavaScript from directly reading the cookie.
  • Secure limits cookie transmission to HTTPS.
  • SameSite controls important cross-site cookie behavior.
  • Cookie-based authentication/refresh flows require CSRF consideration.
  • CORS never replaces ASP.NET Core authentication or authorization.

Interview Questions & Answers

1. How should CORS be configured in production?

Allow only known frontend origins:

policy
    .WithOrigins(
        "https://www.jntech.in"
    )
    .AllowAnyHeader()
    .AllowAnyMethod();

Avoid unnecessarily using AllowAnyOrigin() for a private application API.


2. What does AllowCredentials() do?

It permits credentialed cross-origin requests, such as requests involving eligible cookies.

.AllowCredentials()

3. How does Angular send cookies in a cross-origin request?

When required, use:

{
  withCredentials: true
}

The browser then handles eligible cookies according to the cookie and CORS rules.


4. Can Angular read an HttpOnly cookie?

No.

That is the purpose of:

HttpOnly = true

The browser manages the cookie and can attach it to eligible requests.


5. Can AllowAnyOrigin() be combined with AllowCredentials()?

No.

Use an explicit origin:

.WithOrigins(
    "https://www.jntech.in"
)
.AllowCredentials();

6. What CORS headers are important for credentialed requests?

Typically:

Access-Control-Allow-Origin: https://www.jntech.in
Access-Control-Allow-Credentials: true

The origin must be explicit rather than *.


7. Is withCredentials: true alone enough?

No.

The server must also permit the origin and credentials:

.WithOrigins(...)
.AllowCredentials()

and the cookie itself must be eligible to be sent according to Secure, SameSite, domain/path, and browser rules.


8. Do we always need CORS in production?

No. If Angular and the API are exposed through the same scheme, host, and port, the browser sees them as the same origin and cross-origin CORS is not required.


Interview Quick Answer

In production, ASP.NET Core should normally allow only explicitly trusted Angular origins using WithOrigins(). When cross-origin cookies are required, the server uses AllowCredentials() and Angular uses withCredentials: true. Credentialed CORS cannot use the wildcard AllowAnyOrigin(); the permitted origin must be explicitly specified.

← Back to Articles