Files
ui-essentials/projects/auth-client/README.md
Giuliano Silvestro 9b40aa3afb Add auth-client library for Elixir auth service integration
- Complete Angular client library for authentication and authorization
- JWT token management with automatic refresh and storage
- OAuth integration with social providers (Google, GitHub, etc.)
- Two-factor authentication support (TOTP and backup codes)
- Route guards for authentication and scope-based authorization
- HTTP interceptor for automatic token injection and refresh
- Comprehensive TypeScript interfaces for all API models
- User management features (profile updates, password changes)
- Cross-tab synchronization and token validation
- Complete usage guide with practical examples

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-11 14:56:59 +10:00

9.5 KiB

Auth Client Library

Angular client library for integrating with the Elixir-based auth service. Provides authentication, authorization, and user management capabilities.

Features

  • Authentication: Login, register, logout with JWT tokens
  • Token Management: Automatic token refresh and storage
  • OAuth Integration: Social authentication with multiple providers
  • Two-Factor Authentication: TOTP and backup codes support
  • Route Guards: Protect routes based on authentication and scopes
  • HTTP Interceptor: Automatic token injection and refresh
  • TypeScript Support: Fully typed interfaces and models

Installation

npm install auth-client

Setup

1. Import the HTTP Client Module

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';

@NgModule({
  imports: [
    HttpClientModule,
    // ... other imports
  ],
})
export class AppModule {}

2. Configure the Auth Service

import { AuthService } from 'auth-client';

export class AppComponent {
  constructor(private authService: AuthService) {
    // Configure the base URL for your auth service
    this.authService.configure('http://localhost:4000');
  }
}

3. Add HTTP Interceptor (Optional)

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from 'auth-client';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true
    }
  ]
})
export class AppModule {}

Usage

Authentication

Login

import { AuthService } from 'auth-client';

constructor(private authService: AuthService) {}

login() {
  this.authService.login({
    email: 'user@example.com',
    password: 'password123'
  }).subscribe({
    next: (response) => {
      console.log('Login successful:', response.user);
    },
    error: (error) => {
      console.error('Login failed:', error);
    }
  });
}

Register

register() {
  this.authService.register({
    email: 'user@example.com',
    password: 'password123',
    first_name: 'John',
    last_name: 'Doe'
  }).subscribe({
    next: (response) => {
      console.log('Registration successful:', response.user);
    },
    error: (error) => {
      console.error('Registration failed:', error);
    }
  });
}

Logout

logout() {
  this.authService.logout().subscribe({
    next: () => {
      console.log('Logout successful');
    },
    error: (error) => {
      console.error('Logout failed:', error);
    }
  });
}

Authentication State

import { AuthService } from 'auth-client';

constructor(private authService: AuthService) {
  // Subscribe to authentication state
  this.authService.isAuthenticated$.subscribe(isAuth => {
    console.log('Is authenticated:', isAuth);
  });

  // Subscribe to current user
  this.authService.currentUser$.subscribe(user => {
    console.log('Current user:', user);
  });

  // Check if authenticated synchronously
  const isAuth = this.authService.isAuthenticated();
}

Route Guards

Protect Authenticated Routes

import { AuthGuard } from 'auth-client';

const routes: Routes = [
  {
    path: 'dashboard',
    component: DashboardComponent,
    canActivate: [AuthGuard]
  },
  {
    path: 'admin',
    component: AdminComponent,
    canActivate: [AuthGuard],
    data: {
      requiredScopes: ['admin'], // Require admin scope
      requireAllScopes: true, // Must have all scopes (default: false)
      unauthorizedRedirect: '/access-denied'
    }
  }
];

Protect Guest Routes

import { GuestGuard } from 'auth-client';

const routes: Routes = [
  {
    path: 'login',
    component: LoginComponent,
    canActivate: [GuestGuard], // Redirect to home if already authenticated
    data: {
      authenticatedRedirect: '/dashboard'
    }
  }
];

OAuth Integration

Get Available Providers

import { OAuthService } from 'auth-client';

constructor(private oauthService: OAuthService) {}

getProviders() {
  this.oauthService.getProviders().subscribe(providers => {
    console.log('Available providers:', providers);
  });
}

Initiate OAuth Flow

// Redirect flow
loginWithGoogle() {
  this.oauthService.initiateOAuthFlow('google', 'http://localhost:4200/oauth/callback');
}

// Popup flow
async loginWithGooglePopup() {
  try {
    const result = await this.oauthService.initiateOAuthPopup('google');
    console.log('OAuth successful:', result);
  } catch (error) {
    console.error('OAuth failed:', error);
  }
}

Handle OAuth Callback

// In your callback component
ngOnInit() {
  this.oauthService.completeOAuthFlow('google').subscribe({
    next: (result) => {
      console.log('OAuth login successful:', result);
      this.router.navigate(['/dashboard']);
    },
    error: (error) => {
      console.error('OAuth login failed:', error);
      this.router.navigate(['/login']);
    }
  });
}

Two-Factor Authentication

Setup 2FA

setup2FA() {
  this.authService.setup2FA().subscribe({
    next: (response) => {
      // Display QR code and backup codes
      console.log('QR Code:', response.qr_code);
      console.log('Backup codes:', response.backup_codes);
    },
    error: (error) => {
      console.error('2FA setup failed:', error);
    }
  });
}

Verify 2FA Setup

verify2FA(token: string) {
  this.authService.verify2FASetup({ token }).subscribe({
    next: () => {
      console.log('2FA enabled successfully');
    },
    error: (error) => {
      console.error('2FA verification failed:', error);
    }
  });
}

User Management

Update Profile

updateProfile() {
  this.authService.updateProfile({
    first_name: 'Jane',
    last_name: 'Smith'
  }).subscribe({
    next: (user) => {
      console.log('Profile updated:', user);
    },
    error: (error) => {
      console.error('Profile update failed:', error);
    }
  });
}

Change Password

changePassword() {
  this.authService.changePassword({
    current_password: 'oldpassword',
    new_password: 'newpassword',
    new_password_confirmation: 'newpassword'
  }).subscribe({
    next: () => {
      console.log('Password changed successfully');
    },
    error: (error) => {
      console.error('Password change failed:', error);
    }
  });
}

Token Management

Manual Token Operations

import { TokenService } from 'auth-client';

constructor(private tokenService: TokenService) {}

checkToken() {
  // Check if token exists and is valid
  const isValid = this.tokenService.isTokenValid();
  
  // Get user information from token
  const userId = this.tokenService.getUserId();
  const email = this.tokenService.getUserEmail();
  const scopes = this.tokenService.getUserScopes();
  
  // Check scopes
  const hasAdminScope = this.tokenService.hasScope('admin');
  const hasAnyScope = this.tokenService.hasAnyScope(['read', 'write']);
  const hasAllScopes = this.tokenService.hasAllScopes(['read', 'write']);
}

API Reference

Models

All TypeScript interfaces are available for import:

import {
  User,
  LoginRequest,
  LoginResponse,
  RegisterRequest,
  TokenPair,
  ApiError,
  // ... and more
} from 'auth-client';

Services

  • AuthService: Main authentication service
  • TokenService: Token management and validation
  • OAuthService: OAuth provider integration
  • AuthHttpService: Low-level HTTP client

Guards

  • AuthGuard: Protect authenticated routes
  • GuestGuard: Protect guest-only routes

Interceptors

  • AuthInterceptor: Automatic token injection and refresh

Configuration

Environment Variables

You can configure the auth service URL through your environment:

// environment.ts
export const environment = {
  authServiceUrl: 'http://localhost:4000'
};

// app.component.ts
constructor(private authService: AuthService) {
  this.authService.configure(environment.authServiceUrl);
}

Token Storage

By default, tokens are stored in localStorage. The library handles:

  • Automatic token refresh before expiration
  • Cross-tab synchronization
  • Token validation and cleanup

Error Handling

All services return Observable streams with proper error handling:

this.authService.login(credentials).subscribe({
  next: (response) => {
    // Handle success
  },
  error: (apiError: ApiError) => {
    console.error('Error:', apiError.error);
    
    // Handle specific errors
    if (apiError.requires_2fa) {
      // Redirect to 2FA input
    }
    
    if (apiError.details) {
      // Handle validation errors
      console.error('Validation errors:', apiError.details);
    }
  }
});

Building

To build the library, run:

ng build auth-client

This command will compile your project, and the build artifacts will be placed in the dist/ directory.

Publishing the Library

Once the project is built, you can publish your library by following these steps:

  1. Navigate to the dist directory:

    cd dist/auth-client
    
  2. Run the npm publish command to publish your library to the npm registry:

    npm publish
    

Running unit tests

To execute unit tests with the Karma test runner, use the following command:

ng test auth-client

Contributing

This library is designed to work with the Elixir auth service. Please ensure API compatibility when making changes.

License

MIT License