Implementing Authentication with API calls

Loading

Authentication is a crucial part of web applications, ensuring that users can securely log in, log out, and access protected resources. In AngularJS, authentication is typically implemented using $http for API calls, JWT (JSON Web Tokens) for session management, and $q for handling promises.


1. Overview of Authentication Flow

The authentication process in AngularJS typically follows these steps:

  1. User Login
    • The user enters credentials (email/password).
    • A request is sent to the backend API.
    • If credentials are valid, the API returns a JWT token.
  2. Storing the Token
    • The token is stored in localStorage or sessionStorage.
    • The token is attached to subsequent requests for authentication.
  3. Protecting Routes
    • Only authenticated users can access certain routes.
    • AngularJS interceptors can be used to add the token automatically.
  4. User Logout
    • The token is removed from storage.
    • The user is redirected to the login page.

2. Creating an Authentication Service

A service (AuthService) is responsible for handling login, logout, and storing authentication tokens.

app.factory("AuthService", function($http, $q) {
var authService = {};

// Login function
authService.login = function(credentials) {
return $http.post("https://api.example.com/auth/login", credentials)
.then(function(response) {
localStorage.setItem("authToken", response.data.token);
return response.data;
})
.catch(function(error) {
return $q.reject(error);
});
};

// Logout function
authService.logout = function() {
localStorage.removeItem("authToken");
};

// Check if user is authenticated
authService.isAuthenticated = function() {
return !!localStorage.getItem("authToken");
};

return authService;
});

Stores JWT token in localStorage
Provides functions for login, logout, and authentication checks


3. Implementing Login Controller

A controller to handle the login form and call AuthService.

app.controller("LoginController", function($scope, AuthService, $location) {
$scope.credentials = { email: "", password: "" };
$scope.loginError = "";

$scope.login = function() {
AuthService.login($scope.credentials).then(function(response) {
$location.path("/dashboard"); // Redirect to dashboard on success
}).catch(function(error) {
$scope.loginError = "Invalid credentials. Please try again.";
});
};
});

🔹 Captures user credentials
🔹 Calls AuthService.login()
🔹 Redirects on success, shows an error on failure


4. Attaching Token to API Requests

To ensure that authenticated requests include the JWT token, we use an HTTP interceptor.

app.factory("AuthInterceptor", function($q) {
return {
request: function(config) {
var token = localStorage.getItem("authToken");
if (token) {
config.headers.Authorization = "Bearer " + token;
}
return config;
},
responseError: function(response) {
if (response.status === 401) {
localStorage.removeItem("authToken");
window.location = "#/login"; // Redirect to login on unauthorized access
}
return $q.reject(response);
}
};
});

// Register the interceptor
app.config(function($httpProvider) {
$httpProvider.interceptors.push("AuthInterceptor");
});

🔹 Adds JWT to headers on every API request
🔹 Redirects users if they receive a 401 Unauthorized response


5. Protecting Routes with Authentication

To restrict access to certain routes, use $routeProvider and check AuthService.isAuthenticated().

app.run(function($rootScope, $location, AuthService) {
$rootScope.$on("$routeChangeStart", function(event, next) {
if (next.requiresAuth && !AuthService.isAuthenticated()) {
$location.path("/login"); // Redirect to login if not authenticated
}
});
});

app.config(function($routeProvider) {
$routeProvider
.when("/dashboard", {
templateUrl: "dashboard.html",
controller: "DashboardController",
requiresAuth: true // Custom property to check authentication
})
.when("/login", {
templateUrl: "login.html",
controller: "LoginController"
})
.otherwise({
redirectTo: "/login"
});
});

🔹 Prevents unauthenticated users from accessing protected pages
🔹 Redirects to login page if authentication fails


6. Implementing Logout

To allow users to log out, call AuthService.logout() and redirect to the login page.

app.controller("DashboardController", function($scope, AuthService, $location) {
$scope.logout = function() {
AuthService.logout();
$location.path("/login");
};
});

🔹 Clears stored token
🔹 Redirects user to the login page


7. Displaying Authenticated User Information

After successful login, user details can be fetched using the stored token.

app.controller("ProfileController", function($scope, $http) {
$http.get("https://api.example.com/user/profile")
.then(function(response) {
$scope.user = response.data;
})
.catch(function(error) {
console.error("Error fetching profile:", error);
});
});

🔹 Calls authenticated API to fetch user details
🔹 Requires token in headers (handled by interceptor)


8. Refreshing Token Automatically

Some APIs provide a refresh token mechanism. This ensures the user remains authenticated without logging in again.

app.factory("AuthInterceptor", function($q, $http) {
return {
responseError: function(response) {
if (response.status === 401) {
var refreshToken = localStorage.getItem("refreshToken");
if (refreshToken) {
return $http.post("https://api.example.com/auth/refresh", { token: refreshToken })
.then(function(newTokenResponse) {
localStorage.setItem("authToken", newTokenResponse.data.token);
response.config.headers.Authorization = "Bearer " + newTokenResponse.data.token;
return $http(response.config); // Retry original request
});
}
}
return $q.reject(response);
}
};
});

🔹 Tries to refresh JWT if expired
🔹 Retries the failed request with a new token

Leave a Reply

Your email address will not be published. Required fields are marked *