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

469 lines
9.5 KiB
Markdown

# 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
```bash
npm install auth-client
```
## Setup
### 1. Import the HTTP Client Module
```typescript
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
@NgModule({
imports: [
HttpClientModule,
// ... other imports
],
})
export class AppModule {}
```
### 2. Configure the Auth Service
```typescript
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)
```typescript
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
```typescript
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
```typescript
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
```typescript
logout() {
this.authService.logout().subscribe({
next: () => {
console.log('Logout successful');
},
error: (error) => {
console.error('Logout failed:', error);
}
});
}
```
### Authentication State
```typescript
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
```typescript
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
```typescript
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
```typescript
import { OAuthService } from 'auth-client';
constructor(private oauthService: OAuthService) {}
getProviders() {
this.oauthService.getProviders().subscribe(providers => {
console.log('Available providers:', providers);
});
}
```
#### Initiate OAuth Flow
```typescript
// 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
```typescript
// 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
```typescript
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
```typescript
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
```typescript
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
```typescript
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
```typescript
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:
```typescript
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:
```typescript
// 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:
```typescript
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:
```bash
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:
```bash
cd dist/auth-client
```
2. Run the `npm publish` command to publish your library to the npm registry:
```bash
npm publish
```
## Running unit tests
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
```bash
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