- 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>
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:
-
Navigate to the
distdirectory:cd dist/auth-client -
Run the
npm publishcommand 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