@payez/next-mvp 4.0.24 → 4.0.25
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/dist/auth/better-auth.d.ts +10 -7
- package/dist/auth/better-auth.js +90 -84
- package/dist/server/auth.d.ts +0 -7
- package/package.json +1 -1
- package/src/auth/better-auth.ts +98 -87
|
@@ -45,13 +45,6 @@ export declare function createBetterAuthInstance(idpConfig: IDPClientConfig): im
|
|
|
45
45
|
refreshCache: false;
|
|
46
46
|
};
|
|
47
47
|
};
|
|
48
|
-
databaseHooks: {
|
|
49
|
-
session: {
|
|
50
|
-
create: {
|
|
51
|
-
after: (session: any) => Promise<void>;
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
};
|
|
55
48
|
advanced: {
|
|
56
49
|
cookiePrefix: string;
|
|
57
50
|
cookies: {
|
|
@@ -105,3 +98,13 @@ export declare function getBetterAuthHandler(): Promise<{
|
|
|
105
98
|
GET: (req: Request) => Promise<Response>;
|
|
106
99
|
POST: (req: Request) => Promise<Response>;
|
|
107
100
|
} | null>;
|
|
101
|
+
/**
|
|
102
|
+
* Exchange OAuth identity for IDP tokens and store in the BA Redis session.
|
|
103
|
+
*
|
|
104
|
+
* Call this from the OAuth callback route AFTER better-auth has processed the
|
|
105
|
+
* callback and created the session. Reads the session token from the Set-Cookie
|
|
106
|
+
* header of the response to find the BA Redis key.
|
|
107
|
+
*
|
|
108
|
+
* This replaces the old databaseHooks approach which doesn't fire in stateless mode.
|
|
109
|
+
*/
|
|
110
|
+
export declare function exchangeOAuthForIdpTokens(sessionToken: string, provider?: string): Promise<boolean>;
|
package/dist/auth/better-auth.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.createBetterAuthInstance = createBetterAuthInstance;
|
|
|
16
16
|
exports.isBetterAuthEnabled = isBetterAuthEnabled;
|
|
17
17
|
exports.getBetterAuthInstance = getBetterAuthInstance;
|
|
18
18
|
exports.getBetterAuthHandler = getBetterAuthHandler;
|
|
19
|
+
exports.exchangeOAuthForIdpTokens = exchangeOAuthForIdpTokens;
|
|
19
20
|
require("server-only");
|
|
20
21
|
const better_auth_1 = require("better-auth");
|
|
21
22
|
const next_js_1 = require("better-auth/next-js");
|
|
@@ -103,90 +104,6 @@ function createBetterAuthInstance(idpConfig) {
|
|
|
103
104
|
refreshCache: false,
|
|
104
105
|
},
|
|
105
106
|
},
|
|
106
|
-
// After social login, exchange Google identity for IDP tokens and store in Redis
|
|
107
|
-
databaseHooks: {
|
|
108
|
-
session: {
|
|
109
|
-
create: {
|
|
110
|
-
after: async (session) => {
|
|
111
|
-
try {
|
|
112
|
-
const userId = session.userId;
|
|
113
|
-
const token = session.token;
|
|
114
|
-
if (!userId || !token)
|
|
115
|
-
return;
|
|
116
|
-
// Look up user from Better Auth's memory/DB to get email
|
|
117
|
-
// The user was just created/found by Better Auth during OAuth
|
|
118
|
-
const baKey = `ba:${appSlug}:${token}`;
|
|
119
|
-
const baRaw = await (0, redis_1.getRedis)().get(baKey).catch(() => null);
|
|
120
|
-
const baData = baRaw ? JSON.parse(baRaw) : null;
|
|
121
|
-
const email = baData?.user?.email;
|
|
122
|
-
const name = baData?.user?.name;
|
|
123
|
-
const image = baData?.user?.image;
|
|
124
|
-
if (!email) {
|
|
125
|
-
console.warn('[BETTER_AUTH] Session created but no email found for IDP token exchange');
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
// Call IDP oauth-callback to get IDP tokens
|
|
129
|
-
const idpUrl = process.env.IDP_URL || '';
|
|
130
|
-
if (!idpUrl) {
|
|
131
|
-
console.warn('[BETTER_AUTH] No IDP URL configured, skipping token exchange');
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const oauthRes = await fetch(`${idpUrl}/api/ExternalAuth/oauth-callback`, {
|
|
135
|
-
method: 'POST',
|
|
136
|
-
headers: { 'Content-Type': 'application/json' },
|
|
137
|
-
body: JSON.stringify({
|
|
138
|
-
provider: 'google',
|
|
139
|
-
provider_account_id: userId,
|
|
140
|
-
email,
|
|
141
|
-
name,
|
|
142
|
-
image,
|
|
143
|
-
client_id: idpConfig.clientSlug || String(idpConfig.clientId),
|
|
144
|
-
}),
|
|
145
|
-
});
|
|
146
|
-
const oauthResText = await oauthRes.text();
|
|
147
|
-
console.log('[BETTER_AUTH] IDP oauth-callback response:', oauthRes.status, oauthResText.substring(0, 500));
|
|
148
|
-
if (!oauthRes.ok) {
|
|
149
|
-
console.error('[BETTER_AUTH] IDP oauth-callback failed:', oauthRes.status);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
let idpData;
|
|
153
|
-
try {
|
|
154
|
-
idpData = JSON.parse(oauthResText);
|
|
155
|
-
}
|
|
156
|
-
catch {
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
const result = idpData?.data?.result || idpData?.data || idpData;
|
|
160
|
-
if (!result?.access_token) {
|
|
161
|
-
console.warn('[BETTER_AUTH] IDP oauth-callback returned no access_token. Keys:', Object.keys(result || {}));
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
// Store IDP tokens in the BA Redis session
|
|
165
|
-
if (baData) {
|
|
166
|
-
const requiresTwoFactor = result.user?.requiresTwoFactor ?? result.requiresTwoFactor ?? false;
|
|
167
|
-
baData.idpTokens = {
|
|
168
|
-
idpAccessToken: result.access_token,
|
|
169
|
-
idpRefreshToken: result.refresh_token,
|
|
170
|
-
idpAccessTokenExpires: result.expires_in
|
|
171
|
-
? Date.now() + result.expires_in * 1000
|
|
172
|
-
: Date.now() + 15 * 60 * 1000,
|
|
173
|
-
userId: String(result.user?.user_id || result.user?.id || result.user_id || userId),
|
|
174
|
-
email: result.user?.email || result.email || email,
|
|
175
|
-
name: result.user?.full_name || result.user?.name || result.name || name,
|
|
176
|
-
roles: result.user?.roles || result.roles || [],
|
|
177
|
-
mfaVerified: !requiresTwoFactor,
|
|
178
|
-
};
|
|
179
|
-
await (0, redis_1.getRedis)().setex(baKey, 7 * 24 * 60 * 60, JSON.stringify(baData));
|
|
180
|
-
console.log('[BETTER_AUTH] IDP tokens stored in session for', email);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
catch (err) {
|
|
184
|
-
console.error('[BETTER_AUTH] Post-login IDP exchange failed:', err instanceof Error ? err.message : String(err));
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
107
|
// Cookie prefix must match slim-middleware expectations ({slug}.session-token)
|
|
191
108
|
advanced: {
|
|
192
109
|
cookiePrefix: appSlug,
|
|
@@ -251,3 +168,92 @@ async function getBetterAuthHandler() {
|
|
|
251
168
|
const auth = await getBetterAuthInstance();
|
|
252
169
|
return (0, next_js_2.toNextJsHandler)(auth);
|
|
253
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Exchange OAuth identity for IDP tokens and store in the BA Redis session.
|
|
173
|
+
*
|
|
174
|
+
* Call this from the OAuth callback route AFTER better-auth has processed the
|
|
175
|
+
* callback and created the session. Reads the session token from the Set-Cookie
|
|
176
|
+
* header of the response to find the BA Redis key.
|
|
177
|
+
*
|
|
178
|
+
* This replaces the old databaseHooks approach which doesn't fire in stateless mode.
|
|
179
|
+
*/
|
|
180
|
+
async function exchangeOAuthForIdpTokens(sessionToken, provider = 'google') {
|
|
181
|
+
try {
|
|
182
|
+
const config = await (0, idp_client_config_1.getIDPClientConfig)();
|
|
183
|
+
const appSlug = config.clientSlug || (0, app_slug_1.getAppSlug)();
|
|
184
|
+
const baKey = `ba:${appSlug}:${sessionToken}`;
|
|
185
|
+
// Read the BA session from Redis
|
|
186
|
+
const baRaw = await (0, redis_1.getRedis)().get(baKey).catch(() => null);
|
|
187
|
+
if (!baRaw) {
|
|
188
|
+
console.warn('[BETTER_AUTH] exchangeOAuthForIdpTokens: session not found in Redis for token', sessionToken.substring(0, 10));
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
const baData = JSON.parse(baRaw);
|
|
192
|
+
const email = baData?.user?.email;
|
|
193
|
+
const name = baData?.user?.name;
|
|
194
|
+
const image = baData?.user?.image;
|
|
195
|
+
const baUserId = baData?.session?.userId || baData?.user?.id;
|
|
196
|
+
if (!email) {
|
|
197
|
+
console.warn('[BETTER_AUTH] exchangeOAuthForIdpTokens: no email in session');
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
// Call IDP oauth-callback
|
|
201
|
+
const idpUrl = process.env.IDP_URL || '';
|
|
202
|
+
if (!idpUrl) {
|
|
203
|
+
console.warn('[BETTER_AUTH] No IDP_URL configured, skipping token exchange');
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
console.log('[BETTER_AUTH] Exchanging OAuth identity for IDP tokens:', email);
|
|
207
|
+
const oauthRes = await fetch(`${idpUrl}/api/ExternalAuth/oauth-callback`, {
|
|
208
|
+
method: 'POST',
|
|
209
|
+
headers: { 'Content-Type': 'application/json' },
|
|
210
|
+
body: JSON.stringify({
|
|
211
|
+
provider,
|
|
212
|
+
provider_account_id: baUserId,
|
|
213
|
+
email,
|
|
214
|
+
name,
|
|
215
|
+
image,
|
|
216
|
+
client_id: config.clientSlug || String(config.clientId),
|
|
217
|
+
}),
|
|
218
|
+
});
|
|
219
|
+
const oauthResText = await oauthRes.text();
|
|
220
|
+
console.log('[BETTER_AUTH] IDP oauth-callback response:', oauthRes.status, oauthResText.substring(0, 500));
|
|
221
|
+
if (!oauthRes.ok) {
|
|
222
|
+
console.error('[BETTER_AUTH] IDP oauth-callback failed:', oauthRes.status);
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
let idpData;
|
|
226
|
+
try {
|
|
227
|
+
idpData = JSON.parse(oauthResText);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
const result = idpData?.data?.result || idpData?.data || idpData;
|
|
233
|
+
if (!result?.access_token) {
|
|
234
|
+
console.warn('[BETTER_AUTH] IDP oauth-callback returned no access_token. Keys:', Object.keys(result || {}));
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
// Store IDP tokens in the BA Redis session
|
|
238
|
+
const requiresTwoFactor = result.user?.requiresTwoFactor ?? result.requiresTwoFactor ?? false;
|
|
239
|
+
baData.idpTokens = {
|
|
240
|
+
idpAccessToken: result.access_token,
|
|
241
|
+
idpRefreshToken: result.refresh_token,
|
|
242
|
+
idpAccessTokenExpires: result.expires_in
|
|
243
|
+
? Date.now() + result.expires_in * 1000
|
|
244
|
+
: Date.now() + 15 * 60 * 1000,
|
|
245
|
+
userId: String(result.user?.user_id || result.user?.id || result.user_id || baUserId),
|
|
246
|
+
email: result.user?.email || result.email || email,
|
|
247
|
+
name: result.user?.full_name || result.user?.name || result.name || name,
|
|
248
|
+
roles: result.user?.roles || result.roles || [],
|
|
249
|
+
mfaVerified: !requiresTwoFactor,
|
|
250
|
+
};
|
|
251
|
+
await (0, redis_1.getRedis)().setex(baKey, 7 * 24 * 60 * 60, JSON.stringify(baData));
|
|
252
|
+
console.log('[BETTER_AUTH] IDP tokens stored in session for', email);
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
console.error('[BETTER_AUTH] IDP token exchange failed:', err instanceof Error ? err.message : String(err));
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
package/dist/server/auth.d.ts
CHANGED
|
@@ -28,13 +28,6 @@ export declare function getAuthInstance(): Promise<import("better-auth/types").A
|
|
|
28
28
|
refreshCache: false;
|
|
29
29
|
};
|
|
30
30
|
};
|
|
31
|
-
databaseHooks: {
|
|
32
|
-
session: {
|
|
33
|
-
create: {
|
|
34
|
-
after: (session: any) => Promise<void>;
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
31
|
advanced: {
|
|
39
32
|
cookiePrefix: string;
|
|
40
33
|
cookies: {
|
package/package.json
CHANGED
package/src/auth/better-auth.ts
CHANGED
|
@@ -112,93 +112,6 @@ export function createBetterAuthInstance(idpConfig: IDPClientConfig) {
|
|
|
112
112
|
},
|
|
113
113
|
},
|
|
114
114
|
|
|
115
|
-
// After social login, exchange Google identity for IDP tokens and store in Redis
|
|
116
|
-
databaseHooks: {
|
|
117
|
-
session: {
|
|
118
|
-
create: {
|
|
119
|
-
after: async (session: any) => {
|
|
120
|
-
try {
|
|
121
|
-
const userId = session.userId;
|
|
122
|
-
const token = session.token;
|
|
123
|
-
if (!userId || !token) return;
|
|
124
|
-
|
|
125
|
-
// Look up user from Better Auth's memory/DB to get email
|
|
126
|
-
// The user was just created/found by Better Auth during OAuth
|
|
127
|
-
const baKey = `ba:${appSlug}:${token}`;
|
|
128
|
-
const baRaw = await getRedis().get(baKey).catch(() => null);
|
|
129
|
-
const baData = baRaw ? JSON.parse(baRaw) : null;
|
|
130
|
-
const email = baData?.user?.email;
|
|
131
|
-
const name = baData?.user?.name;
|
|
132
|
-
const image = baData?.user?.image;
|
|
133
|
-
|
|
134
|
-
if (!email) {
|
|
135
|
-
console.warn('[BETTER_AUTH] Session created but no email found for IDP token exchange');
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Call IDP oauth-callback to get IDP tokens
|
|
140
|
-
const idpUrl = process.env.IDP_URL || '';
|
|
141
|
-
if (!idpUrl) {
|
|
142
|
-
console.warn('[BETTER_AUTH] No IDP URL configured, skipping token exchange');
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const oauthRes = await fetch(`${idpUrl}/api/ExternalAuth/oauth-callback`, {
|
|
147
|
-
method: 'POST',
|
|
148
|
-
headers: { 'Content-Type': 'application/json' },
|
|
149
|
-
body: JSON.stringify({
|
|
150
|
-
provider: 'google',
|
|
151
|
-
provider_account_id: userId,
|
|
152
|
-
email,
|
|
153
|
-
name,
|
|
154
|
-
image,
|
|
155
|
-
client_id: idpConfig.clientSlug || String(idpConfig.clientId),
|
|
156
|
-
}),
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
const oauthResText = await oauthRes.text();
|
|
160
|
-
console.log('[BETTER_AUTH] IDP oauth-callback response:', oauthRes.status, oauthResText.substring(0, 500));
|
|
161
|
-
|
|
162
|
-
if (!oauthRes.ok) {
|
|
163
|
-
console.error('[BETTER_AUTH] IDP oauth-callback failed:', oauthRes.status);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
let idpData: any;
|
|
168
|
-
try { idpData = JSON.parse(oauthResText); } catch { return; }
|
|
169
|
-
const result = idpData?.data?.result || idpData?.data || idpData;
|
|
170
|
-
|
|
171
|
-
if (!result?.access_token) {
|
|
172
|
-
console.warn('[BETTER_AUTH] IDP oauth-callback returned no access_token. Keys:', Object.keys(result || {}));
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Store IDP tokens in the BA Redis session
|
|
177
|
-
if (baData) {
|
|
178
|
-
const requiresTwoFactor = result.user?.requiresTwoFactor ?? result.requiresTwoFactor ?? false;
|
|
179
|
-
baData.idpTokens = {
|
|
180
|
-
idpAccessToken: result.access_token,
|
|
181
|
-
idpRefreshToken: result.refresh_token,
|
|
182
|
-
idpAccessTokenExpires: result.expires_in
|
|
183
|
-
? Date.now() + result.expires_in * 1000
|
|
184
|
-
: Date.now() + 15 * 60 * 1000,
|
|
185
|
-
userId: String(result.user?.user_id || result.user?.id || result.user_id || userId),
|
|
186
|
-
email: result.user?.email || result.email || email,
|
|
187
|
-
name: result.user?.full_name || result.user?.name || result.name || name,
|
|
188
|
-
roles: result.user?.roles || result.roles || [],
|
|
189
|
-
mfaVerified: !requiresTwoFactor,
|
|
190
|
-
};
|
|
191
|
-
await getRedis().setex(baKey, 7 * 24 * 60 * 60, JSON.stringify(baData));
|
|
192
|
-
console.log('[BETTER_AUTH] IDP tokens stored in session for', email);
|
|
193
|
-
}
|
|
194
|
-
} catch (err) {
|
|
195
|
-
console.error('[BETTER_AUTH] Post-login IDP exchange failed:', err instanceof Error ? err.message : String(err));
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
|
|
202
115
|
// Cookie prefix must match slim-middleware expectations ({slug}.session-token)
|
|
203
116
|
advanced: {
|
|
204
117
|
cookiePrefix: appSlug,
|
|
@@ -272,3 +185,101 @@ export async function getBetterAuthHandler(): Promise<{ GET: (req: Request) => P
|
|
|
272
185
|
const auth = await getBetterAuthInstance();
|
|
273
186
|
return toNextJsHandler(auth);
|
|
274
187
|
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Exchange OAuth identity for IDP tokens and store in the BA Redis session.
|
|
191
|
+
*
|
|
192
|
+
* Call this from the OAuth callback route AFTER better-auth has processed the
|
|
193
|
+
* callback and created the session. Reads the session token from the Set-Cookie
|
|
194
|
+
* header of the response to find the BA Redis key.
|
|
195
|
+
*
|
|
196
|
+
* This replaces the old databaseHooks approach which doesn't fire in stateless mode.
|
|
197
|
+
*/
|
|
198
|
+
export async function exchangeOAuthForIdpTokens(
|
|
199
|
+
sessionToken: string,
|
|
200
|
+
provider: string = 'google'
|
|
201
|
+
): Promise<boolean> {
|
|
202
|
+
try {
|
|
203
|
+
const config = await getIDPClientConfig();
|
|
204
|
+
const appSlug = config.clientSlug || getAppSlug();
|
|
205
|
+
const baKey = `ba:${appSlug}:${sessionToken}`;
|
|
206
|
+
|
|
207
|
+
// Read the BA session from Redis
|
|
208
|
+
const baRaw = await getRedis().get(baKey).catch(() => null);
|
|
209
|
+
if (!baRaw) {
|
|
210
|
+
console.warn('[BETTER_AUTH] exchangeOAuthForIdpTokens: session not found in Redis for token', sessionToken.substring(0, 10));
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const baData = JSON.parse(baRaw);
|
|
215
|
+
const email = baData?.user?.email;
|
|
216
|
+
const name = baData?.user?.name;
|
|
217
|
+
const image = baData?.user?.image;
|
|
218
|
+
const baUserId = baData?.session?.userId || baData?.user?.id;
|
|
219
|
+
|
|
220
|
+
if (!email) {
|
|
221
|
+
console.warn('[BETTER_AUTH] exchangeOAuthForIdpTokens: no email in session');
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Call IDP oauth-callback
|
|
226
|
+
const idpUrl = process.env.IDP_URL || '';
|
|
227
|
+
if (!idpUrl) {
|
|
228
|
+
console.warn('[BETTER_AUTH] No IDP_URL configured, skipping token exchange');
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log('[BETTER_AUTH] Exchanging OAuth identity for IDP tokens:', email);
|
|
233
|
+
|
|
234
|
+
const oauthRes = await fetch(`${idpUrl}/api/ExternalAuth/oauth-callback`, {
|
|
235
|
+
method: 'POST',
|
|
236
|
+
headers: { 'Content-Type': 'application/json' },
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
provider,
|
|
239
|
+
provider_account_id: baUserId,
|
|
240
|
+
email,
|
|
241
|
+
name,
|
|
242
|
+
image,
|
|
243
|
+
client_id: config.clientSlug || String(config.clientId),
|
|
244
|
+
}),
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const oauthResText = await oauthRes.text();
|
|
248
|
+
console.log('[BETTER_AUTH] IDP oauth-callback response:', oauthRes.status, oauthResText.substring(0, 500));
|
|
249
|
+
|
|
250
|
+
if (!oauthRes.ok) {
|
|
251
|
+
console.error('[BETTER_AUTH] IDP oauth-callback failed:', oauthRes.status);
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
let idpData: any;
|
|
256
|
+
try { idpData = JSON.parse(oauthResText); } catch { return false; }
|
|
257
|
+
const result = idpData?.data?.result || idpData?.data || idpData;
|
|
258
|
+
|
|
259
|
+
if (!result?.access_token) {
|
|
260
|
+
console.warn('[BETTER_AUTH] IDP oauth-callback returned no access_token. Keys:', Object.keys(result || {}));
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Store IDP tokens in the BA Redis session
|
|
265
|
+
const requiresTwoFactor = result.user?.requiresTwoFactor ?? result.requiresTwoFactor ?? false;
|
|
266
|
+
baData.idpTokens = {
|
|
267
|
+
idpAccessToken: result.access_token,
|
|
268
|
+
idpRefreshToken: result.refresh_token,
|
|
269
|
+
idpAccessTokenExpires: result.expires_in
|
|
270
|
+
? Date.now() + result.expires_in * 1000
|
|
271
|
+
: Date.now() + 15 * 60 * 1000,
|
|
272
|
+
userId: String(result.user?.user_id || result.user?.id || result.user_id || baUserId),
|
|
273
|
+
email: result.user?.email || result.email || email,
|
|
274
|
+
name: result.user?.full_name || result.user?.name || result.name || name,
|
|
275
|
+
roles: result.user?.roles || result.roles || [],
|
|
276
|
+
mfaVerified: !requiresTwoFactor,
|
|
277
|
+
};
|
|
278
|
+
await getRedis().setex(baKey, 7 * 24 * 60 * 60, JSON.stringify(baData));
|
|
279
|
+
console.log('[BETTER_AUTH] IDP tokens stored in session for', email);
|
|
280
|
+
return true;
|
|
281
|
+
} catch (err) {
|
|
282
|
+
console.error('[BETTER_AUTH] IDP token exchange failed:', err instanceof Error ? err.message : String(err));
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|