**English** | [한국어](./README.ko.md)

# @authon/angular

> Drop-in Angular authentication with service, guard, and social buttons — Auth0 alternative

[![npm version](https://img.shields.io/npm/v/@authon/angular?color=6d28d9)](https://www.npmjs.com/package/@authon/angular)
[![License](https://img.shields.io/badge/license-MIT-blue)](../../LICENSE)

## Prerequisites

Before installing the SDK, create an Authon project and get your API keys:

1. **Create a project** at [Authon Dashboard](https://authon.dev/dashboard/overview)
   - Click "Create Project" and enter your app name
   - Select the authentication methods you want (Email/Password, OAuth providers, etc.)

2. **Get your API keys** from Project Settings → API Keys
   - **Publishable Key** (`pk_live_...`) — use in your frontend code
   - **Test Key** (`pk_test_...`) — for development, enables Dev Teleport

3. **Configure OAuth providers** (optional) in Project Settings → OAuth
   - Add Google, Apple, GitHub, etc. with their respective Client ID and Secret
   - Set the redirect URL to `https://api.authon.dev/v1/auth/oauth/redirect`

> **Test vs Live keys:** Use `pk_test_...` during development. Switch to `pk_live_...` before deploying to production. Test keys use a sandbox environment with no rate limits.

## Install

```bash
npm install @authon/angular
```

## Quick Start

```ts
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideAuthon } from '@authon/angular';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    ...provideAuthon({
      publishableKey: 'pk_live_YOUR_PUBLISHABLE_KEY',
    }),
  ],
};
```

```ts
// app.component.ts
import { Component, Inject, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';
import { AuthonService } from '@authon/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <div *ngIf="!authon.isLoading">
      <div *ngIf="authon.isSignedIn">
        <p>Welcome, {{ authon.user?.displayName }}</p>
        <button (click)="authon.signOut()">Sign out</button>
      </div>
      <button *ngIf="!authon.isSignedIn" (click)="authon.openSignIn()">Sign in</button>
    </div>
  `,
})
export class AppComponent implements OnInit, OnDestroy {
  private unsub?: () => void;
  constructor(
    @Inject('AuthonService') public authon: AuthonService,
    private cdr: ChangeDetectorRef,
  ) {}
  ngOnInit() { this.unsub = this.authon.onStateChange(() => this.cdr.markForCheck()); }
  ngOnDestroy() { this.unsub?.(); }
}
```

## Common Tasks

### Add Google OAuth Login

```ts
async signInWithGoogle() {
  await this.authon.getClient().signInWithOAuth('google');
}
```

### Protect a Route

```ts
// app.routes.ts
import { inject } from '@angular/core';
import { authGuard, AuthonService } from '@authon/angular';

export const routes = [
  {
    path: 'dashboard',
    loadComponent: () => import('./dashboard.component').then(m => m.DashboardComponent),
    canActivate: [() => {
      const authon = inject('AuthonService') as AuthonService;
      return authGuard(authon, '/sign-in');
    }],
  },
];
```

### Get Current User

```ts
const user = this.authon.user;
// { id, email, displayName, avatarUrl, emailVerified, ... }

const token = this.authon.getToken();
```

### Add Email/Password Auth

```ts
async handleSignIn(email: string, password: string) {
  await this.authon.getClient().signInWithEmail(email, password);
}
```

### Handle Sign Out

```ts
await this.authon.signOut();
```

## Environment Variables

| Variable | Required | Description |
|----------|----------|-------------|
| `AUTHON_PUBLISHABLE_KEY` | Yes | Project publishable key (`pk_live_...` or `pk_test_...`) |
| `AUTHON_API_URL` | No | Optional — defaults to `api.authon.dev` |

## API Reference

### AuthonService

| Property / Method | Type |
|-------------------|------|
| `user` | `AuthonUser \| null` |
| `isSignedIn` | `boolean` |
| `isLoading` | `boolean` |
| `openSignIn()` | `Promise<void>` |
| `openSignUp()` | `Promise<void>` |
| `signOut()` | `Promise<void>` |
| `getToken()` | `string \| null` |
| `getClient()` | `Authon` (full @authon/js client) |
| `onStateChange(cb)` | `() => void` (unsubscribe) |
| `web3GetNonce(...)` | Web3 nonce |
| `web3Verify(...)` | Web3 sign-in |
| `passwordlessSendCode(...)` | Magic link / OTP |
| `passkeyRegister(...)` | Register passkey |
| `passkeyAuthenticate(...)` | Auth with passkey |

### Helpers

| Function | Description |
|----------|-------------|
| `provideAuthon(config)` | Angular provider factory for standalone apps |
| `authGuard(service, redirectTo?)` | Route guard factory |
| `renderSocialButtons(options)` | Render OAuth buttons into a DOM element |

## Comparison

| Feature | Authon | Clerk | Auth.js |
|---------|--------|-------|---------|
| Pricing | Free | $25/mo+ | Free |
| OAuth providers | 10+ | 20+ | 80+ |
| Angular support | Native | Community | No |
| MFA/Passkeys | Yes | Yes | Plugin |
| Web3 auth | Yes | No | No |

## License

MIT
