State-based authentication ensures that users can only access specific parts of an application based on their authentication status. This is crucial for securing AngularJS applications.
1. Understanding State-Based Authentication
In an AngularJS single-page application (SPA), authentication typically involves:
Storing user session data (using $rootScope
, localStorage
, or a service).
Restricting routes based on authentication status.
Redirecting users to login if they are not authenticated.
Example Workflow
- User logs in → Credentials are verified via an API → Token is stored.
- User navigates to a protected route → App checks if user is authenticated.
- If authenticated → User accesses the route.
- If not authenticated → Redirected to the login page.
- User logs out → Session is cleared, and access is revoked.
2. Setting Up Authentication Service
A centralized service manages authentication, login, logout, and state checking.
Create AuthService
for Authentication Management
app.factory('AuthService', function($http, $window) {
var auth = {
isAuthenticated: false,
user: null,
login: function(credentials) {
return $http.post('/api/login', credentials).then(function(response) {
auth.isAuthenticated = true;
auth.user = response.data.user;
$window.localStorage.setItem('authToken', response.data.token);
return response.data.user;
});
},
logout: function() {
auth.isAuthenticated = false;
auth.user = null;
$window.localStorage.removeItem('authToken');
},
isLoggedIn: function() {
return !!$window.localStorage.getItem('authToken');
}
};
return auth;
});
What happens?
- On login, the authentication token is saved in
localStorage
. - On logout, user data is cleared.
isLoggedIn()
checks if the user is authenticated.
3. Implementing Authentication in Controllers
Login Controller (LoginController
)
app.controller('LoginController', function($scope, AuthService, $location) {
$scope.credentials = { username: '', password: '' };
$scope.errorMessage = '';
$scope.login = function() {
AuthService.login($scope.credentials).then(function(user) {
$location.path('/dashboard'); // Redirect on success
}).catch(function() {
$scope.errorMessage = 'Invalid login credentials';
});
};
});
What happens?
- User submits credentials →
AuthService.login()
is called. - If successful → Redirects to
/dashboard
. - If failed → Shows error message.
4. Protecting Routes with Authentication
Restricting Access Using $routeChangeStart
To protect routes, use $routeChangeStart
in the main application module.
app.run(function($rootScope, $location, AuthService) {
$rootScope.$on('$routeChangeStart', function(event, next) {
if (next.requiresAuth && !AuthService.isLoggedIn()) {
event.preventDefault();
$location.path('/login'); // Redirect to login page
}
});
});
What happens?
- Before changing routes, it checks if the user is authenticated.
- If not authenticated → Redirects to
/login
.
Defining Routes with Authentication Checks
Modify the AngularJS routing to protect specific pages.
app.config(function($routeProvider) {
$routeProvider
.when('/login', {
templateUrl: 'views/login.html',
controller: 'LoginController'
})
.when('/dashboard', {
templateUrl: 'views/dashboard.html',
controller: 'DashboardController',
requiresAuth: true
})
.when('/profile', {
templateUrl: 'views/profile.html',
controller: 'ProfileController',
requiresAuth: true
})
.otherwise({
redirectTo: '/login'
});
});
What happens?
requiresAuth: true
ensures that protected routes require authentication.- If a user is not logged in, they are redirected to
/login
.
5. Showing/Hiding UI Elements Based on Authentication
Use ng-show
or ng-if
to show/hide elements dynamically based on authentication state.
Example: Displaying Logout Button if Logged In
<div ng-if="AuthService.isLoggedIn()">
<button ng-click="logout()">Logout</button>
</div>
Example: Showing Different Navbar Links Based on Authentication
<nav>
<ul>
<li><a href="#/home">Home</a></li>
<li ng-if="!AuthService.isLoggedIn()"><a href="#/login">Login</a></li>
<li ng-if="AuthService.isLoggedIn()"><a href="#/dashboard">Dashboard</a></li>
<li ng-if="AuthService.isLoggedIn()"><a href="" ng-click="logout()">Logout</a></li>
</ul>
</nav>
What happens?
- If the user is not logged in, only “Home” and “Login” links appear.
- If the user is logged in, “Dashboard” and “Logout” appear.
6. Implementing Logout Functionality
Logout Function
app.controller('LogoutController', function($scope, AuthService, $location) {
$scope.logout = function() {
AuthService.logout();
$location.path('/login'); // Redirect to login
};
});
What happens?
- Calls
AuthService.logout()
to clear the session. - Redirects the user to
/login
.
7. Persisting Authentication State After Page Refresh
Even if the user refreshes the page, they should remain logged in.
Checking Authentication on App Load
Modify AuthService
to check localStorage
on app load:
app.run(function(AuthService) {
if (AuthService.isLoggedIn()) {
AuthService.isAuthenticated = true;
}
});
What happens?
- Ensures that authentication state is preserved across page reloads.
8. Securing API Calls with Authentication Token
When making API requests, send the authentication token in headers.
Example: Attaching Token to API Requests
app.factory('AuthInterceptor', function($window) {
return {
request: function(config) {
var token = $window.localStorage.getItem('authToken');
if (token) {
config.headers.Authorization = 'Bearer ' + token;
}
return config;
}
};
});
app.config(function($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
});
What happens?
- Before sending an API request, AngularJS adds the token in headers.
- The backend validates the token before processing the request.