Where Should Secrets Be Stored in an Angular + ASP.NET Core Architecture?
1. What Are Secrets?
Secrets are confidential values that must not be exposed to the browser or committed to source code.
Examples:
- SQL Server passwords and connection strings containing credentials
- JWT signing keys/private keys
- OAuth client secrets
- Private third-party API keys
- Storage account keys
- Service credentials
In an Angular + ASP.NET Core architecture, secrets belong on the server side, not in Angular.
Angular Browser
│
│ HTTPS
▼
ASP.NET Core Web API
│
├── Reads secrets securely
│
▼
Secret Store / Server Configuration
│
├── Database credentials
├── API secrets
└── Signing keys
2. Full Simple Sample
Assume:
Angular
↓
ASP.NET Core Web API
↓
SQL Server
and ASP.NET Core also calls an external payment API.
Angular environment.ts
Angular should contain only non-secret configuration:
export const environment = {
production: false,
apiUrl: 'https://localhost:7001/api'
};
This is fine because the browser needs to know the API address.
Do not do this:
export const environment = {
apiUrl: 'https://localhost:7001/api',
// ❌ Never do this
databasePassword: 'Password123',
jwtSecret: 'super-secret-key',
paymentApiKey: 'payment-secret-123'
};
3. Angular Service
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 only knows:
https://localhost:7001/api
It doesn't know the SQL Server password or other backend secrets.
4. ASP.NET Core — Development Secrets
For local development, ASP.NET Core provides User Secrets.
Initialize it:
dotnet user-secrets init
Store the SQL Server connection string:
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=ShopDb;User Id=appuser;Password=Secret123;TrustServerCertificate=True"
Store an external API secret:
dotnet user-secrets set "PaymentApi:ApiKey" "PAYMENT-SECRET-123"
These secrets are stored outside your project source tree rather than being committed to Git.
5. Read Secrets in ASP.NET Core
Program.cs
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Read connection string
var connectionString =
builder.Configuration.GetConnectionString("DefaultConnection");
// Configure EF Core
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(connectionString);
});
// Read private API key
var paymentApiKey =
builder.Configuration["PaymentApi:ApiKey"];
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
ASP.NET Core's configuration system provides the values to the application without Angular ever receiving them.
6. What About appsettings.json?
You can use appsettings.json for non-secret configuration.
For example:
{
"Logging": {
"LogLevel": {
"Default": "Information"
}
},
"PaymentApi": {
"BaseUrl": "https://payments.example.com"
}
}
Avoid committing real production secrets such as:
{
"ConnectionStrings": {
"DefaultConnection":
"Server=prod;User Id=sa;Password=RealProductionPassword"
},
"PaymentApi": {
"ApiKey": "REAL-PRODUCTION-SECRET"
}
}
The problem is not that appsettings.json can never technically contain a secret; the problem is committing plaintext production credentials into source control or deploying them without appropriate protection.
7. Recommended Storage by Environment
A practical architecture is:
| Environment | Recommended Secret Storage |
|---|---|
| Angular | Never store confidential secrets |
| Local ASP.NET Core | User Secrets |
| Development server | Environment/platform secrets or secret manager |
| SIT/UAT | Environment/platform secrets or managed secret store |
| Production | Managed secret store such as Azure Key Vault |
For an Azure-hosted application, a common architecture is:
Angular
│
▼
ASP.NET Core
│
│ Managed Identity
▼
Azure Key Vault
│
├── DB credentials if needed
├── Third-party API secrets
└── Other application secrets
8. Azure Key Vault
For production, Azure Key Vault can store secrets centrally.
Conceptually:
Azure Key Vault
│
├── DatabaseConnectionString
├── PaymentApiKey
├── ExternalApiSecret
└── Other secrets
ASP.NET Core can access Key Vault through its Azure identity rather than embedding Key Vault credentials directly into the application.
A common design is:
ASP.NET Core
│
│ Managed Identity
▼
Azure Key Vault
│
▼
Secret
This avoids creating another secret merely to access your secret store.
9. Environment Variables
ASP.NET Core can also receive secrets through environment variables or hosting-platform configuration.
For example:
PaymentApi__ApiKey=PAYMENT-SECRET-123
ASP.NET Core maps the double underscore:
__
to the configuration hierarchy separator:
:
Therefore:
PaymentApi__ApiKey
can be accessed as:
builder.Configuration["PaymentApi:ApiKey"];
This is useful with hosting systems, containers, and CI/CD pipelines, although the security ultimately depends on how the deployment platform protects and supplies those variables.
10. Configuration Precedence
One major benefit of ASP.NET Core configuration is that your application code doesn't need to know exactly where a value came from.
You can write:
var apiKey =
builder.Configuration["PaymentApi:ApiKey"];
The value can be supplied through the configured providers, such as:
appsettings.json
↓
appsettings.{Environment}.json
↓
User Secrets (development)
↓
Environment Variables
↓
Command-line configuration
↓
Additional providers such as Key Vault
The effective precedence depends on the order in which configuration providers are added; later providers generally override earlier values.
So your application code remains:
builder.Configuration["PaymentApi:ApiKey"]
regardless of whether the deployment supplies the value through User Secrets, environment variables, or Key Vault.
11. Recommended Architecture
For Angular + ASP.NET Core:
┌───────────────────────────────┐
│ Angular Browser │
│ │
│ API URL │
│ Public client configuration │
└──────────────┬────────────────┘
│
│ HTTPS
▼
┌───────────────────────────────┐
│ ASP.NET Core Web API │
│ │
│ Authentication │
│ Authorization │
│ Business Logic │
│ Database Access │
└──────────────┬────────────────┘
│
│ Secure identity
▼
┌───────────────────────────────┐
│ Secret Management │
│ │
│ Azure Key Vault │
│ Environment/platform secrets │
│ User Secrets (local dev) │
└──────────────┬────────────────┘
│
┌────┴────┐
▼ ▼
SQL Server External APIs
The key security boundary is:
Browser
│
│ Never receives server secrets
▼
Backend
│
▼
Secret Store
12. What About JWT?
There are two very different things:
JWT access token
An issued access token may be sent to Angular:
Authorization: Bearer <access-token>
because Angular needs it to authenticate API requests.
JWT signing key
The key used to create/validate signatures is server-side cryptographic material.
JWT Access Token
↓
Can be issued to Angular
JWT Signing Key / Private Key
↓
Authentication server/backend
↓
Never Angular
Don't confuse an issued credential with the server's signing secret/private key.
13. What About OAuth?
Similarly:
Client ID
↓
Usually public identifier
↓
May appear in Angular
Client Secret
↓
Confidential credential
↓
Must NOT be stored in Angular
An Angular SPA is a public client and cannot reliably keep a client secret confidential.
Key Points
- Angular cannot securely store confidential secrets.
- Anything sent to the browser should be considered potentially inspectable.
- Angular can contain non-secret configuration such as:
apiUrl: 'https://api.example.com'
- Keep database credentials, private API keys, signing keys, and client secrets on the backend.
- For local ASP.NET Core development, User Secrets are convenient.
- For deployed environments, use protected environment/platform configuration or a managed secret store.
- On Azure, Azure Key Vault + Managed Identity is a strong pattern because the application can authenticate to Key Vault without embedding another credential.
- Don't commit production passwords into
appsettings.json. - Angular should never connect directly to SQL Server.
Angular → ASP.NET Core → SQL Server
Interview Questions and Answers
1. Where should secrets be stored in an Angular + ASP.NET Core application?
Secrets should be stored server-side, using mechanisms such as ASP.NET Core User Secrets for local development, protected environment/platform configuration, or a managed secret store such as Azure Key Vault.
2. Can secrets be stored in Angular environment.ts?
No. Angular executes in the browser, so values included in its code or downloadable configuration can potentially be inspected.
3. Where should I store secrets during local development?
Use ASP.NET Core User Secrets:
dotnet user-secrets set "PaymentApi:ApiKey" "secret"
This keeps the value outside the project's source files.
4. Where should production secrets be stored?
A managed secret store such as Azure Key Vault is appropriate, or the secure secret/configuration facilities provided by your hosting platform.
5. Should production passwords be stored in appsettings.Production.json?
Avoid committing plaintext production secrets there. Keep non-secret configuration in appsettings files and inject confidential values from protected server-side sources.
6. How does ASP.NET Core read a secret?
Through IConfiguration, for example:
var apiKey =
builder.Configuration["PaymentApi:ApiKey"];
The underlying value can come from whichever configuration provider your environment uses.
7. Should Angular know the SQL Server connection string?
No.
The architecture should be:
Angular
↓
ASP.NET Core Web API
↓
SQL Server
Only the backend needs database connectivity.
8. Why use Managed Identity with Azure Key Vault?
Managed Identity allows an Azure-hosted ASP.NET Core application to authenticate to Azure resources without storing a separate username/password or client secret in the application.
9. What is the best short interview answer?
In an Angular + ASP.NET Core architecture, confidential secrets should never be stored in Angular because browser-delivered code can be inspected. Keep secrets on the ASP.NET Core/server side—using User Secrets for local development and protected environment configuration or a managed secret store such as Azure Key Vault in deployed environments. Angular should contain only non-sensitive configuration such as the API base URL.