@seaverse/auth-sdk 0.3.9 → 0.4.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 CHANGED
@@ -98,6 +98,31 @@ console.log('Health:', health);
98
98
 
99
99
  当你的应用被嵌入到 iframe 中时,可以使用 `getIframeToken()` 方法从父页面获取认证 token。这对于第三方登录重定向场景特别有用。
100
100
 
101
+ #### 检查是否在 iframe 中运行
102
+
103
+ 在调用 iframe 相关方法前,建议先检查应用是否在 iframe 中运行:
104
+
105
+ ```typescript
106
+ import { SeaVerseBackendAPIClient } from '@seaverse/auth-sdk';
107
+
108
+ // 方式 1: 使用静态方法(无需 client 实例)
109
+ if (SeaVerseBackendAPIClient.isInIframe()) {
110
+ console.log('应用正在 iframe 中运行');
111
+ } else {
112
+ console.log('应用不在 iframe 中运行');
113
+ }
114
+
115
+ // 方式 2: 使用实例方法
116
+ const client = new SeaVerseBackendAPIClient({
117
+ appId: 'your app id',
118
+ });
119
+
120
+ if (client.isInIframe()) {
121
+ console.log('应用正在 iframe 中运行');
122
+ // 可以安全地调用 getIframeToken()
123
+ }
124
+ ```
125
+
101
126
  #### 子页面 (iframe 内) 使用方式
102
127
 
103
128
  ```typescript
@@ -107,23 +132,29 @@ const client = new SeaVerseBackendAPIClient({
107
132
  appId: 'your app id',
108
133
  });
109
134
 
110
- // iframe 中请求父页面的 token
111
- try {
112
- const token = await client.getIframeToken({
113
- timeout: 10000 // 可选,默认 30 秒
114
- });
135
+ // 先检查是否在 iframe
136
+ if (!client.isInIframe()) {
137
+ console.log('应用不在 iframe 中,跳过 token 获取');
138
+ // 可以使用其他登录方式
139
+ } else {
140
+ // 在 iframe 中请求父页面的 token
141
+ try {
142
+ const token = await client.getIframeToken({
143
+ timeout: 10000 // 可选,默认 30 秒
144
+ });
115
145
 
116
- // 设置 token 到 client
117
- client.setToken(token);
118
- localStorage.setItem('token', token);
146
+ // 设置 token 到 client
147
+ client.setToken(token);
148
+ localStorage.setItem('token', token);
119
149
 
120
- console.log('成功从父页面获取 token');
150
+ console.log('成功从父页面获取 token');
121
151
 
122
- // 现在可以使用需要认证的 API
123
- const user = await client.getCurrentUser();
124
- console.log('当前用户:', user);
125
- } catch (error) {
126
- console.error('获取 token 失败:', error);
152
+ // 现在可以使用需要认证的 API
153
+ const user = await client.getCurrentUser();
154
+ console.log('当前用户:', user);
155
+ } catch (error) {
156
+ console.error('获取 token 失败:', error);
157
+ }
127
158
  }
128
159
  ```
129
160
 
@@ -172,6 +203,14 @@ const client = new SeaVerseBackendAPIClient({
172
203
  });
173
204
 
174
205
  async function initIframeApp() {
206
+ // 0. 检查是否在 iframe 中
207
+ if (!client.isInIframe()) {
208
+ console.log('应用不在 iframe 中,使用常规登录流程');
209
+ // 使用常规登录流程
210
+ showLoginForm();
211
+ return;
212
+ }
213
+
175
214
  try {
176
215
  // 1. 尝试从父页面获取 token
177
216
  const token = await client.getIframeToken();
@@ -1152,6 +1191,7 @@ SDK支持以下环境:
1152
1191
  | `forgotPassword()` | `{ email, frontend_url? }` | `SuccessResponse` | 忘记密码,frontend_url 默认为 window.location.href |
1153
1192
  | `resetPassword()` | `{ token, new_password }` | `SuccessResponse` | 重置密码 |
1154
1193
  | `setToken()` | `token: string` | `void` | 设置认证 token(OAuth 登录后使用) |
1194
+ | `isInIframe()` | - | `boolean` | 检查应用是否在 iframe 中运行(支持静态方法和实例方法) |
1155
1195
  | `getIframeToken()` | `{ timeout? }` | `Promise<string>` | 从父页面获取 token(仅 iframe 场景),timeout 默认 30000ms |
1156
1196
  | `getApiServiceToken()` | - | `ApiServiceTokenResponse` | 获取API Token |
1157
1197
 
package/dist/index.cjs CHANGED
@@ -1285,6 +1285,51 @@ class SeaVerseBackendAPIClient {
1285
1285
  // Update the httpClient's auth
1286
1286
  this.httpClient.auth = auth;
1287
1287
  }
1288
+ /**
1289
+ * Check if the application is running inside an iframe
1290
+ * This is a utility method to detect iframe context before calling iframe-specific methods
1291
+ *
1292
+ * @returns true if running in an iframe, false otherwise
1293
+ *
1294
+ * @example
1295
+ * // Check if in iframe before requesting token
1296
+ * if (client.isInIframe()) {
1297
+ * const token = await client.getIframeToken();
1298
+ * client.setToken(token);
1299
+ * } else {
1300
+ * console.log('Not running in an iframe');
1301
+ * }
1302
+ *
1303
+ * @example
1304
+ * // Use as a static method without client instance
1305
+ * if (SeaVerseBackendAPIClient.isInIframe()) {
1306
+ * console.log('Application is embedded in an iframe');
1307
+ * }
1308
+ */
1309
+ static isInIframe() {
1310
+ // Only works in browser environment
1311
+ if (typeof window === 'undefined') {
1312
+ return false;
1313
+ }
1314
+ // Check if window.self is not equal to window.top
1315
+ // This is the standard way to detect if running in an iframe
1316
+ try {
1317
+ return window.self !== window.top;
1318
+ }
1319
+ catch (e) {
1320
+ // If we get a SecurityError (cross-origin iframe), we're definitely in an iframe
1321
+ return true;
1322
+ }
1323
+ }
1324
+ /**
1325
+ * Instance method to check if running in an iframe
1326
+ * Calls the static method for convenience
1327
+ *
1328
+ * @returns true if running in an iframe, false otherwise
1329
+ */
1330
+ isInIframe() {
1331
+ return SeaVerseBackendAPIClient.isInIframe();
1332
+ }
1288
1333
  /**
1289
1334
  * Get token from parent window via iframe communication
1290
1335
  * This method is designed for scenarios where the application is embedded in an iframe
@@ -1330,7 +1375,7 @@ class SeaVerseBackendAPIClient {
1330
1375
  return Promise.reject(new Error('getIframeToken() can only be used in browser environment'));
1331
1376
  }
1332
1377
  // Check if we're in an iframe
1333
- if (window.self === window.top) {
1378
+ if (!this.isInIframe()) {
1334
1379
  return Promise.reject(new Error('getIframeToken() can only be used inside an iframe'));
1335
1380
  }
1336
1381
  const timeout = options?.timeout || 30000; // Default 30 seconds