Published: February 16, 2026
Author: Václav Švára
Generated with assistance from: Claude (Anthropic AI)
Table of Contents
- Introduction
- The Challenge
- 🔴 CRITICAL: CapacitorHttp Configuration
- Architecture Overview
- Prerequisites
- Azure AD App Registration
- MSAL Configuration
- Authentication Service Implementation
- Deep Link Handling (iOS)
- Deep Link Handling (Android)
- Login Flow
- Token Management
- HTTP Interceptor
- Testing the Implementation
- Troubleshooting
- Security Best Practices
- Conclusion
Introduction
Implementing Microsoft Authentication (MSAL) in a Capacitor Angular application presents unique challenges compared to standard web applications. The combination of native mobile platforms (iOS/Android) with web technologies requires special handling of authentication flows, deep links, and token management.
This comprehensive guide walks you through every step of implementing MSAL authentication in a Capacitor Angular app, from Azure AD configuration to production-ready code.
⚠️ IMPORTANT: Before starting, read the CRITICAL: CapacitorHttp Configuration section. This single configuration prevents the #1 cause of MSAL authentication failures in Capacitor apps (CORS errors).
The Challenge
Why is MSAL different in Capacitor?
Custom URL Schemes: Capacitor apps run oncapacitor://localhostinstead ofhttps://domains
Deep Link Redirects: OAuth redirects must be handled by native app deep links
Browser Context: MSAL expects a standard browser environment, but Capacitor uses a WebView
Token Storage: Secure token storage differs between web and native platforms
Silent Token Refresh: Silent refresh in iframes doesn't work in native WebViews
What we'll build
A complete authentication solution that:
- ✅ Works on iOS, Android, and Web (PWA)
- ✅ Bypasses CORS issues with CapacitorHttp (critical!)
- ✅ Handles OAuth2 redirect flow properly
- ✅ Stores tokens securely
- ✅ Automatically refreshes expired tokens
- ✅ Attaches JWT tokens to API requests
- ✅ Handles login/logout gracefully
🔴 CRITICAL: CapacitorHttp Configuration
⚠️ READ THIS FIRST - Authentication Will Fail Without It!
This is the #1 reason MSAL fails in Capacitor apps. Before implementing anything else, you MUST configure CapacitorHttp, or authentication will fail with CORS errors.
The Problem
Azure AD (login.microsoftonline.com) rejects the capacitor://localhost origin during MSAL token exchange:
MSAL.js → fetch('https://login.microsoftonline.com/token')
Request Origin: capacitor://localhost
Azure AD Response: ❌ CORS error (Origin not allowed)
Result: ❌ Authentication fails
The Solution
Enable CapacitorHttp in your Capacitor config. This automatically patches ALL HTTP requests (including MSAL's token exchange) to use native HTTP, which bypasses CORS entirely:
MSAL.js → CapacitorHttp patch → Native HTTP (no Origin header)
Azure AD Response: ✅ 200 OK
Result: ✅ Authentication succeeds!
Required Configuration
File: capacitor.config.ts
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.yourcompany.yourapp',
appName: 'YourApp',
webDir: 'dist',
plugins: {
CapacitorHttp: {
enabled: true, // 🔴 CRITICAL: Enable native HTTP (bypasses CORS)
},
},
};
export default config;
Why This Works
- ✅ Zero code changes - MSAL.js works without modifications
- ✅ Automatic patching - All fetch/XHR/HttpClient requests use native HTTP
- ✅ No CORS errors - Native HTTP doesn't send Origin header
- ✅ Transparent - Your Angular code doesn't know the difference
What Gets Automatically Patched
With CapacitorHttp: { enabled: true }, these are automatically converted to native HTTP:
- ✅ MSAL.js token requests (Azure AD communication)
- ✅ Angular HttpClient (your API calls)
- ✅ JavaScript fetch() (any library using fetch)
- ✅ XMLHttpRequest (legacy AJAX)
- ✅ All third-party libraries (automatic)
❌ Common Mistakes
DON'T create wrapper services:
// ❌ WRONG - Unnecessary and won't help MSAL
export class HttpWrapperService {
// Wrapper services don't help because MSAL uses fetch() directly
}
DON'T add capacitor://localhost to backend CORS:
// ❌ WRONG - Will never be used with CapacitorHttp enabled
builder.Services.AddCors(options => {
options.AddPolicy("AllowCapacitor", policy => {
policy.WithOrigins("capacitor://localhost") // ❌ Useless
});
});
Backend CORS Configuration
With CapacitorHttp: { enabled: true }, your backend doesn't need CORS configuration for native apps because:
- Native HTTP doesn't send
Originheader - CORS is a browser security feature, not a native app concern
You only need CORS if:
- Testing in web browser (development)
- Supporting web version (PWA) alongside mobile
// ASP.NET Core - ONLY for web browser/PWA support
builder.Services.AddCors(options => {
options.AddPolicy("AllowWeb", policy => {
policy.WithOrigins("http://localhost:4200") // Web dev server only
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
app.UseCors("AllowWeb");
Verification
After enabling CapacitorHttp, verify it's working:
Build and run on device:
npm run build
npx cap sync
npx cap run ios # or android
Check console logs:
If you see CORS errors, CapacitorHttp is NOT enabled correctly.
Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ Angular Application │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Authentication Service │ │
│ │ - Login / Logout │ │
│ │ - Token acquisition │ │
│ │ - Silent refresh │ │
│ └──────────────────┬───────────────────────────────────┘ │
│ │ │
│ ┌──────────────────▼───────────────────────────────────┐ │
│ │ MSAL Angular Library │ │
│ │ (@azure/msal-angular, @azure/msal-browser) │ │
│ └──────────────────┬───────────────────────────────────┘ │
└────────────────────┼────────────────────────────────────────┘
│
┌───────────┴───────────┐
│ │
┌────▼─────┐ ┌─────▼────┐
│ Web │ │ Native │
│ (PWA) │ │ (iOS/ │
│ │ │ Android) │
│ Standard │ │ Deep │
│ Redirect │ │ Links │
└────┬─────┘ └─────┬────┘
│ │
└──────────┬───────────┘
│
┌──────────▼──────────┐
│ Azure AD / Entra │
│ OAuth2 Provider │
└─────────────────────┘
Prerequisites
Required Knowledge
- Angular (v16+)
- TypeScript
- Capacitor basics
- OAuth2 / OpenID Connect concepts
Required Tools
# Node.js and npm
node --version # v18+ recommended
npm --version
# Angular CLI
npm install -g @angular/cli
# Capacitor CLI
npm install -g @capacitor/cli
# Xcode (macOS, for iOS)
# Android Studio (for Android)
Required Packages
# MSAL packages
npm install @azure/msal-browser @azure/msal-angular
# Capacitor core
npm install @capacitor/core @capacitor/cli
# Capacitor platforms
npm install @capacitor/ios @capacitor/android
# RxJS (usually already in Angular)
npm install rxjs
Azure AD App Registration
Step 1: Create App Registration
- Go to
- OAuth 2.0 Authorization Code Flow
Published: February 16, 2026
Author: Václav Švára
Generated with assistance from: Claude (Anthropic AI)
License: MIT
Did you find this guide helpful? Share your experience or questions in the comments below!
SOCIAL SHARE CARD GENERATOR