@makefully/adaptfully 5.0.4 → 5.0.6

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/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project are documented in this file.
4
4
 
5
+ ## 5.0.6 — 2026-10-07
6
+
7
+ ### Changed
8
+
9
+ - **`google-auth`** persists the GIS access token in **`localStorage`** by default (was `sessionStorage`), so web sign-in survives browser restarts until explicit logout or Google silent reauth fails. Opt back into tab-only tokens with `config.googleTokenStorage: 'sessionStorage'`. Existing `sessionStorage` tokens are migrated once on read.
10
+
11
+ ## 5.0.5 — 2026-10-06
12
+
13
+ ### Changed
14
+
15
+ - **`social-auth`** Google login on Capacitor now passes `filterByAuthorizedAccounts: false` (Capgo/Family Link guidance) so Credential Manager does not stick to a stale authorized-account filter that surfaces `[16] Account reauth failed`.
16
+
5
17
  ## 5.0.4 — 2026-10-06
6
18
 
7
19
  ### Changed
package/README.md CHANGED
@@ -236,7 +236,8 @@ Optional config keys:
236
236
  | Key | Default | Purpose |
237
237
  |-----|---------|---------|
238
238
  | `googleClientId` | *(required)* | Browser GIS OAuth client id |
239
- | `googleTokenKey` | `adaptfully_google_token` | `sessionStorage` key for the access token |
239
+ | `googleTokenKey` | `adaptfully_google_token` | Storage key for the GIS access token |
240
+ | `googleTokenStorage` | `localStorage` | `localStorage` (survives browser restart) or `sessionStorage` (tab-only) |
240
241
  | `googleScopes` | `openid email profile` | OAuth scopes |
241
242
  | `autoLoginStorageKey` | `lastLoggedIn` | Storage key written with the user id on login |
242
243
 
@@ -1,4 +1,4 @@
1
- /* global google, sessionStorage, window */
1
+ /* global google, localStorage, sessionStorage, window */
2
2
 
3
3
  (function registerGoogleAuth(ns) {
4
4
  const { configValue, getStorage } = ns.auth.helpers;
@@ -6,6 +6,7 @@
6
6
  const DEFAULT_SCOPES = 'openid email profile';
7
7
  const DEFAULT_TOKEN_KEY = 'adaptfully_google_token';
8
8
  const DEFAULT_AUTO_LOGIN_KEY = 'lastLoggedIn';
9
+ const DEFAULT_TOKEN_STORAGE = 'localStorage';
9
10
 
10
11
  class GoogleAuthPlugin {
11
12
  constructor() {
@@ -32,6 +33,27 @@
32
33
  return configValue('googleTokenKey', DEFAULT_TOKEN_KEY);
33
34
  }
34
35
 
36
+ /**
37
+ * Where the GIS access token is persisted.
38
+ * Default `localStorage` so sign-in survives browser restarts until logout
39
+ * (or Google silent reauth fails). Use `sessionStorage` for tab-only tokens.
40
+ */
41
+ #tokenStorageName() {
42
+ const raw = configValue('googleTokenStorage', DEFAULT_TOKEN_STORAGE);
43
+ return raw === 'sessionStorage' ? 'sessionStorage' : 'localStorage';
44
+ }
45
+
46
+ #tokenStore() {
47
+ try {
48
+ if (this.#tokenStorageName() === 'sessionStorage') {
49
+ return typeof sessionStorage !== 'undefined' ? sessionStorage : null;
50
+ }
51
+ return typeof localStorage !== 'undefined' ? localStorage : null;
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+
35
57
  /**
36
58
  * Browser GIS OAuth client id only (`config.googleClientId`).
37
59
  * Capacitor / Capgo builds use `platforms.<name>.socialLogin.google.webClientId` instead.
@@ -95,16 +117,91 @@
95
117
  this.authenticated = !!(this.user.id && this.user.email);
96
118
  }
97
119
 
120
+ #readStoredToken() {
121
+ const key = this.#tokenKey(),
122
+ primary = this.#tokenStore();
123
+ let token = '';
124
+
125
+ try {
126
+ token = (primary && primary.getItem(key)) || '';
127
+ } catch {
128
+ token = '';
129
+ }
130
+
131
+ // One-time migrate: older builds kept the token in sessionStorage.
132
+ if (!token && this.#tokenStorageName() === 'localStorage') {
133
+ try {
134
+ token = (typeof sessionStorage !== 'undefined' && sessionStorage.getItem(key)) || '';
135
+ if (token && primary) {
136
+ primary.setItem(key, token);
137
+ sessionStorage.removeItem(key);
138
+ }
139
+ } catch {
140
+ /* ignore quota / private-mode */
141
+ }
142
+ }
143
+
144
+ return token;
145
+ }
146
+
147
+ #writeStoredToken(token) {
148
+ const key = this.#tokenKey(),
149
+ primary = this.#tokenStore();
150
+
151
+ try {
152
+ if (primary) {
153
+ primary.setItem(key, token);
154
+ }
155
+ } catch {
156
+ /* ignore */
157
+ }
158
+
159
+ // Drop the legacy session copy so tab-close cannot leave a stale twin.
160
+ if (this.#tokenStorageName() === 'localStorage') {
161
+ try {
162
+ if (typeof sessionStorage !== 'undefined') {
163
+ sessionStorage.removeItem(key);
164
+ }
165
+ } catch {
166
+ /* ignore */
167
+ }
168
+ }
169
+ }
170
+
171
+ #clearStoredToken() {
172
+ const key = this.#tokenKey();
173
+
174
+ try {
175
+ this.#tokenStore()?.removeItem(key);
176
+ } catch {
177
+ /* ignore */
178
+ }
179
+ try {
180
+ if (typeof sessionStorage !== 'undefined') {
181
+ sessionStorage.removeItem(key);
182
+ }
183
+ } catch {
184
+ /* ignore */
185
+ }
186
+ try {
187
+ if (typeof localStorage !== 'undefined') {
188
+ localStorage.removeItem(key);
189
+ }
190
+ } catch {
191
+ /* ignore */
192
+ }
193
+ }
194
+
98
195
  #clearSession() {
99
196
  this.accessToken = '';
100
197
  this.user = null;
101
198
  this.authenticated = false;
102
- sessionStorage.removeItem(this.#tokenKey());
199
+ this.#clearStoredToken();
103
200
  }
104
201
 
105
202
  #loadStoredToken() {
106
203
  if (!this.accessToken) {
107
- this.accessToken = sessionStorage.getItem(this.#tokenKey()) || '';
204
+ this.accessToken = this.#readStoredToken();
108
205
  }
109
206
  }
110
207
 
@@ -126,7 +223,7 @@
126
223
  })
127
224
  .then((data) => {
128
225
  this.accessToken = token;
129
- sessionStorage.setItem(this.#tokenKey(), token);
226
+ this.#writeStoredToken(token);
130
227
  this.#applyUserInfo(data);
131
228
  callback();
132
229
  })
@@ -303,15 +303,21 @@
303
303
  return;
304
304
  }
305
305
 
306
- const options = {
307
- scopes: provider === 'google'
308
- ? ['email', 'profile']
309
- : ['email', 'name'],
310
- };
306
+ // Android Capgo defaults / Family Link: never filter to "authorized"
307
+ // accounts only — that path commonly surfaces [16] Account reauth failed.
308
+ const options = provider === 'google'
309
+ ? {
310
+ scopes: ['email', 'profile'],
311
+ filterByAuthorizedAccounts: false,
312
+ }
313
+ : {
314
+ scopes: ['email', 'name'],
315
+ };
311
316
 
312
317
  console.info('[adaptfully social-auth] login starting', authContext({
313
318
  provider,
314
319
  scopes: options.scopes,
320
+ filterByAuthorizedAccounts: options.filterByAuthorizedAccounts ?? null,
315
321
  alreadyAuthenticated: this.authenticated,
316
322
  }));
317
323
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makefully/adaptfully",
3
- "version": "5.0.4",
3
+ "version": "5.0.6",
4
4
  "description": "Platform abstraction and Wrapfully deploy client for Makefully games",
5
5
  "type": "module",
6
6
  "main": "./lib/node/index.js",