Skip to main content

Implementing Security Best Practices

1. Sanitizing User Input

Input Type Description Sanitization Method Notes
HTML Content Untrusted HTML content from users DOMPurify Prevents XSS attacks by stripping dangerous tags
User Text Plain text input (e.g., comments, names) escape-html Escapes HTML characters to prevent injection
URLs User-provided URLs in links or redirects validator.js Validates and sanitizes URLs to ensure they are safe

Example: Using DOMPurify to Sanitize HTML

import DOMPurify from 'dompurify';

const dirty = '<script>alert("XSS")</script><p>Hello <b>World</b></p>';
const clean = DOMPurify.sanitize(dirty);
console.log(clean); // <p>Hello <b>World</b></p>

Example: Escaping User Text

import escapeHtml from 'escape-html';

const userInput = '<script>alert("Hello")</script>';
const escaped = escapeHtml(userInput);
console.log(escaped); // &lt;script&gt;alert(&quot;Hello&quot;)&lt;/script&gt;
Note: Always sanitize user input before rendering it in the DOM or storing it in a database.
Warning: Never rely solely on client-side sanitization. Always validate and sanitize on the server as well.

2. Implementing Authentication

Feature Description Implementation
Authentication Flow OAuth 2.0 or OpenID Connect for secure login import { AuthModule } from '@ionic/auth';
Token Management JWT-based tokens with refresh logic const token = await auth.getToken();
Session Handling Automatic session timeout and re-authentication auth.onSessionExpired(() => { ... });

Example: Setting up Auth in Ionic

import { Auth } from '@ionic/auth';

const auth = new Auth({
  auth0Domain: 'your-domain.auth0.com',
  clientId: 'your-client-id'
});

auth.login().then(() => {
  console.log('User logged in');
});
Note: Ensure all authentication flows are handled securely and tokens are stored in secure storage like SecureStorage.
Warning: Never expose client secrets or sensitive tokens in frontend code.

3. Using HTTPS Connections

Property Description Default Notes
ssl.enabled Enables or disables SSL/TLS encryption for network requests false Must be enabled in production environments
ssl.certificate Path to the SSL certificate file (PEM format) null Required if ssl.enabled is true
ssl.key Path to the private key file (PEM format) null Required if ssl.enabled is true
ssl.trustStore Path to the trust store containing CA certificates null Used for validating server certificates

Example: Enabling HTTPS in Ionic App

import { HttpClientModule } from '@angular/common/http';
import { HttpsInterceptor } from './https.interceptor';

@NgModule({
  imports: [
    HttpClientModule
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpsInterceptor,
      multi: true
    }
  ]
})
export class AppModule { }
Note: Ensure all API endpoints are accessed over HTTPS to prevent man-in-the-middle attacks.
Warning: Never hardcode SSL certificates or keys in your source code. Use environment variables or secure configuration files.

4. Storing Sensitive Data

Storage Method Description Security Level Notes
localStorage localStorage.setItem('key', 'value') Limited Not secure for sensitive data; accessible via JavaScript
sessionStorage sessionStorage.setItem('key', 'value') Limited Same risks as localStorage; cleared on session end
Encrypted Database (SQLite) const db = new SQLite('encrypted.db'); Good Secure if properly encrypted and key managed
Secure HTTP Headers Content-Security-Policy: default-src 'self' Good Prevents XSS and data leakage
Environment Variables process.env.API_KEY Good Not accessible in client-side code; must be injected at build time

Example: Securely Storing API Keys

import { Capacitor } from '@capacitor/core';
import { SecureStoragePlugin } from '@ionic-native/secure-storage';

if (Capacitor.isNativePlatform()) {
  const secureStorage = new SecureStoragePlugin();
  secureStorage.set({ key: 'api_key', value: process.env.API_KEY });
}
Note: Never store sensitive data in plain text or client-side storage. Use platform-specific secure storage when available.

5. Implementing OAuth Flow

Step Description Implementation
1. Setup Configure OAuth provider (e.g., Auth0, Firebase)
import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';

const firebaseConfig = {
  apiKey: "your-api-key",
  authDomain: "your-app.firebaseapp.com",
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
2. Redirect URL Define redirect URI in OAuth provider settings https://yourdomain.com/oauth/callback
3. Initiate Auth Redirect user to OAuth provider login page
const provider = new GoogleAuthProvider();
await signInWithPopup(auth, provider);
4. Handle Callback Receive and process OAuth response
auth.onAuthStateChanged(user => {
  if (user) {
    console.log("User logged in", user);
  }
});

Example: Ionic + Firebase Auth Setup

import { initializeApp } from 'firebase/app';
import { getAuth } from 'firebase/auth';

const firebaseConfig = {
  apiKey: "your-api-key",
  authDomain: "your-app.firebaseapp.com",
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

// Sign in with Google
const provider = new GoogleAuthProvider();
signInWithPopup(auth, provider)
  .then(result => {
    const user = result.user;
    console.log("Signed in as:", user.email);
  })
  .catch(error => {
    console.error("Login error:", error);
  });
Note: Ensure redirect URIs are whitelisted in your OAuth provider dashboard.
Warning: Never store sensitive credentials in client-side code.

6. Using Content Security Policy

Directive Description Default Value Example
default-src Defines the default source for various resources 'self' default-src 'self';
script-src Controls sources for JavaScript execution 'self' script-src 'self' 'unsafe-inline';
style-src Controls sources for CSS stylesheets 'self' style-src 'self' 'unsafe-inline';
img-src Controls sources for images 'self' img-src 'self' data:;
connect-src Controls sources for network requests 'self' connect-src 'self' https://api.example.com;
font-src Controls sources for font files 'self' font-src 'self' https://fonts.googleapis.com;
object-src Controls sources for embedded objects 'none' object-src 'none';
media-src Controls sources for media elements 'self' media-src 'self' blob:;
frame-src Controls sources for embedded frames 'self' frame-src 'self';
base-uri Controls the base URL for relative URLs 'self' base-uri 'self';

Example: Setting up CSP in Ionic App

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com; font-src 'self' https://fonts.googleapis.com; object-src 'none'; media-src 'self' blob:; frame-src 'self'; base-uri 'self';">
Note: The Content Security Policy (CSP) is a security feature that helps prevent cross-site scripting (XSS) and other code injection attacks. It is recommended to set a strict CSP for Ionic apps to enhance security.
Warning: Be cautious when using 'unsafe-inline' in script-src or style-src. It can make your app vulnerable to XSS attacks. Prefer using hash or nonce values for inline scripts and styles.

7. Preventing XSS Attacks

Technique Description Implementation
DOMPurify Sanitizes HTML to prevent XSS import DOMPurify from 'dompurify';\nconst clean = DOMPurify.sanitize(dirtyHtml);
Angular Sanitization Built-in HTML sanitization in Angular import { DomSanitizer } from '@angular/platform-browser';\nconst safeHtml = sanitizer.bypassSecurityTrustHtml(htmlString);
Ionic Content Security Policy (CSP) Restricts content sources to prevent XSS <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline';">

Example: Using DOMPurify in Ionic

import DOMPurify from 'dompurify';

const dirtyHtml = '<script>alert("XSS")</script><p>Safe content</p>';
const cleanHtml = DOMPurify.sanitize(dirtyHtml);

console.log(cleanHtml); // <p>Safe content</p>
Note: Always sanitize user-generated content before rendering it in the DOM.
Warning: Never rely solely on client-side sanitization. Server-side validation is also critical.

8. Implementing Certificate Pinning

Certificate pinning is a security technique used to ensure that an application only accepts a specific certificate or set of certificates from a server. This helps prevent man-in-the-middle (MITM) attacks by ensuring that the application only communicates with servers that present a trusted certificate.

Property Description Value
certificatePinning Enables or disables certificate pinning for the application. true or false
allowedCertificates List of SHA-256 hashes of the allowed certificates. Array of strings
bypassOnDebug Allows bypassing certificate pinning in debug mode. true or false

Example: Configuring Certificate Pinning in Ionic

const config = {
  certificatePinning: true,
  allowedCertificates: [
    'a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890',
    'f0e9d8c7b6a59483726150493827160594837261504938271605948372615049'
  ],
  bypassOnDebug: true
};
Note: The certificate hashes must be SHA-256 encoded. Ensure that the certificates used in production match these hashes exactly.
Warning: Disabling certificate pinning in production environments can expose your application to security risks. Only disable it for debugging purposes.

9. Using Encrypted Storage

Storage Type Description Encryption Usage Example
Secure Storage Platform-specific secure storage for sensitive data NEW AES-256 encryption
import { SecureStoragePlugin } from '@ionic-native/secure-storage';

const storage = new SecureStoragePlugin();
storage.create('myApp').then(() => {
  storage.set('key', 'secretValue');
});
SQLite Encryption Encrypted local database using SQLCipher AES-256 with salted keys
const db = await SQLite.openDatabase({
  name: 'encrypted.db',
  location: 'default',
  key: 'mySecretKey123'
});
Keychain (iOS) Secure storage using iOS Keychain Services NEW AES-256 + hardware-backed
import { Keychain } from '@ionic-native/keychain';

Keychain.set('myKey', 'mySecretValue');
const value = await Keychain.get('myKey');

Example: Securely Storing API Tokens

import { SecureStoragePlugin } from '@ionic-native/secure-storage';

const storage = new SecureStoragePlugin();

// Store token securely
await storage.create('auth');
await storage.set('apiToken', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');

// Retrieve token
const token = await storage.get('apiToken');
console.log(token);
Note: Always use secure storage for sensitive data like tokens, passwords, or keys. Never store them in plain text or local storage.

10. Validating API Responses

Property Description Example
response.status HTTP status code returned by the API 200, 404, 500
response.body JSON or XML payload from the API
{
  "id": 123,
  "name": "Ionic App"
}
response.headers Metadata about the response Content-Type: application/json

Example: Validate API Response in Ionic

import { HttpClient } from &#x27;@angular/common/http&#x27;;

interface ApiResponse {
  id: number;
  name: string;
}

const validateResponse = (response: ApiResponse): boolean => {
  return response.id && typeof response.name === &#x27;string&#x27;;
};

this.http.get<ApiResponse>(&#x27;/api/app&#x27;).subscribe({
  next: (res) => {
    if (validateResponse(res)) {
      console.log(&#x27;Valid response received&#x27;);
    } else {
      console.error(&#x27;Invalid response format&#x27;);
    }
  },
  error: (err) => console.error(&#x27;API Error&#x27;, err)
});
Note: Always validate API responses to prevent runtime errors and ensure data integrity.
Warning: Never trust external API responses without validation, especially when used in UI rendering or business logic.

Was this article helpful?