How do you handle CORS when Angular and Web API are deployed separately?
When Angular and ASP.NET Core Web API are deployed on different origins, the browser enforces the Same-Origin Policy.
ASP.NET Core must therefore configure CORS (Cross-Origin Resource Sharing) to explicitly allow requests from the Angular application's origin.
For example:
Angular
https://www.jntech.in
|
| HTTPS request
↓
ASP.NET Core Web API
https://api.jntech.in
These are different origins, so CORS applies.
1. What is CORS?
CORS (Cross-Origin Resource Sharing) is a browser security mechanism that allows a server to specify which other origins are permitted to access its resources.
An origin consists of:
Scheme + Host + Port
For example:
https://www.jntech.in
contains:
Scheme = https
Host = www.jntech.in
Port = 443 (default)
2. Why is CORS needed?
Suppose Angular is running at:
https://www.jntech.in
and ASP.NET Core is running at:
https://api.jntech.in
Angular sends:
this.http.get(
'https://api.jntech.in/api/products'
);
The browser sees:
Current origin:
https://www.jntech.in
Target origin:
https://api.jntech.in
They are different.
Therefore:
Angular
↓
Browser
↓
Cross-Origin Request
↓
CORS rules checked
↓
ASP.NET Core must allow
https://www.jntech.in
Without the correct CORS response, the browser prevents Angular JavaScript from accessing the response.
3. Where should CORS be configured?
CORS should be configured on the ASP.NET Core Web API, not in Angular.
This is important:
Angular
↓
Requests permission
ASP.NET Core
↓
Grants/denies cross-origin access
Angular cannot decide:
"Allow me to bypass CORS."
The API server determines which origins it allows, and the browser enforces the result.
4. Full Simple ASP.NET Core CORS Configuration
Suppose:
Angular:
https://www.jntech.in
ASP.NET Core:
https://api.jntech.in
Configure 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();
});
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseCors("AngularApp");
app.UseAuthorization();
app.MapControllers();
app.Run();
The important part is:
.WithOrigins("https://www.jntech.in")
It tells ASP.NET Core:
Requests originating from
https://www.jntech.inare allowed by this CORS policy.
5. Understanding each configuration
AddCors()
builder.Services.AddCors(options =>
{
});
Registers CORS services with ASP.NET Core.
AddPolicy()
options.AddPolicy("AngularApp", policy =>
{
});
Creates a named policy:
AngularApp
You can have different policies for different requirements.
WithOrigins()
.WithOrigins("https://www.jntech.in")
Specifies the allowed origin.
You can allow multiple frontend origins:
.WithOrigins(
"https://www.jntech.in",
"https://admin.jntech.in"
)
AllowAnyHeader()
.AllowAnyHeader()
Allows request headers permitted by the policy.
This is useful when Angular sends headers such as:
Authorization
Content-Type
X-Correlation-ID
For example:
Authorization: Bearer eyJhbGci...
AllowAnyMethod()
.AllowAnyMethod()
allows HTTP methods such as:
GET
POST
PUT
PATCH
DELETE
6. Apply the policy
After defining the policy:
builder.Services.AddCors(...)
apply it:
app.UseCors("AngularApp");
Conceptually:
Request
↓
ASP.NET Core
↓
CORS Middleware
↓
Check Origin
↓
Allowed?
↓
Continue
7. Angular sample
environment.production.ts
export const environment = {
production: true,
apiUrl: 'https://api.jntech.in/api'
};
product-service.ts
import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../environments/environment';
export interface Product {
id: number;
name: string;
price: number;
}
@Injectable({
providedIn: 'root'
})
export class ProductService {
private http = inject(HttpClient);
private apiUrl =
`${environment.apiUrl}/products`;
getProducts() {
return this.http.get<Product[]>(
this.apiUrl
);
}
}
Angular sends:
GET https://api.jntech.in/api/products
with an Origin header such as:
Origin: https://www.jntech.in
8. ASP.NET Core API
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok(new[]
{
new
{
Id = 1,
Name = "Laptop",
Price = 50000
},
new
{
Id = 2,
Name = "Mouse",
Price = 1000
}
});
}
}
The complete flow is:
Angular
https://www.jntech.in
↓
Browser sends
Origin: https://www.jntech.in
↓
ASP.NET Core
https://api.jntech.in
↓
CORS Middleware
↓
Is https://www.jntech.in allowed?
↓
YES
↓
ProductsController
↓
JSON Response
↓
Browser allows Angular
to read response
9. What response does CORS produce?
When the request is allowed, the API may return a response header such as:
Access-Control-Allow-Origin: https://www.jntech.in
The browser sees:
Request Origin
https://www.jntech.in
↓ compare
Access-Control-Allow-Origin
https://www.jntech.in
↓
Allowed
10. What happens when the origin isn't allowed?
Suppose a site running at:
https://other-example.com
calls:
https://api.jntech.in/api/products
but your API allows only:
.WithOrigins("https://www.jntech.in")
The browser will not receive the required CORS permission for https://other-example.com, so frontend JavaScript cannot access the response.
You may see a browser console error similar to:
Blocked by CORS policy
11. What is a preflight request?
For some cross-origin requests, the browser first sends an HTTP:
OPTIONS
request.
This is called a CORS preflight request.
For example, Angular wants to send:
POST /api/products
Authorization: Bearer ...
Content-Type: application/json
The browser may first ask:
OPTIONS /api/products
Origin: https://www.jntech.in
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Conceptually:
Angular
↓
Browser
↓
OPTIONS
"Can I send POST with these headers?"
↓
ASP.NET Core CORS
↓
Permission response
↓
Browser
↓
Actual POST request
ASP.NET Core CORS middleware handles this when configured correctly.
12. CORS with JWT authentication
Suppose Angular stores/obtains a JWT and sends:
Authorization: Bearer eyJhbGci...
Angular interceptor:
export const authInterceptor: HttpInterceptorFn =
(req, next) => {
const token = localStorage.getItem('token');
const authRequest = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next(authRequest);
};
Your CORS policy can allow the header:
policy
.WithOrigins("https://www.jntech.in")
.AllowAnyHeader()
.AllowAnyMethod();
Notice that JWT authentication and CORS are different concepts.
CORS
↓
Is this browser origin allowed?
JWT Authentication
↓
Who is this user?
Authorization
↓
Is this user allowed to perform this operation?
CORS does not replace authentication or authorization.
13. CORS with cookie authentication
Cookies require extra consideration.
Angular may need:
this.http.get(
'https://api.jntech.in/api/profile',
{
withCredentials: true
}
);
ASP.NET Core:
builder.Services.AddCors(options =>
{
options.AddPolicy("AngularApp", policy =>
{
policy
.WithOrigins("https://www.jntech.in")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
Important:
.AllowCredentials()
allows credentialed cross-origin requests under the policy.
Cookie attributes such as SameSite and Secure also need to be configured correctly depending on the deployment.
14. Don't combine AllowAnyOrigin() with credentials
This is invalid/insecure as a credentialed CORS policy:
policy
.AllowAnyOrigin()
.AllowCredentials();
When credentials are allowed, specify trusted origins explicitly:
policy
.WithOrigins("https://www.jntech.in")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
This is an important interview question.
15. What does AllowAnyOrigin() mean?
You might see:
policy
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
This effectively allows browser requests from any origin under the CORS policy.
It may be convenient during development or appropriate for an intentionally public API, but it should not be used automatically for a private production application.
For your own Angular frontend, prefer:
.WithOrigins("https://www.jntech.in")
16. Development and Production
During development:
Angular:
http://localhost:4200
API:
https://localhost:7001
You could allow:
.WithOrigins("http://localhost:4200")
Production:
Angular:
https://www.jntech.in
API:
https://api.jntech.in
requires:
.WithOrigins("https://www.jntech.in")
If the API needs to support both:
.WithOrigins(
"http://localhost:4200",
"https://www.jntech.in"
)
However, production configuration is often kept environment-specific rather than permanently mixing development origins into production settings.
17. Better production configuration
Instead of hard-coding the frontend URL:
.WithOrigins("https://www.jntech.in")
you can keep it in ASP.NET Core configuration.
appsettings.json
{
"Cors": {
"AllowedOrigins": [
"https://www.jntech.in"
]
}
}
Then:
var allowedOrigins =
builder.Configuration
.GetSection("Cors:AllowedOrigins")
.Get<string[]>()!;
builder.Services.AddCors(options =>
{
options.AddPolicy("AngularApp", policy =>
{
policy
.WithOrigins(allowedOrigins)
.AllowAnyHeader()
.AllowAnyMethod();
});
});
This is easier to manage across environments.
For example:
Development
↓
http://localhost:4200
SIT
↓
https://sit.jntech.in
UAT
↓
https://uat.jntech.in
Production
↓
https://www.jntech.in
18. Middleware order
A typical configuration is:
var app = builder.Build();
app.UseHttpsRedirection();
app.UseCors("AngularApp");
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
The important idea is that CORS middleware needs to run in the correct place in the ASP.NET Core request pipeline so it can process cross-origin requests appropriately.
19. Why does the API work in Postman but fail in Angular?
This is one of the most common interview questions.
Suppose:
Postman → API → Works
Angular Browser → API → CORS Error
Why?
Because CORS is primarily a browser-enforced security mechanism.
Postman is not a browser executing JavaScript under the browser's Same-Origin Policy.
Therefore:
Postman
↓
API
↓
No browser Same-Origin Policy
Angular
↓
Browser
↓
Same-Origin Policy
↓
CORS checked
↓
API
So:
"It works in Postman" does not prove that browser CORS configuration is correct.
20. CORS is not a firewall
Another important point:
Suppose your CORS policy says:
.WithOrigins("https://www.jntech.in")
That does not mean only jntech.in can physically send HTTP requests to your API.
Non-browser clients may still call:
https://api.jntech.in/api/products
CORS controls what browser JavaScript from other origins can access.
Therefore:
CORS ≠ Authentication
CORS ≠ Authorization
CORS ≠ Firewall
Your API still needs proper:
- authentication
- authorization
- HTTPS
- input validation
- rate limiting where appropriate
- network/security controls where required
Complete Flow
For a separately deployed Angular + ASP.NET Core application:
Angular
https://www.jntech.in
↓
Angular HttpClient
↓
Browser sees different origin
↓
Possible OPTIONS preflight
↓
ASP.NET Core CORS Middleware
↓
Check:
Is https://www.jntech.in allowed?
↓ YES
Actual API request
↓
Authentication
↓
Authorization
↓
Controller
↓
Database
↓
Response
↓
CORS response headers
↓
Browser
↓
Angular receives response
Key Points
- CORS is needed when Angular and ASP.NET Core are accessed through different origins.
- CORS is configured primarily on the ASP.NET Core API.
- Register it using:
builder.Services.AddCors(...)
- Apply it using:
app.UseCors("AngularApp");
- In production, explicitly allow trusted Angular origins:
.WithOrigins("https://www.jntech.in")
AllowAnyHeader()permits required request headers according to the policy.AllowAnyMethod()permits HTTP methods such as GET, POST, PUT and DELETE.- Some requests cause an automatic OPTIONS preflight.
- Cookie-based cross-origin authentication may require:
.AllowCredentials()
and Angular:
withCredentials: true
- Don't use
AllowAnyOrigin()together withAllowCredentials(). - CORS is enforced primarily by browsers, which explains why an API may work in Postman but fail from Angular.
- CORS is not authentication or authorization.
Interview Questions and Answers
1. How do you handle CORS when Angular and ASP.NET Core are deployed separately?
Configure a CORS policy in ASP.NET Core that explicitly allows the Angular application's origin.
policy
.WithOrigins("https://www.jntech.in")
.AllowAnyHeader()
.AllowAnyMethod();
Then apply it:
app.UseCors("AngularApp");
2. Why is CORS required?
Because browsers enforce the Same-Origin Policy. If Angular and the API have different scheme, host, or port, the request is cross-origin.
3. Where should CORS be configured?
Primarily on the ASP.NET Core API because the server declares which origins are allowed to access its resources from browser JavaScript.
4. What is an origin?
An origin is:
Scheme + Host + Port
For example:
https://www.jntech.in:443
5. What is a CORS preflight request?
It is an HTTP OPTIONS request automatically sent by the browser before certain cross-origin requests to check whether the actual method and headers are permitted.
6. Why does the API work in Postman but fail from Angular?
Postman doesn't enforce the browser's Same-Origin Policy. Angular runs inside a browser, where CORS restrictions are enforced.
7. Should AllowAnyOrigin() be used in production?
Not automatically. For an application intended for known frontend origins, explicitly specify those trusted origins using WithOrigins().
8. What is required for cross-origin cookie authentication?
ASP.NET Core may require:
.AllowCredentials()
and Angular:
{ withCredentials: true }
Cookie SameSite and Secure configuration must also be appropriate.
9. Does CORS secure the Web API from Postman or other non-browser clients?
No. CORS is not an API security boundary against arbitrary HTTP clients. Authentication and authorization are still required.
10. What is a strong short interview answer?
When Angular and ASP.NET Core Web API are deployed on different origins, I configure a CORS policy on the ASP.NET Core API using
AddCors(), explicitly allow the Angular production origin withWithOrigins(), allow the required headers and HTTP methods, and apply the policy usingUseCors(). The browser then validates the API's CORS response headers. For credentialed cookie requests, I also configureAllowCredentials()and the appropriate cookie settings.