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>
This commit is contained in:
67
projects/auth-client/src/lib/guards/auth.guard.ts
Normal file
67
projects/auth-client/src/lib/guards/auth.guard.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate, CanActivateChild, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, take, tap } from 'rxjs/operators';
|
||||
import { AuthService } from '../services/auth.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthGuard implements CanActivate, CanActivateChild {
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean> {
|
||||
return this.checkAuth(route, state.url);
|
||||
}
|
||||
|
||||
canActivateChild(
|
||||
childRoute: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean> {
|
||||
return this.canActivate(childRoute, state);
|
||||
}
|
||||
|
||||
private checkAuth(route: ActivatedRouteSnapshot, redirectUrl: string): Observable<boolean> {
|
||||
return this.authService.isAuthenticated$.pipe(
|
||||
take(1),
|
||||
map(isAuthenticated => {
|
||||
if (isAuthenticated) {
|
||||
// Check for required scopes if specified
|
||||
const requiredScopes = route.data?.['requiredScopes'] as string[];
|
||||
if (requiredScopes && requiredScopes.length > 0) {
|
||||
const hasScopes = route.data?.['requireAllScopes']
|
||||
? this.authService.hasAllScopes(requiredScopes)
|
||||
: this.authService.hasAnyScope(requiredScopes);
|
||||
|
||||
if (!hasScopes) {
|
||||
this.handleUnauthorized(route.data?.['unauthorizedRedirect']);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
this.handleUnauthenticated(redirectUrl, route.data?.['loginRedirect']);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private handleUnauthenticated(redirectUrl: string, customLoginPath?: string): void {
|
||||
const loginPath = customLoginPath || '/login';
|
||||
this.router.navigate([loginPath], {
|
||||
queryParams: { returnUrl: redirectUrl }
|
||||
});
|
||||
}
|
||||
|
||||
private handleUnauthorized(customUnauthorizedPath?: string): void {
|
||||
const unauthorizedPath = customUnauthorizedPath || '/unauthorized';
|
||||
this.router.navigate([unauthorizedPath]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user