← Back to Frontend System Design Blogs

Auth Module – Low Level Design

2025-06-21📖 4 min read

Share:

🔐 Step 4: Auth Module – Low Level Design (LLD)

This document outlines the low-level implementation details of the auth feature module in the Angular e-commerce frontend.


📦 Module Structure

src/
├── app/
│   ├── core/
│   │   ├── guards/
│   │   │   └── auth.guard.ts
│   │   └── interceptors/
│   └── features/
│       └── auth/
│           ├── components/
│           │   ├── login/
│           │   │   ├── login.component.ts
│           │   │   └── login.component.html
│           │   └── register/
│           │       ├── register.component.ts
│           │       └── register.component.html
│           ├── services/
│           │   └── auth.service.ts
│           ├── store/
│           │   ├── auth.actions.ts
│           │   ├── auth.reducer.ts
│           │   ├── auth.effects.ts
│           │   └── auth.selectors.ts
│           ├── models/
│           │   └── auth.model.ts
│           ├── auth-routing.module.ts
│           └── auth.module.ts

🧱 Component Breakdown

🔐 LoginComponent

  • Reactive form with email, password
  • Dispatches login() via store or service
  • Shows error messages & loading indicator

📝 RegisterComponent

  • Reactive form: email, password, confirmPassword
  • Client-side validations (pattern, match)
  • Submits to authService.register()

🧪 Service: AuthService

Responsible for actual API calls and token handling.

@Injectable({ providedIn: "root" })
export class AuthService {
  constructor(private store: Store) {}

  login(credentials: LoginRequest): void {
    this.store.dispatch(AuthActions.login({ credentials }));
  }

  register(data: RegisterRequest): void {
    this.store.dispatch(AuthActions.register({ data }));
  }

  logout(): void {
    this.store.dispatch(AuthActions.logout());
  }

  user$(): Observable<User | null> {
    return this.store.select(selectUser);
  }

  error$(): Observable<string | null> {
    return this.store.select(selectAuthError);
  }

  isLoggedIn$(): Observable<boolean> {
    return this.store.select(selectIsAuthenticated);
  }
}

🧩 NgRx Store (optional but scalable)

✅ Actions – auth.actions.ts

export const login = createAction(
  "[Auth] Login",
  props<{ credentials: LoginRequest }>()
);
export const loginSuccess = createAction(
  "[Auth] Login Success",
  props<{ user: User; token: string }>()
);
export const loginFailure = createAction(
  "[Auth] Login Failure",
  props<{ error: any }>()
);

🔁 Reducer – auth.reducer.ts

Handles login, loginSuccess, loginFailure to update state.

🌐 Effects – auth.effects.ts

Handles side-effects like API calls.

login$ = createEffect(() =>
  this.actions$.pipe(
    ofType(AuthActions.login),
    exhaustMap(({ credentials }) =>
      this.authService.login(credentials).pipe(
        map((res) =>
          AuthActions.loginSuccess({ user: res.user, token: res.token })
        ),
        catchError((error) => of(AuthActions.loginFailure({ error })))
      )
    )
  )
);

🔍 Selectors – auth.selectors.ts

export const selectAuthState = createFeatureSelector<AuthState>("auth");
export const selectUser = createSelector(
  selectAuthState,
  (state) => state.user
);
export const selectIsAuthenticated = createSelector(
  selectAuthState,
  (state) => !!state.token
);

🔐 Auth Guard (in Core)

// src/app/core/guards/auth.guard.ts
@Injectable({ providedIn: "root" })
export class AuthGuard implements CanActivate {
  constructor(private auth: AuthService, private router: Router) {}

  canActivate(): boolean {
    if (!this.auth.isLoggedIn()) {
      this.router.navigate(["/login"]);
      return false;
    }
    return true;
  }
}

🧱 Models

// auth.model.ts
export interface LoginRequest {
  email: string;
  password: string;
}

export interface LoginResponse {
  user: User;
  token: string;
}

🔄 API Contracts

Endpoint Method Request Payload Response
/auth/login POST { email, password } { user, token }
/auth/register POST { email, password } { message: string }

🔧 Validation Rules

Field Rules
email Required, Valid email format
password Required, Min 6 chars, 1 special char
confirmPassword Must match password

🚀 Navigation & Routing

const routes: Routes = [
  { path: "login", component: LoginComponent },
  { path: "register", component: RegisterComponent },
];

🛡️ Security Notes

  • Token is stored in localStorage
  • HTTP Interceptor (in core/interceptors) appends Authorization header
  • AuthGuard protects private routes like /checkout, /orders
  • Logout removes token from local storage

📐 Component Interaction Diagram

LoginComponent
 └── dispatches → authService.login()
     └── API → /auth/login
         └── on success → store.dispatch(loginSuccess)
RegisterComponent
 └── calls → authService.register()
     └── API → /auth/register
AuthGuard (core)
 └── uses → authService.isLoggedIn()

✅ Responsibilities Summary

Part Responsibility
LoginComponent Form UI, triggers login
AuthService API interaction, token management
Store (optional) State handling, side effects (NgRx)
AuthGuard (core) Protects routes like /checkout, /orders
Models Type-safe payload structures