Building an Angular Authentication Service: Login and Logout Methods

Chandan Kumar
3 min readJul 17, 2024

--

Creating a robust authentication system is crucial for any web application. In Angular, services provide a convenient way to encapsulate and manage authentication logic. This blog post will guide you through building an Angular authentication service with login and logout methods using the Angular framework.

Setting Up the Angular Service.

First, let’s create the authentication service. This service will handle user registration, login, logout, and session management.

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router';
import { Observable, of } from 'rxjs';
import { tap } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { Auth, User } from '../model/auth';
import { LocalstorageService } from './localstorage.service';

@Injectable({
providedIn: 'root'
})
export class AuthService {
public avail: boolean = false;
public msg: string = "";

private isAuthenticated = false;
private redirectUrl: string | null = null;
private authToken: string | null = null;
private siteKey = '';
private secretKey = '';

private readonly TOKEN_KEY = 'token_Data';
private readonly USER_DATA_KEY = 'USER_Data';
private readonly SESSION_EXPIRY_KEY = 'sessionExpiryData';
private readonly SESSION_DURATION = 5 * 24 * 60 * 60 * 1000;

apiURLUserRegister = environment.apiUrl + 'users_file/user-registration';
apiURLUsers = environment.apiUrl + 'users_file';
apiURLGoogleLogin = environment.apiUrl + 'GoogleLogin';
apiURLLinkedinLogin = environment.apiUrl + 'LinkedinLogin';

constructor(
private http: HttpClient,
private token: LocalstorageService,
private router: Router
) {}

// User registration methods
createUser(user: User): Observable<User> {
return this.http.post<User>(this.apiURLUserRegister, user);
}

Implementing Login Methods

The login methods authenticate users using various strategies such as email/password, Google, LinkedIn, and Facebook.

  // Login methods
loginUser(email: string, password: string): Observable<Auth> {
return this.http.post<Auth>(`${this.apiURLUsers}/login`, { email, password })
.pipe(
tap(user => {
if (user.token) {
this.setUserSession(user);
}
})
);
}

googleLogin(token: string): Observable<Auth> {
return this.http.post<Auth>(`${this.apiURLGoogleLogin}/google-login`, { token })
.pipe(
tap(user => {
if (user.token) {
this.setUserSession(user);
}
})
);
}

initiateLinkedInLogin(): void {
window.location.href = `${this.apiURLLinkedinLogin}/auth/linkedin`;
}

linkedinLogin(code: string): Observable<Auth> {
return this.http.get<Auth>(`${this.apiURLLinkedinLogin}/auth/linkedin/callback?code=${code}`)
.pipe(
tap(user => {
if (user.token) {
this.setUserSession(user);
}
})
);
}

loginWithFacebook(accessToken: string, userID: string): Observable<any> {
const url = `${this.apiURLUsers}/facebook-login`;
const body = { accessToken, userID };
return this.http.post(url, body);
}

Session Management Methods

To manage the user session, we’ll implement methods to set, get, and remove session data.

  // Session management methods
private setUserSession(user: Auth): void {
if (user.token) {
const data = {
name: user.name,
email: user.email,
token: user.token,
userId: user.userId,
};
this.authToken = user.token;
this.setStorageItem(this.TOKEN_KEY, user.token);
this.setStorageItem(this.USER_DATA_KEY, JSON.stringify(data));
this.setSessionExpiry();
this.isAuthenticated = true;

if (user.role === undefined) {
const redirectUrl = this.getRedirectUrl();
this.setRedirectUrl(redirectUrl || '/user');
}
} else {
console.error('User token is undefined');
this.isAuthenticated = false;
}
}

private setStorageItem(key: string, value: string): void {
localStorage.setItem(key, value);
sessionStorage.setItem(key, value);
}

private removeStorageItem(key: string): void {
localStorage.removeItem(key);
sessionStorage.removeItem(key);
}

private setSessionExpiry(): void {
const expiryTime = new Date().getTime() + this.SESSION_DURATION;
sessionStorage.setItem(this.SESSION_EXPIRY_KEY, expiryTime.toString());
}

private checkSessionExpiry(): void {
const expiryTime = sessionStorage.getItem(this.SESSION_EXPIRY_KEY);
if (expiryTime) {
const currentTime = new Date().getTime();
if (currentTime >= +expiryTime) {
this.logout();
}
}
}

isLoggedIn(): boolean {
this.checkSessionExpiry();
this.authToken = this.getToken();
return !!this.authToken;
}

getToken(): string | null {
return sessionStorage.getItem(this.TOKEN_KEY) || localStorage.getItem(this.TOKEN_KEY);
}

logout(): void {
this.removeStorageItem(this.TOKEN_KEY);
this.removeStorageItem(this.USER_DATA_KEY);
sessionStorage.removeItem(this.SESSION_EXPIRY_KEY);
this.clearSessionStorage();
this.isAuthenticated = false;
this.authToken = null;
this.router.navigate(['/login']);
}

private clearSessionStorage(): void {
sessionStorage.clear();
}

Password Management and Verification Methods

Additionally, the service includes methods for password management and account verification.

  // Password management methods
forgotInstructorPassword(email: string): Observable<any> {
return this.http.post(`${this.apiURLUsers}/forgot-password`, { email });
}

resetUserPassword(token: string, newPassword: string): Observable<any> {
return this.http.post(`${this.apiURLUsers}/reset-password/${token}`, { newPassword });
}

requestPasswordReset(email: string): Observable<any> {
return this.http.post(`${this.apiURLUsers}/forgot-password`, { email });
}

// Verification methods
verify(token: string): Observable<User> {
return this.http.get(`${this.apiURLUsers}/verify/${token}`);
}

verifyHcaptcha(response: string): Observable<any> {
const requestBody = { secret: this.secretKey, response };
return this.http.post(`${this.apiURLUsers}/verify-hcaptcha`, requestBody);
}

getSiteKey(): string {
return this.siteKey;
}

// Redirect URL methods
setRedirectUrl(url: string): void {
this.redirectUrl = url;
}

getRedirectUrl(): string | null {
const url = this.redirectUrl;
this.redirectUrl = null;
return url;
}
}

Conclusion

By encapsulating authentication logic within a service, we ensure that our application remains modular and maintainable. This service provides a solid foundation for handling user authentication, session management, and password management in an Angular application. With these methods, you can build a secure and user-friendly authentication system for your Angular projects.

--

--

Chandan Kumar
Chandan Kumar

Written by Chandan Kumar

Software Engineer | CS-Engineering Graduate | Mean Stack Developer | @Jobluu https://www.linkedin.com/in/developerchandan/

Responses (2)