AngularJS is a powerful JavaScript framework for building dynamic web applications. However, like any web technology, it comes with security risks. Since AngularJS is client-side, attackers can exploit vulnerabilities if security best practices are not followed. Below is a step-by-step guide on how to secure AngularJS applications effectively.
1. Understanding Security Risks in AngularJS
Before securing an AngularJS application, it is crucial to understand the primary security threats:
- Cross-Site Scripting (XSS): Malicious scripts injected into web pages that execute in the user’s browser.
- Cross-Site Request Forgery (CSRF): Unauthorized commands executed on behalf of an authenticated user.
- Injection Attacks: Code injections like SQL, NoSQL, and command injections.
- Unvalidated Inputs: Accepting user input without proper sanitization.
- Exposing Sensitive Data: Storing secrets like API keys in the frontend.
Now, let’s go through best practices to mitigate these threats.
2. Enable Strict Contextual Escaping (SCE)
AngularJS provides Strict Contextual Escaping (SCE) to prevent Cross-Site Scripting (XSS) attacks. This feature ensures that HTML, URLs, and JavaScript are sanitized before rendering.
How to Implement SCE
By default, AngularJS enables SCE. However, developers sometimes disable it for convenience, which creates security loopholes. Ensure that you never disable SCE globally.
var app = angular.module('myApp', []);
app.config(function($sceProvider) {
$sceProvider.enabled(true); // Ensures SCE is enabled
});
Best Practice
- Always use $sce.trustAs methods carefully when whitelisting content.
- Avoid using $sce.trustAsHtml unless absolutely necessary.
3. Prevent Cross-Site Scripting (XSS) Attacks
XSS attacks happen when user input is not properly sanitized. To mitigate XSS:
A. Use AngularJS Binding Instead of innerHTML
Never use innerHTML or document.write()
to inject dynamic content.
Secure Code (Using AngularJS Binding)
<p>{{ userComment }}</p>
Insecure Code (Using innerHTML
)
<p ng-bind-html="userComment"></p> <!-- Risky if not sanitized -->
B. Sanitize User Input
Use $sanitize service to clean user inputs.
var app = angular.module('myApp', ['ngSanitize']);
app.controller('MainCtrl', function($scope, $sanitize) {
$scope.userInput = $sanitize("<script>alert('XSS')</script>"); // Script will be removed
});
C. Avoid Using ng-bind-html
Unnecessarily
If using ng-bind-html
, ensure that content is sanitized.
<div ng-bind-html="trustedHtml"></div>
$scope.trustedHtml = $sce.trustAsHtml(sanitizedContent);
4. Protect Against Cross-Site Request Forgery (CSRF/XSRF)
CSRF attacks trick authenticated users into submitting unauthorized requests. AngularJS provides built-in protection via XSRF tokens.
How CSRF Protection Works in AngularJS
AngularJS expects an XSRF-TOKEN
from the server, which is automatically sent in every AJAX request.
A. Configure CSRF Tokens in the Backend
The backend should generate a CSRF token and set it as a cookie.
// Example for Node.js/Express
app.use(require('csurf')({ cookie: true }));
B. Ensure AngularJS Includes the CSRF Token Automatically
AngularJS looks for the token in cookies and sends it in headers.
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'XSRF-TOKEN';
$httpProvider.defaults.xsrfHeaderName = 'X-XSRF-TOKEN';
}]);
Best Practices
- Never disable CSRF protection.
- Ensure tokens are regenerated after login/logout.
5. Avoid Using eval()
and Function()
Using eval()
and Function()
exposes the application to code injection attacks.
Insecure Code
var userCode = "alert('Hacked!')";
eval(userCode); // Dangerous
Secure Alternative Use JSON.parse()
instead of eval()
when dealing with JSON data.
var data = JSON.parse(userInput); // Safe alternative
6. Use Content Security Policy (CSP)
CSP prevents unauthorized scripts from executing in your AngularJS application.
A. Configure CSP in the Server Response Header
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
B. Avoid Inline Scripts
Instead of using inline scripts:
<script>alert('Hello');</script> <!-- Insecure -->
Use external JavaScript files:
<script src="secure.js"></script> <!-- Secure -->
7. Secure API Communication
A. Use HTTPS
Always enforce HTTPS to prevent Man-in-the-Middle (MITM) attacks.
B. Use Token-Based Authentication
Instead of storing session-based authentication in cookies, use JWT tokens.
$http.defaults.headers.common.Authorization = 'Bearer ' + token;
C. Restrict CORS
Ensure only trusted domains can make requests.
app.use(cors({ origin: 'https://trusted-website.com' }));
8. Implement Role-Based Access Control (RBAC)
Restrict access based on user roles.
A. Create an Authorization Service
app.factory('AuthService', function() {
return {
isAuthorized: function(role) {
return userRoles.includes(role);
}
};
});
B. Restrict Routes Based on Roles
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/admin', {
templateUrl: 'admin.html',
resolve: {
auth: function(AuthService) {
if (!AuthService.isAuthorized('admin')) {
window.location = '/unauthorized';
}
}
}
});
}]);
9. Remove Debugging Tools in Production
Disable AngularJS debugging features before deploying.
app.config(['$compileProvider', function($compileProvider) {
$compileProvider.debugInfoEnabled(false);
}]);
10. Keep AngularJS and Dependencies Updated
Use the latest secure versions of AngularJS and third-party libraries.
A. Update Dependencies Regularly
Check for security updates:
npm audit
B. Monitor Security Vulnerabilities
Use tools like Snyk or OWASP Dependency Check.