@qidcloud/sdk 1.2.2 → 1.2.3

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
@@ -21,30 +21,107 @@ const qid = new QidCloud({
21
21
 
22
22
  ---
23
23
 
24
- ## 🛡️ Identity & Auth (`qid.auth`)
24
+ ## ⚠️ Prerequisite: CORS Configuration
25
25
 
26
- ### `createSession()`
27
- Initializes a new PQC handshake session for QR login.
28
- - **Returns**: `Promise<{ sessionId: string, qrData: string, expiresAt: number }>`
29
- ```typescript
30
- const { sessionId, qrData } = await qid.auth.createSession();
26
+ Before using the SDK, you **must whitelist your application's domain** in the QidCloud Console.
27
+ 1. Go to **Settings > Security**.
28
+ 2. Add your app's URL (e.g., `http://localhost:5173` or `https://myapp.com`) to the **Allowed Origins** list.
29
+ 3. Without this, browser requests will be blocked by CORS policy.
30
+
31
+ ---
32
+
33
+ ## 🛡️ Authentication Guide
34
+
35
+ QidCloud uses a **Post-Quantum Cryptography (PQC)** handshake for authentication. Users strictly log in by scanning a QR code with their QidCloud Mobile App. **Password entry is NOT supported** in the SDK to ensure credentials never touch the client device.
36
+
37
+ ### 1. Recommended: Using `QidCloudLogin` Component
38
+ The easiest way to implement secure login.
39
+ ```tsx
40
+ import { QidCloud, QidCloudLogin } from '@qidcloud/sdk';
41
+
42
+ const sdk = new QidCloud({
43
+ apiKey: 'your_api_key',
44
+ tenantId: 'your_project_id'
45
+ });
46
+
47
+ function App() {
48
+ return (
49
+ <QidCloudLogin
50
+ sdk={sdk}
51
+ onSuccess={(user, token) => {
52
+ console.log('Logged in:', user);
53
+ // Token is also automatically cached in localStorage by the component
54
+ }}
55
+ onError={(err) => console.error(err)}
56
+ />
57
+ );
58
+ }
31
59
  ```
32
60
 
33
- ### `getProfile(token)`
34
- Verifies a session token and retrieves the user profile.
35
- - **Returns**: `Promise<QidUser>`
36
- ```typescript
37
- const user = await qid.auth.getProfile(sessionToken);
61
+ ### 2. Custom UI: Using `useQidAuth` Hook
62
+ For building your own UI while keeping the SDK's state management.
63
+ ```tsx
64
+ import { useQidAuth } from '@qidcloud/sdk';
65
+
66
+ function CustomLogin() {
67
+ const {
68
+ login, // Generates QR and starts polling
69
+ session, // Contains { qrData } to display
70
+ user, // Populated on success
71
+ logout
72
+ } = useQidAuth(sdk);
73
+
74
+ if (user) return <button onClick={logout}>Logout {user.username}</button>;
75
+
76
+ return (
77
+ <div>
78
+ <button onClick={login}>Generate QR</button>
79
+ {session && <QRCode value={session.qrData} />}
80
+ </div>
81
+ );
82
+ }
38
83
  ```
39
84
 
40
- ### `listen(sessionId, onAuthorized, onDenied?)`
41
- Listen for real-time authorization events via WebSocket.
42
- ```typescript
43
- qid.auth.listen(sessionId,
44
- (token) => console.log('Authenticated:', token),
45
- (error) => console.error('Denied:', error)
46
- );
85
+ ### 3. Raw Implementation (No SDK)
86
+ If you prefer to hit the endpoints directly:
87
+ 1. **Create Session**: `POST /api/auth/session` (Headers: `x-api-key`, `x-tenant-id`) -> Returns `sessionId`, `qrData`.
88
+ 2. **Display QR**: Render `qrData` as a QR code.
89
+ 3. **Listen (Socket/Poll)**: Connect to `socket.io` specific to `sessionId` OR poll status.
90
+ 4. **Exchange**: When mobile app confirms, server sends auth token.
91
+ 5. **Get Profile**: `GET /api/me` (Header: `Authorization: Bearer <token>`).
92
+
93
+ ### 📱 Mobile-to-Mobile (App-to-App) Auth
94
+ If you are building a mobile application that needs to authenticate users via the QidCloud Mobile App:
95
+
96
+ 1. **Initiate**: Call `sdk.auth.createSession()` to get a `sessionId`.
97
+ 2. **Deep Link**: Construct a deep link to the QidCloud app using the following format:
98
+ ```
99
+ qidcloud://authorize?data=<JSON_PAYLOAD>&callback=<YOUR_APP_SCHEME>
100
+ ```
101
+ - **data**: URL-encoded JSON containing `{ "sessionId": "..." }`.
102
+ - **callback**: Your app's deep link scheme (e.g., `myapp://auth-callback`).
103
+ 3. **Handle Callback**: The QidCloud app will redirect back to your callback URL with status results:
104
+ - **Success**: `myapp://auth-callback?status=accepted&userId=<APPROVER_ID>`
105
+ - **Rejection**: `myapp://auth-callback?status=rejected`
106
+ 4. **Finalize**: Your app should listen for the `authenticated` event on the socket (as shown in Step 2) to receive the final session token.
107
+
108
+ ---
109
+ ### 🔐 Session Management
110
+ - **Persistence**: The SDK automatically caches the token in `localStorage` under `qid_auth_token`.
111
+ - **Restoration**: On page load, `useQidAuth` checks for this token and verifies it via `/api/me`.
112
+ - **Expiry**: Tokens expire after **1 hour of inactivity**. The backend implements a sliding window, so active sessions automatically extend their validity. Handle 401 errors by calling `logout()`.
113
+
114
+ ### 🚪 Logout Handling
115
+ Always use the SDK's `logout()` method to preventing "ghost sessions".
116
+ ```tsx
117
+ const { logout } = useQidAuth(sdk);
118
+ // ...
119
+ <button onClick={logout}>Sign Out</button>
47
120
  ```
121
+ **What `logout()` does:**
122
+ 1. Calls `POST /api/logout` to invalidate the session on the server.
123
+ 2. Removes the token from `localStorage`.
124
+ 3. Clears in-memory state.
48
125
 
49
126
  ---
50
127
 
@@ -127,6 +204,19 @@ const logs = await qid.logs.fetch({ limit: 50, level: 'error' });
127
204
 
128
205
  ---
129
206
 
207
+
208
+ ---
209
+
210
+ ## ✅ Production Readiness Checklist
211
+
212
+ To ensure a secure and robust integration, verify the following before going live:
213
+
214
+ - [ ] **HTTPS Only**: Ensure your application is served over HTTPS. The SDK's cryptographic features (and many browser security APIs) require a secure context.
215
+ - [ ] **Environment Variables**: Store your `apiKey` and `tenantId` in environment variables (e.g., `VITE_QID_API_KEY`) ensuring they are not hardcoded in version control.
216
+ - [ ] **Error Boundaries**: Wrap the `QidCloudLogin` component in a React Error Boundary to gracefully handle any unexpected runtime failures.
217
+ - [ ] **Strict Mode**: If using React Strict Mode, ensure your `useEffect` logic handles double-invocation (The SDK's hooks are already optimized for this).
218
+ - [ ] **CORS**: Double-check that all your production domains (including `www` and non-`www`) are whitelisted in the QidCloud Console.
219
+
130
220
  ## ⚛️ React Helpers
131
221
 
132
222
  ### `useQidAuth(sdk)`
@@ -140,3 +230,28 @@ Pre-built component for PQC login.
140
230
  ```tsx
141
231
  <QidSignInButton sdk={qid} onSuccess={(user) => console.log(user)} />
142
232
  ```
233
+
234
+ ---
235
+
236
+ ## ❓ Troubleshooting
237
+
238
+ ### "Invalid hook call" after linking the SDK locally
239
+ If you are developing the SDK locally and linking it to your project (via `npm link` or `npm install ../sdk-path`), you might encounter an "Invalid hook call" error. This is usually caused by **Duplicate React** (the app and the SDK are using different React instances).
240
+
241
+ **Solution for Vite projects:**
242
+ Add `resolve.dedupe` to your `vite.config.ts` to force both your app and the SDK to share the same React instance.
243
+
244
+ ```typescript
245
+ // vite.config.ts
246
+ import { defineConfig } from 'vite'
247
+
248
+ export default defineConfig({
249
+ // ... rest of config
250
+ resolve: {
251
+ dedupe: ['react', 'react-dom']
252
+ }
253
+ })
254
+ ```
255
+
256
+ **Manual Check:**
257
+ Ensure that the `@qidcloud/sdk` folder does NOT have a `node_modules/react` directory. If it does, delete it manually so it defers to your project's React.
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { QidCloud } from '../index';
3
+ import { QidUser } from '../types';
4
+ interface QidCloudLoginProps {
5
+ sdk: QidCloud;
6
+ onSuccess: (user: QidUser, token: string) => void;
7
+ onError?: (error: string) => void;
8
+ className?: string;
9
+ }
10
+ /**
11
+ * A comprehensive login component for QidCloud.
12
+ * STRICT SECURITY: ONLY supports QR Scanning (Mobile App) for Post-Quantum security.
13
+ * Conventional login is not available in the SDK to prevent password transmission in third-party apps.
14
+ */
15
+ export declare const QidCloudLogin: React.FC<QidCloudLoginProps>;
16
+ export {};
@@ -7,9 +7,12 @@ export interface UseQidAuthReturn {
7
7
  error: string | null;
8
8
  session: QidAuthSession | null;
9
9
  initializing: boolean;
10
+ isExpired: boolean;
11
+ timeLeft: number;
10
12
  login: () => Promise<void>;
11
13
  logout: () => void;
12
14
  cancel: () => void;
15
+ setAuthenticated: (user: QidUser, token: string) => void;
13
16
  }
14
17
  /**
15
18
  * A React hook for managing QidCloud authentication lifecycle.
package/dist/index.d.ts CHANGED
@@ -22,4 +22,5 @@ export declare class QidCloud {
22
22
  export default QidCloud;
23
23
  export * from './types';
24
24
  export { QidSignInButton } from './components/QidSignInButton';
25
+ export { QidCloudLogin } from './components/QidCloudLogin';
25
26
  export { useQidAuth } from './hooks/useQidAuth';