@55387.ai/uniauth-client 1.2.2 → 1.2.4
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 +92 -160
- package/package.json +42 -43
- package/INTEGRATION.md +0 -1273
package/README.md
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
# @55387.ai/uniauth-client
|
|
2
2
|
|
|
3
|
-
UniAuth
|
|
3
|
+
> UniAuth Frontend SDK — Phone, Email, Social & SSO login for browser apps.
|
|
4
|
+
>
|
|
5
|
+
> UniAuth 前端 SDK — 支持手机、邮箱、社交登录和跨域 SSO。
|
|
6
|
+
|
|
7
|
+
**Version / 版本:** 1.2.2
|
|
4
8
|
|
|
5
|
-
## 安装
|
|
9
|
+
## Install / 安装
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
12
|
npm install @55387.ai/uniauth-client
|
|
9
|
-
# or
|
|
13
|
+
# or / 或
|
|
10
14
|
pnpm add @55387.ai/uniauth-client
|
|
11
15
|
```
|
|
12
16
|
|
|
13
|
-
## 快速开始
|
|
17
|
+
## Quick Start / 快速开始
|
|
14
18
|
|
|
15
19
|
```typescript
|
|
16
20
|
import { UniAuthClient } from '@55387.ai/uniauth-client';
|
|
@@ -19,200 +23,133 @@ const auth = new UniAuthClient({
|
|
|
19
23
|
baseUrl: 'https://sso.55387.xyz',
|
|
20
24
|
});
|
|
21
25
|
|
|
22
|
-
//
|
|
26
|
+
// Phone login / 手机登录
|
|
23
27
|
await auth.sendCode('+8613800138000');
|
|
24
|
-
|
|
25
|
-
// 验证码登录
|
|
26
28
|
const result = await auth.loginWithCode('+8613800138000', '123456');
|
|
27
29
|
|
|
28
|
-
//
|
|
30
|
+
// Email login / 邮箱登录
|
|
31
|
+
const result = await auth.loginWithEmail('user@example.com', 'password');
|
|
32
|
+
|
|
33
|
+
// Check auth / 检查状态
|
|
29
34
|
if (auth.isAuthenticated()) {
|
|
30
35
|
const user = await auth.getCurrentUser();
|
|
31
|
-
console.log('已登录:', user);
|
|
32
36
|
}
|
|
33
37
|
```
|
|
34
38
|
|
|
35
|
-
##
|
|
39
|
+
## Login Methods / 登录方式
|
|
36
40
|
|
|
37
|
-
###
|
|
41
|
+
### 📱 Phone / 手机号
|
|
38
42
|
|
|
39
43
|
```typescript
|
|
40
|
-
auth.
|
|
41
|
-
|
|
42
|
-
clientId: 'ua_xxxxxxxxxxxx',
|
|
43
|
-
redirectUri: window.location.origin + '/callback',
|
|
44
|
-
scope: 'openid profile email phone', // 可选,默认 'openid profile email'
|
|
45
|
-
});
|
|
44
|
+
await auth.sendCode('+8613800138000');
|
|
45
|
+
const result = await auth.loginWithCode('+8613800138000', '123456');
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
###
|
|
48
|
+
### 📧 Email / 邮箱
|
|
49
49
|
|
|
50
50
|
```typescript
|
|
51
|
-
//
|
|
52
|
-
auth.
|
|
51
|
+
// Password / 密码登录
|
|
52
|
+
await auth.loginWithEmail('user@example.com', 'password');
|
|
53
53
|
|
|
54
|
-
//
|
|
55
|
-
auth.
|
|
56
|
-
|
|
54
|
+
// Passwordless / 无密码
|
|
55
|
+
await auth.sendEmailCode('user@example.com');
|
|
56
|
+
await auth.loginWithEmailCode('user@example.com', '123456');
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
// Register / 注册
|
|
59
|
+
await auth.registerWithEmail('user@example.com', 'password', 'Nickname');
|
|
60
|
+
```
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
### 🌐 Social Login / 社交登录
|
|
61
63
|
|
|
62
64
|
```typescript
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
useEffect(() => {
|
|
66
|
-
const handleCallback = async () => {
|
|
67
|
-
if (auth.isSSOCallback()) {
|
|
68
|
-
try {
|
|
69
|
-
const result = await auth.handleSSOCallback();
|
|
70
|
-
if (result) {
|
|
71
|
-
// 保存 Token
|
|
72
|
-
localStorage.setItem('access_token', result.access_token);
|
|
73
|
-
if (result.refresh_token) {
|
|
74
|
-
localStorage.setItem('refresh_token', result.refresh_token);
|
|
75
|
-
}
|
|
76
|
-
window.location.href = '/';
|
|
77
|
-
}
|
|
78
|
-
} catch (error) {
|
|
79
|
-
console.error('SSO callback error:', error);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
handleCallback();
|
|
84
|
-
}, []);
|
|
85
|
-
|
|
86
|
-
return <div>登录中...</div>;
|
|
87
|
-
}
|
|
65
|
+
const providers = await auth.getOAuthProviders(); // ['google', 'github', 'wechat']
|
|
66
|
+
auth.startSocialLogin('google');
|
|
88
67
|
```
|
|
89
68
|
|
|
90
|
-
###
|
|
91
|
-
|
|
92
|
-
`handleSSOCallback()` 成功时返回:
|
|
69
|
+
### 🔐 SSO / 单点登录
|
|
93
70
|
|
|
94
71
|
```typescript
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
refresh_token?: string; // 刷新令牌(可选)
|
|
98
|
-
expires_in?: number; // 过期时间(秒)
|
|
99
|
-
token_type: string; // 令牌类型,通常为 "Bearer"
|
|
100
|
-
id_token?: string; // OpenID Connect ID Token
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### 注意事项
|
|
72
|
+
// ⚠️ Must call configureSso() before using loginWithSSO()
|
|
73
|
+
// ⚠️ 使用 loginWithSSO() 前必须调用 configureSso()
|
|
105
74
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
75
|
+
// Configure / 配置
|
|
76
|
+
auth.configureSso({
|
|
77
|
+
ssoUrl: 'https://sso.55387.xyz',
|
|
78
|
+
clientId: 'ua_xxxxxxxxxxxx',
|
|
79
|
+
redirectUri: window.location.origin + '/callback',
|
|
80
|
+
scope: 'openid profile email phone',
|
|
81
|
+
});
|
|
109
82
|
|
|
110
|
-
|
|
83
|
+
// Login / 登录
|
|
84
|
+
auth.loginWithSSO(); // Basic
|
|
85
|
+
auth.loginWithSSO({ usePKCE: true }); // Recommended for SPAs
|
|
111
86
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
87
|
+
// Callback page / 回调页处理
|
|
88
|
+
if (auth.isSSOCallback()) {
|
|
89
|
+
const result = await auth.handleSSOCallback();
|
|
90
|
+
// result: { access_token, refresh_token?, token_type, id_token? }
|
|
91
|
+
}
|
|
92
|
+
```
|
|
117
93
|
|
|
94
|
+
> ⚠️ **Confidential Clients** must exchange tokens on the backend. See [AI Integration Guide](../../docs/AI_INTEGRATION_GUIDE.md#2b-backend-proxy-confidential-client).
|
|
95
|
+
>
|
|
96
|
+
> ⚠️ **机密客户端** 需在后端完成 Token 交换,参见 [集成指南](../../docs/AI_INTEGRATION_GUIDE.md#2b-backend-proxy-confidential-client)。
|
|
118
97
|
|
|
119
|
-
|
|
98
|
+
### 🔑 MFA / 多因素认证
|
|
120
99
|
|
|
121
100
|
```typescript
|
|
122
101
|
const result = await auth.loginWithCode(phone, code);
|
|
123
|
-
|
|
124
102
|
if (result.mfa_required) {
|
|
125
|
-
|
|
126
|
-
const finalResult = await auth.verifyMFA(result.mfa_token!, mfaCode);
|
|
103
|
+
await auth.verifyMFA(result.mfa_token!, '123456');
|
|
127
104
|
}
|
|
128
105
|
```
|
|
129
106
|
|
|
130
|
-
##
|
|
131
|
-
|
|
132
|
-
```typescript
|
|
133
|
-
// 获取可用的 OAuth 提供商
|
|
134
|
-
const providers = await auth.getOAuthProviders();
|
|
135
|
-
|
|
136
|
-
// 发起社交登录
|
|
137
|
-
auth.startSocialLogin('google');
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## 认证状态监听
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
const unsubscribe = auth.onAuthStateChange((user, isAuthenticated) => {
|
|
144
|
-
if (isAuthenticated) {
|
|
145
|
-
console.log('用户已登录:', user);
|
|
146
|
-
} else {
|
|
147
|
-
console.log('用户已登出');
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// 取消监听
|
|
152
|
-
unsubscribe();
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
## API 参考
|
|
107
|
+
## API Reference / API 参考
|
|
156
108
|
|
|
157
|
-
###
|
|
109
|
+
### Config / 配置
|
|
158
110
|
|
|
159
111
|
```typescript
|
|
160
112
|
interface UniAuthConfig {
|
|
161
|
-
baseUrl: string; // API
|
|
162
|
-
appKey?: string; //
|
|
163
|
-
clientId?: string; // OAuth
|
|
113
|
+
baseUrl: string; // API base URL
|
|
114
|
+
appKey?: string; // App key (optional)
|
|
115
|
+
clientId?: string; // OAuth client ID
|
|
164
116
|
storage?: 'localStorage' | 'sessionStorage' | 'memory';
|
|
165
117
|
onTokenRefresh?: (tokens) => void;
|
|
166
118
|
onAuthError?: (error) => void;
|
|
167
|
-
enableRetry?: boolean; //
|
|
168
|
-
timeout?: number; //
|
|
119
|
+
enableRetry?: boolean; // Default: true
|
|
120
|
+
timeout?: number; // Default: 30000
|
|
169
121
|
}
|
|
170
122
|
```
|
|
171
123
|
|
|
172
|
-
###
|
|
173
|
-
|
|
174
|
-
|
|
|
175
|
-
|
|
176
|
-
| `sendCode(phone, type?)` |
|
|
177
|
-
| `sendEmailCode(email, type?)` | 发送邮箱验证码 |
|
|
178
|
-
| `loginWithCode(phone, code)` | 手机验证码登录 |
|
|
179
|
-
| `loginWithEmailCode(email, code)` | 邮箱验证码登录 |
|
|
180
|
-
| `loginWithEmail(email, password)` | 邮箱密码登录 |
|
|
181
|
-
| `registerWithEmail(email, password, nickname?)` | 邮箱注册 |
|
|
182
|
-
| `verifyMFA(mfaToken, code)` | MFA 验证 |
|
|
183
|
-
| `getCurrentUser()` | 获取当前用户 |
|
|
184
|
-
| `updateProfile(updates)` |
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
|
191
|
-
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
| `getOAuthProviders()` | 获取 OAuth 提供商列表 |
|
|
202
|
-
| `startSocialLogin(provider, redirectUri?)` | 发起社交登录 |
|
|
203
|
-
|
|
204
|
-
### 状态方法
|
|
205
|
-
|
|
206
|
-
| 方法 | 说明 |
|
|
207
|
-
|------|------|
|
|
208
|
-
| `isAuthenticated()` | 检查是否已登录 |
|
|
209
|
-
| `isTokenValid()` | 检查 Token 是否有效 |
|
|
210
|
-
| `getAccessToken()` | 获取 Token (异步,自动刷新) |
|
|
211
|
-
| `getAccessTokenSync()` | 获取 Token (同步) |
|
|
212
|
-
| `getCachedUser()` | 获取缓存的用户信息 |
|
|
213
|
-
| `onAuthStateChange(callback)` | 监听认证状态变更 |
|
|
214
|
-
|
|
215
|
-
## 错误处理
|
|
124
|
+
### Methods / 方法
|
|
125
|
+
|
|
126
|
+
| Method | Description / 说明 |
|
|
127
|
+
|--------|-----------|
|
|
128
|
+
| `sendCode(phone, type?)` | Send SMS code / 发送短信验证码 |
|
|
129
|
+
| `sendEmailCode(email, type?)` | Send email code / 发送邮箱验证码 |
|
|
130
|
+
| `loginWithCode(phone, code)` | Phone code login / 手机验证码登录 |
|
|
131
|
+
| `loginWithEmailCode(email, code)` | Email code login / 邮箱验证码登录 |
|
|
132
|
+
| `loginWithEmail(email, password)` | Email password login / 邮箱密码登录 |
|
|
133
|
+
| `registerWithEmail(email, password, nickname?)` | Email register / 邮箱注册 |
|
|
134
|
+
| `verifyMFA(mfaToken, code)` | MFA verification / MFA 验证 |
|
|
135
|
+
| `getCurrentUser()` | Get current user / 获取当前用户 |
|
|
136
|
+
| `updateProfile(updates)` | Update profile / 更新资料 |
|
|
137
|
+
| `isAuthenticated()` | Check login status / 检查登录状态 |
|
|
138
|
+
| `isTokenValid()` | Check token validity / 检查令牌有效性 |
|
|
139
|
+
| `getAccessToken()` | Get token (auto-refresh) / 获取令牌(自动刷新) |
|
|
140
|
+
| `getAccessTokenSync()` | Get token (sync) / 获取令牌(同步) |
|
|
141
|
+
| `getCachedUser()` | Get cached user / 获取缓存用户 |
|
|
142
|
+
| `onAuthStateChange(cb)` | Auth state listener / 认证状态监听 |
|
|
143
|
+
| `logout()` | Logout / 登出 |
|
|
144
|
+
| `logoutAll()` | Logout all devices / 全设备登出 |
|
|
145
|
+
| `configureSso(config)` | Configure SSO / 配置 SSO |
|
|
146
|
+
| `loginWithSSO(options?)` | Start SSO login / 发起 SSO 登录 |
|
|
147
|
+
| `isSSOCallback()` | Detect SSO callback / 检测 SSO 回调 |
|
|
148
|
+
| `handleSSOCallback()` | Handle SSO callback / 处理 SSO 回调 |
|
|
149
|
+
| `getOAuthProviders()` | List OAuth providers / 获取 OAuth 提供商 |
|
|
150
|
+
| `startSocialLogin(provider)` | Start social login / 发起社交登录 |
|
|
151
|
+
|
|
152
|
+
## Error Handling / 错误处理
|
|
216
153
|
|
|
217
154
|
```typescript
|
|
218
155
|
import { UniAuthError, AuthErrorCode } from '@55387.ai/uniauth-client';
|
|
@@ -222,14 +159,9 @@ try {
|
|
|
222
159
|
} catch (error) {
|
|
223
160
|
if (error instanceof UniAuthError) {
|
|
224
161
|
switch (error.code) {
|
|
225
|
-
case AuthErrorCode.MFA_REQUIRED:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
case AuthErrorCode.VERIFY_FAILED:
|
|
229
|
-
// 验证码错误
|
|
230
|
-
break;
|
|
231
|
-
default:
|
|
232
|
-
console.error(error.message);
|
|
162
|
+
case AuthErrorCode.MFA_REQUIRED: // Need MFA / 需要 MFA
|
|
163
|
+
case AuthErrorCode.VERIFY_FAILED: // Wrong code / 验证码错误
|
|
164
|
+
case AuthErrorCode.RATE_LIMITED: // Rate limited / 频率限制
|
|
233
165
|
}
|
|
234
166
|
}
|
|
235
167
|
}
|
package/package.json
CHANGED
|
@@ -1,45 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
]
|
|
2
|
+
"name": "@55387.ai/uniauth-client",
|
|
3
|
+
"version": "1.2.4",
|
|
4
|
+
"description": "UniAuth Frontend SDK - Phone, Email, SSO login for browser",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"require": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^22.10.2",
|
|
25
|
+
"tsup": "^8.3.5",
|
|
26
|
+
"typescript": "^5.7.2",
|
|
27
|
+
"vitest": "^2.1.9"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"auth",
|
|
31
|
+
"authentication",
|
|
32
|
+
"sms",
|
|
33
|
+
"login",
|
|
34
|
+
"sdk"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
38
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"test:watch": "vitest",
|
|
41
|
+
"lint": "eslint src --ext .ts",
|
|
42
|
+
"clean": "rm -rf dist"
|
|
43
|
+
}
|
|
45
44
|
}
|