Skip to content
XID

@xid-kit/angular

Angular 17+ standalone provider, RxJS service, functional route guards, and standalone components on top of @xid-kit/core.

Status

XID publishes no packages to any registry. This SDK is distributed as source in the XID repository; use it from a checkout of the repository.

Package status is Current package. Angular 17+ standalone provider, RxJS service, functional guards, and standalone components are implemented. A real IdP round-trip on production infrastructure is still pending manual verification.

Provider setup

Call provideXid in app.config.ts. It registers the XID_CLIENT injection token and wires an APP_INITIALIZER that calls client.load() on bootstrap. No NgModule required.

// app.config.ts
import { ApplicationConfig } from '@angular/core'
import { provideXid } from '@xid-kit/angular'

export const appConfig: ApplicationConfig = {
  providers: [
    // Core auth endpoints must be served on this application's exact origin.
    provideXid({ mode: 'same-origin' }),
  ],
}

XidAuthService

import { Component, inject } from '@angular/core'
import { AsyncPipe } from '@angular/common'
import { XidAuthService } from '@xid-kit/angular'

@Component({
  selector: 'app-header',
  standalone: true,
  imports: [AsyncPipe],
  template: `
    @if (auth.isLoaded$ | async) {
      @if (auth.isSignedIn$ | async) {
        <span>{{ (auth.user$ | async)?.primaryEmailAddress }}</span>
      } @else {
        <a routerLink="/sign-in">Sign in</a>
      }
    }
  `,
})
export class HeaderComponent {
  readonly auth = inject(XidAuthService)
}

Angular signals bridge

Use toSignal() from @angular/core/rxjs-interop to convert observables to signals for template reads.

import { toSignal } from '@angular/core/rxjs-interop'
import { inject } from '@angular/core'
import { XidAuthService } from '@xid-kit/angular'

@Component({ standalone: true, ... })
export class MyComponent {
  readonly #auth = inject(XidAuthService)
  readonly user = toSignal(this.#auth.user$, { initialValue: null })
}

Route guards

import { Routes } from '@angular/router'
import { authGuard, hasOrganizationGuard, hasPermissionGuard } from '@xid-kit/angular'

export const routes: Routes = [
  {
    path: 'dashboard',
    canActivate: [authGuard()],
    loadComponent: () => import('./dashboard.component').then(m => m.DashboardComponent),
  },
  {
    path: 'admin',
    canActivate: [hasPermissionGuard('org:settings:write')],
    loadComponent: () => import('./admin.component').then(m => m.AdminComponent),
  },
]

Standalone components

<!-- template -->
<xid-sign-in-button signInUrl="/sign-in" redirectUrl="/dashboard">Log in</xid-sign-in-button>
<xid-sign-out-button redirectUrl="/home">Log out</xid-sign-out-button>

Exported API

Export Kind Purpose
provideXid function Registers XID_CLIENT singleton and APP_INITIALIZER; accepts ProvideXidOptions
XID_CLIENT InjectionToken The raw XidClient instance; prefer XidAuthService for most use cases
XidAuthService service RxJS observables: state$, isLoaded$, isSignedIn$, user$, session$, organization$; plus getToken, signOut, setActiveOrganization, setActiveSession
authGuard CanActivateFn factory Redirects to /sign-in when user is not signed in
hasOrganizationGuard CanActivateFn factory Redirects when no active organization context is present
hasPermissionGuard CanActivateFn factory Redirects when user lacks the specified permission
SignInButton standalone component Selector xid-sign-in-button; inputs signInUrl, redirectUrl, ariaLabel
SignOutButton standalone component Selector xid-sign-out-button; inputs sessionId, redirectUrl, ariaLabel; shows aria-busy while signing out

Type to search

Use arrow keys to navigateEnter to selectEscape to close