SDK

Angular SDK (idenplane-angular)

Full Angular integration with dependency injection, route guards, HTTP interceptor, and RxJS-based reactive state.

Key Features

Injectable AuthService with RxJS observables
Route guards (role-based)
HTTP interceptor with automatic 401 retry
NgModule.forRoot() and standalone-compatible
OAuth 2.0 + PKCE
Automatic token refresh
Dedicated authError$ stream for error handling
Reactive user state

Requirements

  • Angular 16+
  • TypeScript 5+
  • Node.js 18+

Installation

npm install idenplane-angular

Configuration

Register the SDK in your root module using IdenplaneModule.forRoot(). This provides AuthService, AuthGuard, and AuthInterceptor for the whole app.

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { IdenplaneModule } from 'idenplane-angular';

@NgModule({
  imports: [
    BrowserModule,
    HttpClientModule,
    IdenplaneModule.forRoot({
      url: 'https://auth.example.com',
      realm: 'my-realm',
      clientId: 'my-angular-app',
      redirectUri: window.location.origin + '/callback',
    }),
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

AuthService — Login & Logout

Inject AuthService to manage authentication state. State is exposed as RxJS observables (isAuthenticated$, user$, isLoading$) for use with the async pipe.

import { Component } from '@angular/core';
import { AuthService } from 'idenplane-angular';

@Component({
  selector: 'app-header',
  template: `
    @if (auth.isAuthenticated$ | async) {
      <span>Welcome, {{ (auth.user$ | async)?.name }}</span>
      <button (click)="auth.logout()">Logout</button>
    } @else {
      <button (click)="auth.login()">Sign In</button>
    }
  `,
})
export class HeaderComponent {
  constructor(public auth: AuthService) {}
}

Route Guards

Protect routes with the built-in AuthGuard class, applied via canActivate. Role requirements go in the route's data.roles array.

import { Routes } from '@angular/router';
import { AuthGuard } from 'idenplane-angular';

export const routes: Routes = [
  { path: '', component: HomeComponent },
  {
    path: 'dashboard',
    component: DashboardComponent,
    canActivate: [AuthGuard],
  },
  {
    path: 'admin',
    component: AdminComponent,
    canActivate: [AuthGuard],
    data: { roles: ['admin'] }, // Role-based guard
  },
];

HTTP Interceptor

IdenplaneModule.forRoot() already registers the class-based interceptor. If you use standalone components with provideHttpClient() instead of HttpClientModule, wire the functional authInterceptor directly.

// app.config.ts (standalone bootstrap)
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { authInterceptor } from 'idenplane-angular';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(
      withInterceptors([authInterceptor])
    ),
  ],
};

// API calls automatically include an Authorization: Bearer header,
// and a single token refresh + retry is attempted on a 401 response.
@Injectable()
export class ApiService {
  constructor(private http: HttpClient) {}

  getProfile() {
    return this.http.get('/api/profile');
  }
}

User Info & Roles

AuthService also exposes synchronous getters and role/permission helpers for use outside templates.

import { Component } from '@angular/core';
import { AuthService } from 'idenplane-angular';

@Component({ /* ... */ })
export class ProfileComponent {
  constructor(private auth: AuthService) {}

  get user() { return this.auth.user; }
  get isAdmin() { return this.auth.hasRole('admin'); }
  get token() { return this.auth.getToken(); }
}

Callback Component

Handle the OAuth callback redirect.

// callback.component.ts
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from 'idenplane-angular';

@Component({
  selector: 'app-callback',
  template: '<p>Signing in...</p>',
})
export class CallbackComponent implements OnInit {
  constructor(private auth: AuthService, private router: Router) {}

  async ngOnInit() {
    await this.auth.handleCallback();
    this.router.navigate(['/dashboard']);
  }
}