@niid/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,257 @@
1
+ # NIID Web SDK
2
+
3
+ Веб-SDK для интеграции с NIID OAuth 2.0 системой единого входа.
4
+
5
+ ## Установка
6
+
7
+ ```bash
8
+ npm install @niid/sdk
9
+ ```
10
+
11
+ ## Быстрый старт
12
+
13
+ ### React
14
+
15
+ ```tsx
16
+ import { LoginButton } from '@niid/sdk/react';
17
+ import '@niid/sdk/styles';
18
+
19
+ function App() {
20
+ return (
21
+ <LoginButton
22
+ clientId="your-client-id"
23
+ onSuccess={(user) => console.log('User logged in:', user)}
24
+ onError={(error) => console.error('Login error:', error)}
25
+ >
26
+ Sign in with NIID
27
+ </LoginButton>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ### Vanilla JavaScript
33
+
34
+ ```html
35
+ <!DOCTYPE html>
36
+ <html>
37
+ <head>
38
+ <link rel="stylesheet" href="node_modules/@niid/sdk/styles/button.css">
39
+ </head>
40
+ <body>
41
+ <div id="login-container"></div>
42
+
43
+ <script type="module">
44
+ import { createLoginButton } from '@niid/sdk/vanilla';
45
+
46
+ const button = createLoginButton({
47
+ clientId: 'your-client-id',
48
+ onSuccess: (user) => console.log('User logged in:', user),
49
+ onError: (error) => console.error('Login error:', error)
50
+ }, document.getElementById('login-container'));
51
+ </script>
52
+ </body>
53
+ </html>
54
+ ```
55
+
56
+ ### Программный доступ
57
+
58
+ ```typescript
59
+ import { NIIDClient } from '@niid/sdk';
60
+
61
+ const client = new NIIDClient({
62
+ clientId: 'your-client-id',
63
+ apiUrl: 'http://localhost:11700',
64
+ ssoUrl: 'http://localhost:11706'
65
+ });
66
+
67
+ // Инициация входа
68
+ client.login();
69
+
70
+ // Обработка callback (вызывать на странице после редиректа)
71
+ const user = await client.handleCallback();
72
+
73
+ // Получение информации о пользователе
74
+ const userInfo = await client.getUserInfo();
75
+
76
+ // Проверка аутентификации
77
+ if (client.isAuthenticated()) {
78
+ console.log('User is authenticated');
79
+ }
80
+
81
+ // Выход
82
+ client.logout();
83
+ ```
84
+
85
+ ## Конфигурация
86
+
87
+ ### NIIDConfig
88
+
89
+ ```typescript
90
+ interface NIIDConfig {
91
+ clientId: string; // Обязательно: Client ID приложения
92
+ clientSecret?: string; // Опционально: для конфиденциальных клиентов
93
+ apiUrl?: string; // По умолчанию: http://localhost:11700
94
+ ssoUrl?: string; // По умолчанию: http://localhost:11706
95
+ redirectUri?: string; // По умолчанию: window.location.origin + window.location.pathname
96
+ scope?: string; // По умолчанию: 'profile email'
97
+ storageKey?: string; // По умолчанию: 'niid'
98
+ }
99
+ ```
100
+
101
+ ## API
102
+
103
+ ### NIIDClient
104
+
105
+ Основной класс для работы с NIID OAuth.
106
+
107
+ #### Методы
108
+
109
+ - `login(redirectUri?: string, scope?: string)` - Инициация OAuth flow
110
+ - `handleCallback()` - Обработка OAuth callback после редиректа
111
+ - `getUserInfo()` - Получение информации о текущем пользователе
112
+ - `refreshToken()` - Обновление access token через refresh token
113
+ - `logout()` - Выход и очистка токенов
114
+ - `isAuthenticated()` - Проверка наличия валидного access token
115
+ - `getAccessToken()` - Получение текущего access token
116
+
117
+ ### LoginButton (React)
118
+
119
+ React компонент кнопки входа.
120
+
121
+ #### Пропсы
122
+
123
+ - `clientId: string` - Client ID приложения (обязательно)
124
+ - `clientSecret?: string` - Client Secret (опционально)
125
+ - `apiUrl?: string` - URL API Gateway
126
+ - `ssoUrl?: string` - URL SSO Flow
127
+ - `redirectUri?: string` - Redirect URI
128
+ - `scope?: string` - OAuth scope
129
+ - `onSuccess?: (user: UserInfo) => void` - Callback при успешном входе
130
+ - `onError?: (error: Error) => void` - Callback при ошибке
131
+ - `className?: string` - Дополнительные CSS классы
132
+ - `children?: ReactNode` - Кастомный текст кнопки
133
+ - `variant?: 'primary' | 'secondary'` - Вариант стиля
134
+
135
+ ### createLoginButton (Vanilla JS)
136
+
137
+ Функция для создания кнопки входа без React.
138
+
139
+ #### Параметры
140
+
141
+ - `config: LoginButtonConfig` - Конфигурация кнопки
142
+ - `container: HTMLElement` - DOM элемент для размещения кнопки
143
+
144
+ #### Возвращает
145
+
146
+ Объект с методами:
147
+ - `destroy()` - Удаление кнопки из DOM
148
+ - `update(config: Partial<LoginButtonConfig>)` - Обновление конфигурации
149
+
150
+ ## Типы
151
+
152
+ ```typescript
153
+ interface UserInfo {
154
+ id: number;
155
+ email: string;
156
+ name?: string;
157
+ phone?: string;
158
+ is_active?: boolean;
159
+ created_at?: string;
160
+ updated_at?: string;
161
+ }
162
+
163
+ interface TokenResponse {
164
+ access_token: string;
165
+ refresh_token?: string;
166
+ token_type: string;
167
+ expires_in: number;
168
+ scope?: string;
169
+ }
170
+ ```
171
+
172
+ ## Примеры
173
+
174
+ ### Полный пример с обработкой callback
175
+
176
+ ```tsx
177
+ import { useState, useEffect } from 'react';
178
+ import { LoginButton, NIIDClient } from '@niid/sdk/react';
179
+ import '@niid/sdk/styles';
180
+
181
+ function App() {
182
+ const [user, setUser] = useState(null);
183
+ const [client, setClient] = useState<NIIDClient | null>(null);
184
+
185
+ useEffect(() => {
186
+ const niidClient = new NIIDClient({
187
+ clientId: 'your-client-id',
188
+ apiUrl: 'http://localhost:11700',
189
+ ssoUrl: 'http://localhost:11706'
190
+ });
191
+ setClient(niidClient);
192
+
193
+ // Обработка callback после редиректа
194
+ const handleCallback = async () => {
195
+ const urlParams = new URLSearchParams(window.location.search);
196
+ if (urlParams.get('code')) {
197
+ try {
198
+ const userInfo = await niidClient.handleCallback();
199
+ setUser(userInfo);
200
+ } catch (error) {
201
+ console.error('Failed to handle callback:', error);
202
+ }
203
+ }
204
+ };
205
+
206
+ handleCallback();
207
+ }, []);
208
+
209
+ return (
210
+ <div>
211
+ {user ? (
212
+ <div>
213
+ <p>Welcome, {user.email}!</p>
214
+ <button onClick={() => {
215
+ client?.logout();
216
+ setUser(null);
217
+ }}>Logout</button>
218
+ </div>
219
+ ) : (
220
+ <LoginButton
221
+ clientId="your-client-id"
222
+ onSuccess={(user) => setUser(user)}
223
+ onError={(error) => console.error(error)}
224
+ />
225
+ )}
226
+ </div>
227
+ );
228
+ }
229
+ ```
230
+
231
+ ## Стили
232
+
233
+ SDK включает готовые стили кнопки в стиле SSO flow. Для их использования:
234
+
235
+ ### React
236
+
237
+ ```tsx
238
+ import '@niid/sdk/styles';
239
+ ```
240
+
241
+ ### Vanilla JS
242
+
243
+ ```html
244
+ <link rel="stylesheet" href="node_modules/@niid/sdk/dist/styles/button.css">
245
+ ```
246
+
247
+ ## Безопасность
248
+
249
+ - SDK автоматически генерирует и проверяет `state` параметр для защиты от CSRF атак
250
+ - Токены хранятся в `localStorage` (для публичных клиентов) или могут быть настроены для использования `httpOnly` cookies (требует дополнительной настройки на backend)
251
+ - Access token автоматически обновляется перед истечением срока действия
252
+ - Refresh token используется для автоматического обновления access token при истечении
253
+
254
+ ## Лицензия
255
+
256
+ MIT
257
+
@@ -0,0 +1,5 @@
1
+ import { default as React } from 'react';
2
+ import { LoginButtonProps } from '../types';
3
+
4
+ export declare const LoginButton: React.FC<LoginButtonProps>;
5
+ //# sourceMappingURL=LoginButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginButton.d.ts","sourceRoot":"","sources":["../../src/components/LoginButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAGhE,OAAO,EAAE,gBAAgB,EAAY,MAAM,UAAU,CAAC;AACtD,OAAO,sBAAsB,CAAC;AAE9B,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAiFlD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { LoginButtonConfig, LoginButtonInstance } from '../types';
2
+
3
+ export declare function createLoginButton(config: LoginButtonConfig, container: HTMLElement): LoginButtonInstance;
4
+ //# sourceMappingURL=LoginButton.vanilla.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginButton.vanilla.d.ts","sourceRoot":"","sources":["../../src/components/LoginButton.vanilla.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAY,MAAM,UAAU,CAAC;AAC5E,OAAO,sBAAsB,CAAC;AAE9B,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,iBAAiB,EACzB,SAAS,EAAE,WAAW,GACrB,mBAAmB,CA4LrB"}
@@ -0,0 +1,18 @@
1
+ import { NIIDConfig, UserInfo } from '../types';
2
+
3
+ export declare class NIIDClient {
4
+ private config;
5
+ private tokenManager;
6
+ private oauthFlow;
7
+ private apiClient;
8
+ constructor(config: NIIDConfig);
9
+ login(redirectUri?: string, scope?: string): void;
10
+ handleCallback(): Promise<UserInfo | null>;
11
+ getUserInfo(): Promise<UserInfo>;
12
+ refreshToken(): Promise<void>;
13
+ logout(): void;
14
+ isAuthenticated(): boolean;
15
+ getAccessToken(): string | null;
16
+ private setupTokenRefresh;
17
+ }
18
+ //# sourceMappingURL=NIIDClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NIIDClient.d.ts","sourceRoot":"","sources":["../../src/core/NIIDClient.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAiB,MAAM,UAAU,CAAC;AAK/D,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,SAAS,CAAgB;gBAErB,MAAM,EAAE,UAAU;IA0B9B,KAAK,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IAU3C,cAAc,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAmC1C,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IA+DhC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAenC,MAAM,IAAI,IAAI;IAId,eAAe,IAAI,OAAO;IAI1B,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B,OAAO,CAAC,iBAAiB;CAU1B"}
@@ -0,0 +1,15 @@
1
+ import { NIIDConfig, TokenResponse } from '../types';
2
+
3
+ export declare class OAuthFlow {
4
+ private config;
5
+ private apiClient;
6
+ private stateStorageKey;
7
+ constructor(config: NIIDConfig);
8
+ initiateLogin(): void;
9
+ exchangeCodeForToken(code: string, state?: string): Promise<TokenResponse>;
10
+ refreshAccessToken(refreshToken: string): Promise<TokenResponse>;
11
+ private saveState;
12
+ private getState;
13
+ private clearState;
14
+ }
15
+ //# sourceMappingURL=OAuthFlow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OAuthFlow.d.ts","sourceRoot":"","sources":["../../src/core/OAuthFlow.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGrD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,eAAe,CAAS;gBAEpB,MAAM,EAAE,UAAU;IAqB9B,aAAa,IAAI,IAAI;IAef,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA+B1E,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAoBtE,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,QAAQ;IAYhB,OAAO,CAAC,UAAU;CASnB"}
@@ -0,0 +1,19 @@
1
+ import { TokenResponse } from '../types';
2
+
3
+ export declare class TokenManager {
4
+ private storage;
5
+ private accessTokenKey;
6
+ private refreshTokenKey;
7
+ private refreshTimer;
8
+ constructor(storageKey?: string);
9
+ setTokens(tokenResponse: TokenResponse): void;
10
+ getAccessToken(): string | null;
11
+ getRefreshToken(): string | null;
12
+ isTokenValid(token: string | null): boolean;
13
+ isAccessTokenValid(): boolean;
14
+ getTokenExpiration(token: string): number | null;
15
+ scheduleTokenRefresh(accessToken: string, onRefresh?: () => void): void;
16
+ clearRefreshTimer(): void;
17
+ clearTokens(): void;
18
+ }
19
+ //# sourceMappingURL=TokenManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenManager.d.ts","sourceRoot":"","sources":["../../src/core/TokenManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,aAAa,EAAE,MAAM,UAAU,CAAC;AAErD,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,YAAY,CAA8C;gBAEtD,UAAU,GAAE,MAAe;IAMvC,SAAS,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI;IAQ7C,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO;IAY3C,kBAAkB,IAAI,OAAO;IAK7B,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAShD,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI;IAmBvE,iBAAiB,IAAI,IAAI;IAOzB,WAAW,IAAI,IAAI;CAKpB"}
@@ -0,0 +1,5 @@
1
+ export { NIIDClient } from './core/NIIDClient';
2
+ export { TokenManager } from './core/TokenManager';
3
+ export { OAuthFlow } from './core/OAuthFlow';
4
+ export * from './types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,cAAc,SAAS,CAAC"}