Why Should Database Passwords and API Secrets Never Be Shipped in Angular Code?
1. What Does “Shipped in Angular Code” Mean?
Angular is a client-side application. After you build and deploy it, the generated JavaScript files are downloaded to the user's browser.
So if you put a database password or private API secret anywhere in Angular source code, that value can ultimately reach the client.
For example, this is unsafe:
export const environment = {
apiUrl: 'https://api.example.com',
databasePassword: 'DbPassword@123',
privateApiKey: 'SECRET-API-KEY-123'
};
Even if this is placed in:
environment.production.ts
it is not secure.
2. Full Simple Example
Consider an Angular application with an ASP.NET Core Web API and SQL Server.
❌ Wrong Architecture
Angular Browser
│
├── Database Password ❌
├── Private API Key ❌
│
▼
SQL Server / External Service
The browser should never possess these credentials.
❌ Wrong Angular Code
export const environment = {
production: true,
apiUrl: 'https://api.example.com',
connectionString:
'Server=prod-db;Database=ShopDb;User Id=sa;Password=Secret123;',
paymentApiKey:
'PAYMENT-SECRET-123'
};
This is dangerous because these values can end up in browser-delivered JavaScript.
3. Correct Architecture
The correct architecture is:
HTTPS
Angular Browser ──────────► ASP.NET Core Web API
│
│
┌──────────┴──────────┐
│ │
▼ ▼
SQL Server External API
▲ ▲
│ │
DB Credentials Private API Key
│ │
└──────────┬──────────┘
│
Server-side
configuration
Angular only needs to know something like:
export const environment = {
apiUrl: 'https://api.example.com'
};
It does not need to know:
Database password
Connection string
JWT signing key
Private API key
Client secret
4. Simple Angular Code
environment.ts
export const environment = {
apiUrl: 'https://localhost:7001/api'
};
product.ts
import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
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(): Observable<Product[]> {
return this.http.get<Product[]>(this.apiUrl);
}
}
Angular knows only:
https://localhost:7001/api/products
It does not know how ASP.NET Core connects to SQL Server.
5. ASP.NET Core Handles Database Access
The backend might read its connection string from server-side configuration:
var builder = WebApplication.CreateBuilder(args);
var connectionString =
builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddSqlServer<AppDbContext>(
connectionString);
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
For local development, secrets can be supplied through ASP.NET Core User Secrets, environment variables, or another protected development mechanism.
For production, organizations commonly use a managed secret store such as Azure Key Vault or platform-provided secret/environment configuration.
The important boundary is:
Angular
↓
No database credentials
ASP.NET Core
↓
Obtains credentials securely
↓
SQL Server
6. Why Is Shipping Secrets in Angular Dangerous?
Reason 1 — Angular Runs on the User's Machine
Angular isn't running only on your server.
The browser downloads the application's JavaScript.
Angular source
↓
ng build
↓
JavaScript bundles
↓
Web Server
↓
User's Browser
Anything the browser needs in plaintext should be treated as information the user can potentially access.
Reason 2 — Users Can Inspect Browser Resources
Users have browser developer tools.
They can inspect things such as:
Network requests
JavaScript files
Application storage
Request headers
Responses
Loaded resources
Therefore, this is not a security strategy:
const secret = 'MY-SUPER-SECRET-KEY';
7. “But Production Angular Is Minified”
Minification does not solve the problem.
Suppose:
const privateApiKey =
'SECRET-ABC-123';
After a production build, variable names and surrounding code may be transformed or compressed.
But the application still needs the value:
SECRET-ABC-123
to use it.
Therefore:
Minification
≠
Encryption
≠
Secret protection
Minification is primarily a build/performance optimization, not a security boundary.
8. “What If I Hide the Secret in Another Angular File?”
That also doesn't solve it.
For example:
environment.ts
config.ts
constants.ts
service.ts
assets/config.json
runtime-config.json
If the browser can download the value, you must assume the user can obtain it.
This includes runtime configuration too.
For example:
{
"apiUrl": "https://api.example.com",
"databasePassword": "Secret123"
}
If Angular downloads this JSON, the password is exposed.
Runtime configuration is useful for changing configuration between deployments, but it is not a secret store.
9. What Could an Attacker Do With a Database Password?
Suppose Angular contained:
Server=sql.example.com;
Database=ShopDb;
User Id=appuser;
Password=Secret123;
If an attacker obtains those credentials and the database is network-accessible to them, they may attempt unauthorized database operations within whatever privileges that account has.
Potential consequences include:
Read sensitive data
Modify data
Delete data
Abuse database privileges
Attempt further compromise
This is also one reason Angular should never connect directly to SQL Server.
Correct:
Angular
↓
ASP.NET Core API
↓
SQL Server
Not:
Angular
↓
SQL Server ❌
10. What Could Happen If a Private API Key Is Exposed?
Suppose you put:
privateApiKey: 'PAYMENT-SECRET-123'
in Angular.
Someone who extracts the key may try to call the external API independently of your application.
Depending on what that credential permits, this could lead to:
Unauthorized API calls
Quota consumption
Unexpected charges
Unauthorized data access
Abuse of privileged operations
The exact impact depends on the API and the permissions attached to the credential.
11. Correct Way to Use a Private API Key
Suppose your application communicates with a third-party service.
Don't do:
Angular
│
│ Private API Key ❌
▼
Third-Party API
Instead:
Angular
│
│ Normal authenticated request
▼
ASP.NET Core API
│
│ Private API Key
▼
Third-Party API
ASP.NET Core owns and protects the credential.
Angular never receives it.
12. Public API Key vs Private API Secret
Not every value called an "API key" is necessarily confidential.
Some platforms intentionally provide public client identifiers/keys for browser applications.
The important question is:
Does possession of this value grant confidential or privileged access?
If yes, it must not be shipped to Angular.
For example:
Public client identifier
↓
May be designed for browser exposure
Private API secret
↓
Must remain confidential
↓
Backend only
Always follow the provider's documentation about whether a particular credential is public or confidential.
13. What About JWT?
Another common interview confusion is:
JWT Access Token
vs
JWT Signing Secret
They are different.
An issued access token may be provided to the browser because the client needs it to authenticate requests:
Authorization: Bearer <access-token>
But the JWT signing secret/private key must remain on the authentication server/backend.
JWT Access Token
↓
May be issued to Angular
JWT Signing Secret / Private Key
↓
Backend only
↓
Never Angular
14. What Can Angular Safely Contain?
Generally, non-secret configuration can be exposed:
export const environment = {
apiUrl: 'https://api.example.com/api',
applicationName: 'MyApp',
production: true
};
Think of Angular configuration as:
Public configuration delivered to the browser.
Not:
A secure secret vault.
Key Points
- Angular is a client-side application.
- Angular's JavaScript is downloaded to the user's browser.
- Anything shipped to the browser should be treated as potentially inspectable.
- Never put database passwords in Angular.
- Never put SQL connection strings containing credentials in Angular.
- Never put JWT signing keys in Angular.
- Never put OAuth client secrets in Angular.
- Never put private API keys in Angular.
- Minification does not protect secrets.
- Environment files are configuration, not secure secret storage.
- Runtime configuration files are also not appropriate for secrets if they are downloaded by the browser.
- Angular should call ASP.NET Core:
Angular → ASP.NET Core → SQL Server
- ASP.NET Core should obtain confidential credentials from server-side configuration or a secret-management system.
Interview Questions and Answers
1. Why should database passwords never be stored in Angular?
Because Angular runs in the browser. Any password included in the Angular application can potentially be extracted from browser-delivered resources.
2. Why should private API secrets not be stored in Angular?
A user can potentially extract the secret and use it independently of your application, potentially gaining whatever privileges the credential provides.
3. Does a production Angular build protect secrets?
No. Production optimization and minification do not create a security boundary. Confidential values must not be included in browser-delivered code.
4. Where should database credentials be stored?
On the server side. ASP.NET Core can obtain them from protected configuration mechanisms such as environment variables, development User Secrets, or managed secret stores such as Azure Key Vault.
5. Should Angular directly access SQL Server?
No.
Use:
Angular
↓
ASP.NET Core Web API
↓
SQL Server
The backend provides authentication, authorization, validation, business logic, and controlled database access.
6. Is an API URL considered a secret?
Normally, no.
This is generally fine:
apiUrl: 'https://api.example.com/api'
The browser must know the endpoint it is communicating with.
7. Is a JWT token a secret?
An issued access token is a credential and must be handled carefully, but it is fundamentally different from the server's JWT signing secret/private key.
The signing key must never be shipped to Angular.
8. Can runtime configuration securely hide secrets?
No. If Angular downloads a runtime configuration file containing the secret, the browser receives the secret and it can potentially be inspected.
9. What is the short interview answer?
Database passwords and private API secrets must never be shipped in Angular because Angular runs in the user's browser and its JavaScript and configuration can be inspected. Minification does not protect secrets. Confidential credentials should remain on the ASP.NET Core backend and be obtained from secure server-side configuration or a secret store such as Azure Key Vault.