@stardyn/angular-auth
Version:
Angular Authentication Service - Lightweight, configurable authentication service for Angular applications with token management and role-based access control
502 lines (412 loc) • 13 kB
Markdown
# @stardyn/angular-auth
Lightweight, configurable authentication service for Angular applications with token management, role-based access control, and comprehensive security features.
## Features
- **Token Management**: JWT token handling with automatic refresh support
- **Role-Based Access Control**: Route guards and directives for permission-based access
- **Social Authentication**: Google and Microsoft OAuth integration
- **Multiple DataSource Support**: Compatible with standard and refresh-enabled data sources
- **Route Guards**: Comprehensive guard system for authentication and authorization
- **TypeScript Support**: Full type safety with detailed interfaces
- **Security Features**: Password hashing, secure token storage, and automatic logout
- **Angular Integration**: Seamless integration with Angular Router and Dependency Injection
## Installation
```bash
npm install @stardyn/angular-auth
```
## Prerequisites
This package requires the following peer dependencies:
```bash
npm install @stardyn/angular-console @stardyn/angular-data-source @stardyn/angular-helpers
```
## Quick Start
### 1. Basic Authentication Setup
```typescript
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { provideXconAuth } from '@stardyn/angular-auth';
import { XconPasswordHashType } from '@stardyn/angular-auth';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
RouterModule.forRoot([])
],
providers: [
provideXconAuth({
useRefreshToken: true,
debugMode: true,
passwordHashType: XconPasswordHashType.SHA256,
loginEmailEndpoint: '/api/auth/login',
logoutEndpoint: '/api/auth/logout',
refreshTokenEndpoint: '/api/auth/refresh'
})
],
bootstrap: [AppComponent]
})
export class AppModule { }
```
### 2. Standalone Application Setup
```typescript
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { provideXconAuth, XconPasswordHashType } from '@stardyn/angular-auth';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideXconAuth({
useRefreshToken: false,
debugMode: false,
passwordHashType: XconPasswordHashType.MD5_UPPER,
loginEmailEndpoint: '/auth/login-by-email',
redirectLoginUrl: '/dashboard'
})
]
});
```
### 3. Authentication Service Usage
```typescript
import { Component, OnInit } from '@angular/core';
import { AuthService, LoginRequest } from '@stardyn/angular-auth';
@Component({
selector: 'app-login',
template: `
<form (ngSubmit)="login()">
<input [(ngModel)]="email" type="email" placeholder="Email" required>
<input [(ngModel)]="password" type="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
`
})
export class LoginComponent implements OnInit {
email = '';
password = '';
constructor(private authService: AuthService) {}
ngOnInit() {
// Check if user is already authenticated
this.authService.isAuthenticated$.subscribe(isAuth => {
if (isAuth) {
console.log('User is authenticated');
}
});
}
login() {
const credentials: LoginRequest = {
email: this.email,
password: this.password
};
this.authService.login(credentials).subscribe({
next: (response) => {
console.log('Login successful:', response.user);
// Redirect will be handled automatically
},
error: (error) => {
console.error('Login failed:', error.message);
}
});
}
logout() {
this.authService.logout();
}
}
```
## Route Guards
### Authentication Guard
```typescript
import { Routes } from '@angular/router';
import { AuthGuard } from '@stardyn/angular-auth';
export const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard]
},
{
path: 'admin',
component: AdminComponent,
canActivate: [AuthGuard],
canActivateChild: [AuthGuard]
}
];
```
### Role-Based Guard
```typescript
import { Routes } from '@angular/router';
import { AuthRoleGuard, withPermissions, withPermissionsAndRedirect } from '@stardyn/angular-auth';
export const routes: Routes = [
{
path: 'devices',
component: DevicesComponent,
canActivate: [AuthRoleGuard],
data: { permissions: 'DEVICE_READ' }
},
{
path: 'admin-panel',
component: AdminPanelComponent,
canActivate: [AuthRoleGuard],
data: {
permissions: 'ADMIN_PANEL | SUPER_ADMIN',
permissionRedirectTo: '/unauthorized'
}
},
// Using helper functions
{
path: 'settings',
component: SettingsComponent,
...withPermissions(['SETTINGS_READ', 'SETTINGS_WRITE'])
},
{
path: 'reports',
component: ReportsComponent,
...withPermissionsAndRedirect('REPORTS_READ', '/access-denied')
}
];
```
### Login Guard
```typescript
import { Routes } from '@angular/router';
import { LoginGuard } from '@stardyn/angular-auth';
export const routes: Routes = [
{
path: 'login',
component: LoginComponent,
canActivate: [LoginGuard] // Redirects authenticated users away from login page
}
];
```
## Permission Directive
Use the structural directive to conditionally show content based on user permissions:
```typescript
import { Component } from '@angular/core';
import { XconAuthIfRoleDirective } from '@stardyn/angular-auth';
@Component({
selector: 'app-dashboard',
standalone: true,
imports: [XconAuthIfRoleDirective],
template: `
<!-- Single permission -->
<button *xconAuthIfRole="'DEVICE_CREATE'">Create Device</button>
<!-- Multiple permissions (any) -->
<div *xconAuthIfRole="'ADMIN_PANEL | SUPER_ADMIN'">
<h3>Admin Tools</h3>
</div>
<!-- Array syntax -->
<section *xconAuthIfRole="['REPORTS_READ', 'REPORTS_WRITE']">
<app-reports></app-reports>
</section>
`
})
export class DashboardComponent {}
```
## Social Authentication
```typescript
import { Component } from '@angular/core';
import { AuthService, LoginMicrosoftRequest } from '@stardyn/angular-auth';
@Component({
selector: 'app-social-login',
template: `
<button (click)="loginWithGoogle()">Login with Google</button>
<button (click)="loginWithMicrosoft()">Login with Microsoft</button>
`
})
export class SocialLoginComponent {
constructor(private authService: AuthService) {}
loginWithGoogle() {
this.authService.loginWithGoogle().subscribe({
next: (response) => console.log('Google login successful'),
error: (error) => console.error('Google login failed:', error)
});
}
loginWithMicrosoft() {
const microsoftData: LoginMicrosoftRequest = {
email: 'user@company.com',
displayName: 'John Doe',
token: 'microsoft-oauth-token'
};
this.authService.loginWithMicrosoft(microsoftData).subscribe({
next: (response) => console.log('Microsoft login successful'),
error: (error) => console.error('Microsoft login failed:', error)
});
}
}
```
## Configuration Options
### Core Configuration
```typescript
interface XconCoreAuthConfig {
// Security settings
authSiteKey?: string;
authSiteName?: string;
passwordHashType?: XconPasswordHashType;
debugMode?: boolean;
// Token management
useRefreshToken?: boolean;
// API endpoints
loginEmailEndpoint?: string;
loginGmailEndpoint?: string;
loginMicrosoftEndpoint?: string;
logoutEndpoint?: string;
refreshTokenEndpoint?: string;
// Redirect URLs
redirectLoginUrl?: string; // Where to go after login (default: '/dashboard')
redirectLogoutUrl?: string; // Where to go after logout (default: '/login')
// Permission system
isPermissionEngineActive?: boolean;
}
```
### Password Hash Types
```typescript
enum XconPasswordHashType {
NONE = 'NONE', // No hashing (not recommended)
MD5_UPPER = 'MD5_UPPER', // MD5 hash uppercase
SHA256 = 'SHA256' // SHA256 with site key
}
```
## Advanced Usage
### Custom Token Refresh
```typescript
import { Component, OnInit } from '@angular/core';
import { AuthService } from '@stardyn/angular-auth';
@Component({
selector: 'app-advanced-auth'
})
export class AdvancedAuthComponent implements OnInit {
constructor(private authService: AuthService) {}
ngOnInit() {
// Manual token refresh
this.authService.refreshToken().then(response => {
if (response.success) {
console.log('Token refreshed successfully');
}
});
}
getCurrentUserInfo() {
const user = this.authService.getCurrentUser();
if (user) {
console.log('Current user:', {
id: user.user_id,
email: user.email,
permissions: user.permissions,
company: user.company_name
});
}
}
}
```
### User Utilities
```typescript
import { XConUserUtils, XConUser } from '@stardyn/angular-auth';
// User information helpers
const user: XConUser = getCurrentUser();
const fullName = XConUserUtils.getFullName(user);
const displayName = XConUserUtils.getDisplayName(user);
const initials = XConUserUtils.getInitials(user);
const avatarUrl = XConUserUtils.getAvatarUrl(user, 'https://cdn.example.com');
// Permission checks
const canRead = XConUserUtils.hasPermission(user, 'DEVICE_READ');
const canDoAny = XConUserUtils.hasAnyPermission(user, ['READ', 'WRITE']);
const canDoAll = XConUserUtils.hasAllPermissions(user, ['READ', 'WRITE']);
// Authority checks
const isAdmin = XConUserUtils.isAdmin(user);
const isSysAdmin = XConUserUtils.isSysAdmin(user);
const isCustomerUser = XConUserUtils.isCustomerUser(user);
```
## Error Handling
```typescript
import { Component } from '@angular/core';
import { AuthService } from '@stardyn/angular-auth';
@Component({
selector: 'app-error-handling'
})
export class ErrorHandlingComponent {
constructor(private authService: AuthService) {}
handleLogin() {
this.authService.login({ email: 'user@test.com', password: 'test' })
.subscribe({
next: (response) => {
// Success
},
error: (error) => {
switch (error.message) {
case 'Invalid credentials':
console.log('Wrong email or password');
break;
case 'Network connection failed':
console.log('Check your internet connection');
break;
case 'Access forbidden':
console.log('Account may be suspended');
break;
default:
console.log('Login failed:', error.message);
}
}
});
}
}
```
## Environment Configuration
```typescript
// environments/environment.ts
export const environment = {
production: false,
auth: {
useRefreshToken: true,
debugMode: true,
passwordHashType: 'SHA256',
loginEmailEndpoint: '/dev/auth/login',
redirectLoginUrl: '/dashboard',
authSiteKey: 'dev-site-key',
authSiteName: 'MyApp Development'
}
};
// app.module.ts
import { environment } from '../environments/environment';
@NgModule({
providers: [
provideXconAuth(environment.auth)
]
})
export class AppModule {}
```
## TypeScript Support
Full TypeScript support with comprehensive type definitions:
```typescript
import {
AuthService,
XConUser,
AuthResponse,
XconCoreAuthConfig,
LoginRequest,
RefreshTokenRequest
} from '@stardyn/angular-auth';
// Type-safe configuration
const config: XconCoreAuthConfig = {
useRefreshToken: true,
debugMode: false,
passwordHashType: XconPasswordHashType.SHA256
};
// Type-safe user handling
const handleUser = (user: XConUser) => {
console.log(`User ${user.name} has permissions:`, user.permissions);
};
```
## Dependencies
### Peer Dependencies
- `@angular/core` ^20.0.0
- `@angular/common` ^20.0.0
- `@angular/router` ^20.0.0
- `rxjs` >=7.0.0
- `@stardyn/angular-console` ^2.0.9
- `@stardyn/angular-data-source` ^2.0.9
- `@stardyn/angular-helpers` ^2.0.9
## Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
## License
MIT License - see LICENSE file for details.
## Repository
https://github.com/stardyn/angular-auth