Authentication is a crucial aspect of any web application. In AngularJS, routing and authentication go hand in hand to ensure that only authorized users can access certain views or states. Handling authentication properly in AngularJS routes involves checking if a user is logged in, redirecting them if necessary, and ensuring secure access to different parts of your application.
In this guide, we will walk through the process of implementing authentication in AngularJS routes using UI Router and Route Guards.
Step 1: Setting Up AngularJS and UI Router
First, ensure that you have both AngularJS and UI Router set up in your project. Here’s a basic structure:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AngularJS Authentication</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.4.2/angular-ui-router.min.js"></script>
</head>
<body ng-app="authApp">
<div>
<a ui-sref="login">Login</a> |
<a ui-sref="dashboard">Dashboard</a> |
<a ui-sref="profile">Profile</a>
</div>
<div ui-view></div> <!-- UI View for the content -->
<script src="app.js"></script>
</body>
</html>
Step 2: Create the AngularJS Module and Configure Routes
In your app.js
file, define the AngularJS module and configure the routes. Each state can represent a view, such as the login page, dashboard, or profile page. You will implement guards that check if the user is authenticated before navigating to sensitive routes.
var app = angular.module('authApp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
// Default route if the URL doesn't match any state
$urlRouterProvider.otherwise('/login');
// Define states (pages/views)
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'login.html',
controller: 'LoginController'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: 'dashboard.html',
controller: 'DashboardController',
resolve: {
auth: function(AuthService) {
return AuthService.isAuthenticated(); // Route guard
}
}
})
.state('profile', {
url: '/profile',
templateUrl: 'profile.html',
controller: 'ProfileController',
resolve: {
auth: function(AuthService) {
return AuthService.isAuthenticated(); // Route guard
}
}
});
});
- Login State: The login page where the user enters credentials.
- Dashboard and Profile States: These are protected states that require authentication.
The resolve
property ensures that before loading the dashboard
or profile
state, the authentication service is checked to confirm that the user is authenticated.
Step 3: Create the Authentication Service
The authentication service is responsible for handling the user’s login status and ensuring that only authenticated users can access restricted routes. Here’s a simple AuthService
:
app.service('AuthService', function($q, $state) {
var userAuthenticated = false; // Simulated authentication status
this.login = function(username, password) {
// In a real app, authentication logic (e.g., API calls) goes here
if (username === 'admin' && password === 'password') {
userAuthenticated = true;
return true;
} else {
return false;
}
};
this.logout = function() {
userAuthenticated = false;
$state.go('login');
};
this.isAuthenticated = function() {
var deferred = $q.defer();
if (userAuthenticated) {
deferred.resolve();
} else {
deferred.reject();
$state.go('login'); // Redirect to login if not authenticated
}
return deferred.promise;
};
});
login
: Checks if the user credentials are correct and sets theuserAuthenticated
flag.logout
: Logs the user out and redirects to the login page.isAuthenticated
: Checks the authentication status and uses$q.defer()
to either resolve or reject the promise. If rejected, the user is redirected to the login page.
Step 4: Create the Controllers
Each state will have its own controller to manage the page content. For example:
app.controller('LoginController', function($scope, AuthService, $state) {
$scope.login = function(username, password) {
var success = AuthService.login(username, password);
if (success) {
$state.go('dashboard'); // Redirect to dashboard after successful login
} else {
$scope.errorMessage = "Invalid username or password";
}
};
});
app.controller('DashboardController', function($scope) {
$scope.message = "Welcome to the Dashboard!";
});
app.controller('ProfileController', function($scope) {
$scope.message = "Welcome to your profile!";
});
- LoginController: Handles user login. If the login is successful, the user is redirected to the dashboard.
- DashboardController and ProfileController: Display the content for those views. They are protected and require authentication.
Step 5: Create the HTML Templates
Create the HTML templates for the login, dashboard, and profile pages.
- login.html
<div>
<h1>Login</h1>
<form ng-submit="login(username, password)">
<label>Username:</label>
<input type="text" ng-model="username" required><br>
<label>Password:</label>
<input type="password" ng-model="password" required><br>
<button type="submit">Login</button>
</form>
<p>{{ errorMessage }}</p>
</div>
- dashboard.html
<div>
<h1>Dashboard</h1>
<p>{{ message }}</p>
<button ng-click="logout()">Logout</button>
</div>
- profile.html
<div>
<h1>Profile</h1>
<p>{{ message }}</p>
<button ng-click="logout()">Logout</button>
</div>
- The login page lets users enter credentials.
- The dashboard and profile pages show a welcome message and allow the user to log out.
Step 6: Handle Logout
To log the user out, add a logout button to the dashboard.html and profile.html templates, which calls the logout
method from the AuthService
:
$scope.logout = function() {
AuthService.logout();
};
This will log the user out and redirect them to the login page.
Step 7: Final Considerations
- State Guards: Use the
resolve
property in the state configuration to check authentication before accessing the state. If the user is not authenticated, they will be redirected to the login page. - Global Authentication Check: For more complex applications, you may want to add global authentication checks across your app using
$stateChangeStart
events. This ensures that any route transition is checked for authentication.
app.run(function($rootScope, $state, AuthService) {
$rootScope.$on('$stateChangeStart', function(event, toState) {
if (toState.resolve && toState.resolve.auth) {
AuthService.isAuthenticated().catch(function() {
$state.go('login');
});
}
});
});
This code ensures that every state change is checked for authentication.