dexie-cloud-addon 4.3.0 → 4.3.2

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/oauth_flow.md CHANGED
@@ -5,7 +5,6 @@
5
5
  - **SPA** – Customer's frontend application
6
6
  - **Dexie Cloud** – Auth broker + database access control
7
7
  - **OAuth Provider** – Google, GitHub, Apple, Microsoft, etc.
8
- - **Popup Window** – Browser window initiated by the SPA
9
8
 
10
9
  ## Preconditions
11
10
 
@@ -40,36 +39,28 @@ No nonce or PKCE is created yet.
40
39
 
41
40
  Example: User selects **Google**
42
41
 
43
- The client initiates the OAuth flow. There are three ways to do this:
42
+ The client initiates the OAuth flow. There are two ways to do this:
44
43
 
45
- #### 2a. Popup Flow (Recommended for Web SPAs)
44
+ #### 2a. Full Page Redirect (Recommended for Web SPAs)
46
45
 
47
46
  ```js
48
- popup = window.open('about:blank');
49
- popup.location = `https://<db>.dexie.cloud/oauth/login/google?redirect_uri=${encodeURIComponent(window.location.origin)}`;
47
+ window.location.href = `https://<db>.dexie.cloud/oauth/login/google?redirect_uri=${encodeURIComponent(location.href)}`;
50
48
  ```
51
49
 
52
- The `redirect_uri` parameter is used to determine the `targetOrigin` for postMessage.
50
+ The `redirect_uri` parameter specifies where Dexie Cloud should redirect after authentication.
51
+ This can be any page in your app - no dedicated callback route is needed.
53
52
 
54
53
  #### 2b. Custom URL Scheme (Capacitor / Native Apps)
55
54
 
56
55
  ```js
57
56
  // Open in system browser or in-app browser
58
57
  Browser.open({
59
- url: `https://<db>.dexie.cloud/oauth/login/google?redirect_uri=${encodeURIComponent('myapp://oauth-callback')}`
58
+ url: `https://<db>.dexie.cloud/oauth/login/google?redirect_uri=${encodeURIComponent('myapp://')}`
60
59
  });
61
60
  ```
62
61
 
63
62
  The custom scheme `myapp://` tells Dexie Cloud to redirect back via deep link.
64
63
 
65
- #### 2c. Full Page Redirect (Web without Popup)
66
-
67
- ```js
68
- window.location.href = `https://<db>.dexie.cloud/oauth/login/google?redirect_uri=${encodeURIComponent('https://myapp.com/oauth-callback')}`;
69
- ```
70
-
71
- Used when popups are blocked or for a more traditional OAuth redirect flow.
72
-
73
64
  ---
74
65
 
75
66
  ### 3. Dexie Cloud Prepares OAuth
@@ -80,7 +71,7 @@ Dexie Cloud receives `/oauth/login/google` and generates:
80
71
  - `code_verifier` (PKCE)
81
72
  - `code_challenge` (PKCE)
82
73
 
83
- Stores these in the challenges table, then redirects popup to provider:
74
+ Stores these in the challenges table, then redirects the browser to provider:
84
75
 
85
76
  ```
86
77
  https://accounts.google.com/o/oauth2/v2/auth?
@@ -105,7 +96,7 @@ Provider authenticates the user and requests consent if needed.
105
96
 
106
97
  ### 5. Provider Callback to Dexie Cloud
107
98
 
108
- Provider redirects back to popup:
99
+ Provider redirects back to Dexie Cloud:
109
100
 
110
101
  ```
111
102
  https://<db>.dexie.cloud/oauth/callback/google?code=CODE&state=STATE
@@ -125,97 +116,115 @@ Dexie Cloud:
125
116
 
126
117
  ### 6. Dexie Cloud Delivers Auth Code to Client
127
118
 
128
- Dexie Cloud returns HTML that delivers the authorization code back to the client.
129
- The delivery method depends on how the client initiated the login:
119
+ Dexie Cloud issues an HTTP 302 redirect back to the client with the authorization code.
120
+ The auth data is encapsulated in a single `dxc-auth` query parameter containing base64url-encoded JSON.
121
+ This avoids collisions with the app's own query parameters.
130
122
 
131
- #### 6a. Popup Flow (Web SPAs)
123
+ #### 6a. Full Page Redirect (Web SPAs)
132
124
 
133
- If `window.opener` exists, uses postMessage:
125
+ If the client passed an http/https `redirect_uri`, Dexie Cloud redirects:
134
126
 
135
- ```js
136
- window.opener.postMessage(
137
- {
138
- type: 'dexie:oauthResult',
139
- code: DEXIE_AUTH_CODE,
140
- provider: 'google',
141
- state: STATE
142
- },
143
- targetOrigin // Origin captured from redirect_uri or referer
144
- );
145
-
146
- window.close();
127
+ ```
128
+ HTTP/1.1 302 Found
129
+ Location: https://myapp.com/?dxc-auth=eyJjb2RlIjoiLi4uIiwicHJvdmlkZXIiOiJnb29nbGUiLCJzdGF0ZSI6Ii4uLiJ9
147
130
  ```
148
131
 
149
- #### 6b. Custom URL Scheme (Capacitor / Native Apps)
132
+ The `dxc-auth` parameter contains base64url-encoded JSON:
133
+
134
+ ```json
135
+ { "code": "DEXIE_AUTH_CODE", "provider": "google", "state": "STATE" }
136
+ ```
150
137
 
151
- If the client passed a `redirect_uri` with a custom scheme (e.g., `myapp://oauth-callback`),
152
- the callback page redirects to that URL:
138
+ Or in case of error:
153
139
 
154
- ```js
155
- window.location.href =
156
- 'myapp://oauth-callback?code=DEXIE_AUTH_CODE&provider=google&state=STATE';
140
+ ```json
141
+ { "error": "Error message", "provider": "google", "state": "STATE" }
157
142
  ```
158
143
 
159
- The native app intercepts this deep link and extracts the parameters.
144
+ The app doesn't need a dedicated OAuth callback route - the dexie-cloud client library
145
+ detects and processes the `dxc-auth` parameter on any page load.
160
146
 
161
- #### 6c. Full Page Redirect (Web without Popup)
147
+ #### 6b. Custom URL Scheme (Capacitor / Native Apps)
162
148
 
163
- If there's no `window.opener` but the client passed an http/https `redirect_uri`,
164
- the callback page redirects back to the client URL:
149
+ If the client passed a `redirect_uri` with a custom scheme (e.g., `myapp://`),
150
+ Dexie Cloud redirects to that URL with the same `dxc-auth` parameter:
165
151
 
166
- ```js
167
- window.location.href =
168
- 'https://myapp.com/oauth-callback?code=DEXIE_AUTH_CODE&provider=google&state=STATE';
152
+ ```
153
+ HTTP/1.1 302 Found
154
+ Location: myapp://?dxc-auth=eyJjb2RlIjoiLi4uIiwicHJvdmlkZXIiOiJnb29nbGUiLCJzdGF0ZSI6Ii4uLiJ9
169
155
  ```
170
156
 
171
- The client page at that URL handles the auth code from query parameters.
157
+ The native app intercepts this deep link and decodes the parameter.
172
158
 
173
- #### 6d. Error Case
159
+ #### 6c. Error Case
174
160
 
175
- If none of the above conditions are met (no opener, no redirect_uri), an error is displayed
161
+ If no valid `redirect_uri` was provided, an error page is displayed
176
162
  explaining that the auth flow cannot complete.
177
163
 
178
164
  ---
179
165
 
180
166
  ### 7. Client Receives Authorization Code
181
167
 
182
- **For Popup Flow (6a):**
168
+ **For Full Page Redirect (6a):**
183
169
 
184
- SPA listens for postMessage and verifies:
170
+ The `dexie-cloud-addon` library handles OAuth callback detection automatically:
185
171
 
186
- - `type === "dexie:oauthResult"`
187
- - origin (implicit via postMessage)
188
- - provider
189
- - state (optional)
190
- - popup lifecycle
172
+ 1. When `db.cloud.configure()` is called, the addon checks for the `dxc-auth` query parameter
173
+ 2. This check only runs in DOM environments (not in Web Workers)
174
+ 3. If the parameter is present:
175
+ - The URL is immediately cleaned up using `history.replaceState()` to remove `dxc-auth`
176
+ - A `setTimeout(cb, 0)` is scheduled to initiate the token exchange
177
+ - The token exchange fetches from the configured `databaseUrl`
178
+ - The response is processed in the existing `db.on('ready')` callback when Dexie is ready
179
+
180
+ ```js
181
+ // Pseudocode for dexie-cloud-addon implementation
182
+ function configure(options) {
183
+ // Only check in DOM environment, not workers
184
+ if (typeof window !== 'undefined' && window.location) {
185
+ const encoded = new URLSearchParams(location.search).get('dxc-auth');
186
+ if (encoded) {
187
+ // Decode base64url (unpadded) to JSON
188
+ const padded = encoded + '='.repeat((4 - (encoded.length % 4)) % 4);
189
+ const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
190
+ const payload = JSON.parse(atob(base64));
191
+ const { code, provider, state, error } = payload;
192
+
193
+ // Clean up URL immediately (remove dxc-auth param)
194
+ const url = new URL(location.href);
195
+ url.searchParams.delete('dxc-auth');
196
+ history.replaceState(null, '', url.toString());
197
+
198
+ if (!error) {
199
+ // Schedule token exchange (processed in db.on('ready'))
200
+ setTimeout(() => {
201
+ // Perform token exchange with options.databaseUrl
202
+ }, 0);
203
+ }
204
+ }
205
+ }
206
+ }
207
+ ```
191
208
 
192
209
  **For Capacitor/Native Apps (6b):**
193
210
 
194
- App registers a deep link handler for the custom URL scheme:
211
+ App registers a deep link handler and decodes the same parameter:
195
212
 
196
213
  ```js
197
214
  // Capacitor example
198
215
  App.addListener('appUrlOpen', ({ url }) => {
199
- const params = new URL(url).searchParams;
200
- const code = params.get('code');
201
- const provider = params.get('provider');
202
- const state = params.get('state');
203
- // Proceed to token exchange
216
+ const parsedUrl = new URL(url);
217
+ const encoded = parsedUrl.searchParams.get('dxc-auth');
218
+ if (encoded) {
219
+ const padded = encoded + '='.repeat((4 - (encoded.length % 4)) % 4);
220
+ const base64 = padded.replace(/-/g, '+').replace(/_/g, '/');
221
+ const payload = JSON.parse(atob(base64));
222
+ const { code, provider, state, error } = payload;
223
+ // Proceed to token exchange
224
+ }
204
225
  });
205
226
  ```
206
227
 
207
- **For Full Page Redirect (6c):**
208
-
209
- Client page reads parameters from the URL:
210
-
211
- ```js
212
- const params = new URLSearchParams(window.location.search);
213
- const code = params.get('code');
214
- const provider = params.get('provider');
215
- const state = params.get('state');
216
- // Proceed to token exchange
217
- ```
218
-
219
228
  Upon success, client proceeds to token exchange.
220
229
 
221
230
  ---
@@ -270,8 +279,7 @@ This completes authentication.
270
279
 
271
280
  ## Security Properties Achieved
272
281
 
273
- - 🛑 No JWTs exposed via popup or URL
274
- - 🛑 No refresh tokens in postMessage
282
+ - 🛑 No JWTs exposed via URL fragments
275
283
  - 🛑 Provider tokens never reach SPA (only Dexie tokens)
276
284
  - 🛡 Single-use Dexie authorization code (5 min TTL)
277
285
  - 🛡 PKCE prevents provider code interception
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dexie-cloud-addon",
3
- "version": "4.3.0",
3
+ "version": "4.3.2",
4
4
  "description": "Dexie addon that syncs with to Dexie Cloud",
5
5
  "type": "module",
6
6
  "module": "dist/modern/dexie-cloud-addon.min.js",
@@ -94,8 +94,8 @@
94
94
  "rxjs": "^7.x",
95
95
  "yjs": "^13.6.27",
96
96
  "y-protocols": "^1.0.6",
97
- "y-dexie": "^4.2.2",
98
- "dexie-cloud-common": "^1.0.57"
97
+ "dexie-cloud-common": "^1.0.57",
98
+ "y-dexie": "^4.2.2"
99
99
  },
100
100
  "peerDependencies": {
101
101
  "dexie": "^4.3.0"