@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 +257 -0
- package/dist/components/LoginButton.d.ts +5 -0
- package/dist/components/LoginButton.d.ts.map +1 -0
- package/dist/components/LoginButton.vanilla.d.ts +4 -0
- package/dist/components/LoginButton.vanilla.d.ts.map +1 -0
- package/dist/core/NIIDClient.d.ts +18 -0
- package/dist/core/NIIDClient.d.ts.map +1 -0
- package/dist/core/OAuthFlow.d.ts +15 -0
- package/dist/core/OAuthFlow.d.ts.map +1 -0
- package/dist/core/TokenManager.d.ts +19 -0
- package/dist/core/TokenManager.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2955 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +4 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +192 -0
- package/dist/react.js.map +1 -0
- package/dist/styles/button.css +1 -0
- package/dist/types/index.d.ts +64 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/storage.d.ts +9 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/validation.d.ts +6 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/vanilla.d.ts +4 -0
- package/dist/vanilla.d.ts.map +1 -0
- package/dist/vanilla.js +163 -0
- package/dist/vanilla.js.map +1 -0
- package/package.json +72 -0
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 @@
|
|
|
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 @@
|
|
|
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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|