@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 +133 -18
- package/dist/components/QidCloudLogin.d.ts +16 -0
- package/dist/hooks/useQidAuth.d.ts +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +220 -1913
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +220 -1914
- package/dist/index.mjs.map +1 -1
- package/dist/modules/auth.d.ts +4 -0
- package/package.json +5 -3
- package/src/components/QidCloudLogin.tsx +64 -0
- package/src/components/QidSignInButton.tsx +92 -6
- package/src/hooks/useQidAuth.ts +94 -19
- package/src/index.ts +1 -0
- package/src/modules/auth.ts +32 -3
package/README.md
CHANGED
|
@@ -21,30 +21,107 @@ const qid = new QidCloud({
|
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
-
##
|
|
24
|
+
## ⚠️ Prerequisite: CORS Configuration
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
### `
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
###
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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';
|