npm package: @niid/sdk
Description: NIID Web SDK for OAuth 2.0 integration - React and Vanilla JavaScript support
Author: NIID Team
Latest version: 1.0.3

# NIID Web SDK

Веб-SDK для интеграции с NIID OAuth 2.0 системой единого входа.

## Установка

```bash
npm install @niid/sdk
```

## Быстрый старт

### React

```tsx
import { LoginButton } from '@niid/sdk/react';
import '@niid/sdk/styles';

function App() {
  return (
    <LoginButton
      clientId="your-client-id"
      onSuccess={(user) => console.log('User logged in:', user)}
      onError={(error) => console.error('Login error:', error)}
    >
      Sign in with NIID
    </LoginButton>
  );
}
```

### Vanilla JavaScript

```html
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="node_modules/@niid/sdk/styles/button.css">
</head>
<body>
  <div id="login-container"></div>
  
  <script type="module">
    import { createLoginButton } from '@niid/sdk/vanilla';
    
    const button = createLoginButton({
      clientId: 'your-client-id',
      onSuccess: (user) => console.log('User logged in:', user),
      onError: (error) => console.error('Login error:', error)
    }, document.getElementById('login-container'));
  </script>
</body>
</html>
```

### Программный доступ

```typescript
import { NIIDClient } from '@niid/sdk';

const client = new NIIDClient({
  clientId: 'your-client-id',
  apiUrl: 'http://localhost:11700',
  ssoUrl: 'http://localhost:11706'
});

// Инициация входа
client.login();

// Обработка callback (вызывать на странице после редиректа)
const user = await client.handleCallback();

// Получение информации о пользователе
const userInfo = await client.getUserInfo();

// Проверка аутентификации
if (client.isAuthenticated()) {
  console.log('User is authenticated');
}

// Выход
client.logout();
```

## Конфигурация

### NIIDConfig

```typescript
interface NIIDConfig {
  clientId: string;              // Обязательно: Client ID приложения
  clientSecret?: string;        // Опционально: для конфиденциальных клиентов
  apiUrl?: string;              // По умолчанию: http://localhost:11700
  ssoUrl?: string;              // По умолчанию: http://localhost:11706
  redirectUri?: string;         // По умолчанию: window.location.origin + window.location.pathname
  scope?: string;               // По умолчанию: 'profile email'
  storageKey?: string;          // По умолчанию: 'niid'
}
```

## API

### NIIDClient

Основной класс для работы с NIID OAuth.

#### Методы

- `login(redirectUri?: string, scope?: string)` - Инициация OAuth flow
- `handleCallback()` - Обработка OAuth callback после редиректа
- `getUserInfo()` - Получение информации о текущем пользователе
- `refreshToken()` - Обновление access token через refresh token
- `logout()` - Выход и очистка токенов
- `isAuthenticated()` - Проверка наличия валидного access token
- `getAccessToken()` - Получение текущего access token

### LoginButton (React)

React компонент кнопки входа.

#### Пропсы

- `clientId: string` - Client ID приложения (обязательно)
- `clientSecret?: string` - Client Secret (опционально)
- `apiUrl?: string` - URL API Gateway
- `ssoUrl?: string` - URL SSO Flow
- `redirectUri?: string` - Redirect URI
- `scope?: string` - OAuth scope
- `onSuccess?: (user: UserInfo) => void` - Callback при успешном входе
- `onError?: (error: Error) => void` - Callback при ошибке
- `className?: string` - Дополнительные CSS классы
- `children?: ReactNode` - Кастомный текст кнопки
- `variant?: 'primary' | 'secondary'` - Вариант стиля

### createLoginButton (Vanilla JS)

Функция для создания кнопки входа без React.

#### Параметры

- `config: LoginButtonConfig` - Конфигурация кнопки
- `container: HTMLElement` - DOM элемент для размещения кнопки

#### Возвращает

Объект с методами:
- `destroy()` - Удаление кнопки из DOM
- `update(config: Partial<LoginButtonConfig>)` - Обновление конфигурации

## Типы

```typescript
interface UserInfo {
  id: number;
  email: string;
  name?: string;
  phone?: string;
  is_active?: boolean;
  created_at?: string;
  updated_at?: string;
}

interface TokenResponse {
  access_token: string;
  refresh_token?: string;
  token_type: string;
  expires_in: number;
  scope?: string;
}
```

## Примеры

### Полный пример с обработкой callback

```tsx
import { useState, useEffect } from 'react';
import { LoginButton, NIIDClient } from '@niid/sdk/react';
import '@niid/sdk/styles';

function App() {
  const [user, setUser] = useState(null);
  const [client, setClient] = useState<NIIDClient | null>(null);

  useEffect(() => {
    const niidClient = new NIIDClient({
      clientId: 'your-client-id',
      apiUrl: 'http://localhost:11700',
      ssoUrl: 'http://localhost:11706'
    });
    setClient(niidClient);

    // Обработка callback после редиректа
    const handleCallback = async () => {
      const urlParams = new URLSearchParams(window.location.search);
      if (urlParams.get('code')) {
        try {
          const userInfo = await niidClient.handleCallback();
          setUser(userInfo);
        } catch (error) {
          console.error('Failed to handle callback:', error);
        }
      }
    };

    handleCallback();
  }, []);

  return (
    <div>
      {user ? (
        <div>
          <p>Welcome, {user.email}!</p>
          <button onClick={() => {
            client?.logout();
            setUser(null);
          }}>Logout</button>
        </div>
      ) : (
        <LoginButton
          clientId="your-client-id"
          onSuccess={(user) => setUser(user)}
          onError={(error) => console.error(error)}
        />
      )}
    </div>
  );
}
```

## Стили

SDK включает готовые стили кнопки в стиле SSO flow. Для их использования:

### React

```tsx
import '@niid/sdk/styles';
```

### Vanilla JS

```html
<link rel="stylesheet" href="node_modules/@niid/sdk/dist/styles/button.css">
```

## Безопасность

- SDK автоматически генерирует и проверяет `state` параметр для защиты от CSRF атак
- Токены хранятся в `localStorage` (для публичных клиентов) или могут быть настроены для использования `httpOnly` cookies (требует дополнительной настройки на backend)
- Access token автоматически обновляется перед истечением срока действия
- Refresh token используется для автоматического обновления access token при истечении

## Лицензия

MIT