npm package: @simple-login/sdk
Description: Official SDK for Simple Login
Latest version: 3.2.0

# @simple-login/sdk

Official SDK for Simple Login authentication.

## Getting Started

1. Create an account at [simple-login.com](https://simple-login.com)
2. Create an application to get your `clientId` and `clientSecret`
3. Install the SDK and configure it with your credentials

## Installation

```bash
npm install @simple-login/sdk
```

## Configuration

### Using environment variables (recommended)

Set these environment variables and the SDK will auto-detect them:

```bash
# Private server-side
SIMPLELOGIN_CLIENT_SECRET=your-client-secret

# Public
VITE_SIMPLELOGIN_CLIENT_ID=your-client-id
VITE_SIMPLELOGIN_SLUG=your-slug
VITE_SIMPLELOGIN_REDIRECT_URI=https://your-app.com/auth/callback
VITE_SIMPLELOGIN_ORIGIN=https://your-app.com

# NB: Works with VITE_, NEXT_PUBLIC_, NUXT_PUBLIC_, PUBLIC_, REACT_APP_ and EXPO_PUBLIC_
```

```typescript
import { SimpleLogin } from '@simple-login/sdk'

const simpleLogin = new SimpleLogin()
```

### Explicit configuration

You can also pass the config directly (this overrides environment variables):

```typescript
const simpleLogin = new SimpleLogin({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  redirectUri: 'https://your-app.com/auth/callback',
  origin: 'https://your-app.com',
})
```

## Quick Start (All-in-One Flow)

The SDK provides a batteries-included flow that handles cookies, PKCE, state verification, and token refresh automatically.

### 1. Login Route

```typescript
// GET /auth/login
export async function loader() {
  return simpleLogin.redirectToAuth()
}
```

### 2. Callback Route

```typescript
// GET /auth/callback
export async function loader({ request }) {
  const { response, user } = await simpleLogin.handleCallback(request, '/dashboard')

  // Store user in your database if needed
  await db.users.upsert({
    id: user.id,
    email: user.email,
    name: user.name,
  })

  return response
}
```

### 3. Protected Routes

```typescript
// GET /dashboard
export async function loader({ request }) {
  const auth = await simpleLogin.authenticate(request)

  if (!auth) {
    return simpleLogin.redirectToAuth()
  }

  // auth.claims contains decoded JWT claims (sub, application_id, etc.)
  const user = await db.users.findById(auth.claims.sub)

  // auth.headers contains Set-Cookie if tokens were refreshed
  return json({ user }, { headers: auth.headers })
}
```

### 4. Logout Route

```typescript
// POST /auth/logout
export async function action({ request }) {
  return simpleLogin.logout(request)
}
```

## Security Features

### PKCE (Proof Key for Code Exchange)

PKCE is automatically enabled for all authorization requests. The SDK generates a cryptographically secure code verifier and challenge, stores the verifier in an HttpOnly cookie, and includes it in the token exchange.

### State Parameter

A cryptographically secure state parameter is automatically generated (or you can provide your own) and verified on callback to prevent CSRF attacks.

### CSRF Protection for Mutations

The `authenticate()` method automatically checks the `Origin` or `Referer` header for non-GET requests against your configured `origin`. Returns `null` if the origin doesn't match, preventing CSRF attacks.

**Important:** You must set `SIMPLELOGIN_ORIGIN` environment variable (or pass `origin` in config) for CSRF protection to work.

### Token Refresh

The `authenticate()` method automatically refreshes expired access tokens using the refresh token. When tokens are refreshed, the new cookies are included in `auth.headers` - just pass them to your response.

### Secure Cookie Defaults

All cookies are set with secure defaults:

- `HttpOnly` - Not accessible via JavaScript
- `Secure` - Only sent over HTTPS
- `SameSite=Lax` - CSRF protection
- `Path=/` - Available site-wide

## License

MIT