Skip to main content

Overview

AuthService is an Angular service that implements the UsuarioRepository interface to provide HTTP-based authentication functionality. It handles user login and registration operations by communicating with the backend REST API using Angular’s HttpClient. Location: src/app/usuario/infrastructure/services/auth-service.ts

Complete Implementation

import { HttpClient } from '@angular/common/core';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Usuario } from '../../domain/models/usuario';
import { UsuarioRepository } from '../../domain/repositories/usuario.repository';

@Injectable({
  providedIn: 'root',
})
export class AuthService implements UsuarioRepository {

  private readonly BASE_URL = 'http://localhost:8080/'
  constructor(private httpClient: HttpClient) { }

  loginUsuario(usuario: string, contrasena: string): Observable<Usuario> {
    return this.httpClient.get<Usuario>(this.BASE_URL + 'login' + '/' + usuario + '/' + contrasena);
  } 
  registrarUsuario(usuario: string, contrasena: string): Observable<Usuario> {
    const body = { usuario, contrasena };
    return this.httpClient.post<Usuario>(
      `${this.BASE_URL}registro`,
      body,
      { headers: { 'Content-Type': 'application/json' } }
    );
  }
}

Configuration

BASE_URL

BASE_URL
string
default:"http://localhost:8080/"
The base URL for all authentication API endpoints. This is a private readonly property that points to the backend server.

Dependency Injection

The service is provided at the root level (providedIn: 'root'), making it a singleton available throughout the application.

Constructor Dependencies

httpClient
HttpClient
required
Angular’s HTTP client for making HTTP requests. Automatically injected by Angular’s DI system.

Methods

loginUsuario()

Authenticates a user by sending credentials to the backend API via GET request. Signature:
loginUsuario(usuario: string, contrasena: string): Observable<Usuario>
Parameters:
usuario
string
required
The username to authenticate
contrasena
string
required
The user’s password
HTTP Request:
  • Method: GET
  • Endpoint: /login/:usuario/:contrasena
  • Full URL: http://localhost:8080/login/{usuario}/{contrasena}
Returns:
Observable<Usuario>
Observable
An RxJS Observable that emits a Usuario object on successful authentication
Response Structure:
id
number
The unique identifier of the authenticated user
usuario
string
The username of the authenticated user
contrasena
string
The user’s password (note: typically passwords should not be returned)
Example Usage:
import { Component } from '@angular/core';
import { UsuarioRepository } from '../../domain/repositories/usuario.repository';
import { tap } from 'rxjs';

@Component({
  selector: 'app-login-page',
  templateUrl: './login-page.html',
})
export class LoginPage {
  constructor(private authService: UsuarioRepository) {}

  login(usuario: string, contrasena: string) {
    this.authService.loginUsuario(usuario, contrasena).pipe(
      tap(usuario => {
        console.log(usuario);
        usuario 
          ? alert('usuario y contraseña correctos!') 
          : alert('usuario o contraseña incorrectos');       
      })
    ).subscribe();
  }
}

registrarUsuario()

Registers a new user by sending credentials to the backend API via POST request. Signature:
registrarUsuario(usuario: string, contrasena: string): Observable<Usuario>
Parameters:
usuario
string
required
The desired username for the new account
contrasena
string
required
The desired password for the new account
HTTP Request:
  • Method: POST
  • Endpoint: /registro
  • Full URL: http://localhost:8080/registro
  • Headers:
    • Content-Type: application/json
Request Body:
{
  "usuario": "string",
  "contrasena": "string"
}
Returns:
Observable<Usuario>
Observable
An RxJS Observable that emits a Usuario object representing the newly created user
Response Structure:
id
number
The unique identifier assigned to the new user
usuario
string
The username of the newly registered user
contrasena
string
The user’s password (note: typically passwords should not be returned)
Example Usage:
import { Component } from '@angular/core';
import { AuthService } from '../../../services/auth-service';
import { catchError, tap, throwError } from 'rxjs';

@Component({
  selector: 'app-register-page',
  templateUrl: './register-page.html',
})
export class RegisterPage {
  constructor(private authService: AuthService) { }

  registrar(usuario: string, contrasena: string) {
    this.authService.registrarUsuario(usuario, contrasena).pipe(
      tap(usuario => {
        console.log('usuario', usuario);
        usuario 
          ? alert('usuario registrado correctamente') 
          : alert(usuario);
      }), 
      catchError(err => {
        const mensaje = err.error ? err.error : 'Error desconocido';
        alert(`Error al registrar: ${mensaje}`);
        return throwError(() => err);
      })
    ).subscribe();
  }
}

Architecture Integration

Implements UsuarioRepository

AuthService implements the abstract UsuarioRepository class defined in the domain layer, following the repository pattern and clean architecture principles:
export abstract class UsuarioRepository {
    abstract loginUsuario(usuario: string, contrasena: string): Observable<Usuario>;
    abstract registrarUsuario(usuario: string, contrasena: string): Observable<Usuario>;
}
Location: src/app/usuario/domain/repositories/usuario.repository.ts This allows the service to be injected using the abstract repository type, enabling dependency inversion and easier testing.

Usuario Model

Both methods work with the Usuario interface:
export interface Usuario {
    id: number,
    usuario: string,
    contrasena: string
}
Location: src/app/usuario/domain/models/usuario.ts

Observable Patterns

RxJS Integration

The service uses RxJS Observable as the return type for all methods, enabling:
  • Lazy execution: HTTP requests are not made until .subscribe() is called
  • Cancellation: Unsubscribing cancels pending HTTP requests
  • Operator chaining: Use operators like tap, map, catchError for reactive programming
  • Error handling: HTTP errors are propagated through the Observable stream

Common Patterns

Error Handling:
this.authService.registrarUsuario(usuario, contrasena).pipe(
  catchError(err => {
    console.error('Registration failed:', err);
    return throwError(() => err);
  })
).subscribe();
Side Effects with tap:
this.authService.loginUsuario(usuario, contrasena).pipe(
  tap(user => console.log('Logged in user:', user))
).subscribe();
Transformation:
this.authService.loginUsuario(usuario, contrasena).pipe(
  map(user => user.usuario)
).subscribe(username => console.log(username));

Security Considerations

The current implementation passes credentials in the URL path for the login endpoint (GET request). This is not recommended for production as:
  • Credentials appear in server logs
  • Credentials are visible in browser history
  • URLs may be cached by proxies
Consider using POST requests with body payloads for both login and registration.
The API returns user passwords in the response. In production applications, passwords should never be returned to the client, even after successful authentication. Consider returning only non-sensitive user data or authentication tokens.

Build docs developers (and LLMs) love