@djangocfg/api 2.1.482 → 2.1.483
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 +1 -1
- package/dist/auth.cjs +64 -25
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +14 -1
- package/dist/auth.d.ts +14 -1
- package/dist/auth.mjs +64 -25
- package/dist/auth.mjs.map +1 -1
- package/dist/clients.cjs +29 -8
- package/dist/clients.cjs.map +1 -1
- package/dist/clients.d.cts +22 -2
- package/dist/clients.d.ts +22 -2
- package/dist/clients.mjs +29 -8
- package/dist/clients.mjs.map +1 -1
- package/dist/hooks.cjs +29 -8
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.mjs +29 -8
- package/dist/hooks.mjs.map +1 -1
- package/dist/index.cjs +31 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -4
- package/dist/index.d.ts +32 -4
- package/dist/index.mjs +31 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/_api/generated/_cfg_accounts/api.ts +3 -3
- package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpConsentPolicyRetrieve.ts +2 -2
- package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpRequestCreate.ts +2 -2
- package/src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpVerifyCreate.ts +2 -2
- package/src/_api/generated/_cfg_accounts/index.ts +1 -1
- package/src/_api/generated/_cfg_accounts/openapi.json +21 -43
- package/src/_api/generated/_cfg_accounts/schemas/OAuthCallbackRequestRequest.ts +1 -0
- package/src/_api/generated/_cfg_accounts/schemas/OAuthTokenResponse.ts +1 -0
- package/src/_api/generated/_cfg_accounts/schemas/OTPVerifyRequest.ts +1 -0
- package/src/_api/generated/_cfg_accounts/schemas/OTPVerifyResponse.ts +1 -0
- package/src/_api/generated/_cfg_totp/openapi.json +5 -0
- package/src/_api/generated/_cfg_totp/schemas/VerifyResponse.ts +1 -0
- package/src/_api/generated/helpers/auth.ts +27 -6
- package/src/_api/generated/index.ts +1 -1
- package/src/_api/generated/openapi.json +26 -43
- package/src/_api/generated/sdk.gen.ts +1 -1
- package/src/_api/generated/types.gen.ts +28 -0
- package/src/auth/context/AccountsContext.tsx +1 -0
- package/src/auth/context/AuthContext.tsx +3 -2
- package/src/auth/context/types.ts +1 -1
- package/src/auth/hooks/useAuthForm.ts +3 -2
- package/src/auth/hooks/useAuthFormState.ts +3 -0
- package/src/auth/hooks/useAuthRedirect.ts +2 -2
- package/src/auth/hooks/useGithubAuth.ts +34 -21
- package/src/auth/hooks/useTwoFactorVerify.ts +5 -3
- package/src/auth/types/form.ts +3 -1
- package/src/index.ts +5 -1
package/dist/auth.d.cts
CHANGED
|
@@ -107,6 +107,10 @@ type OtpVerifyRequest = {
|
|
|
107
107
|
* Source URL for tracking login (e.g., https://my.djangocfg.com)
|
|
108
108
|
*/
|
|
109
109
|
source_url?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Keep this browser signed in for 30 days
|
|
112
|
+
*/
|
|
113
|
+
remember_me?: boolean;
|
|
110
114
|
};
|
|
111
115
|
/**
|
|
112
116
|
* OTP verification response.
|
|
@@ -146,6 +150,10 @@ type OtpVerifyResponse = {
|
|
|
146
150
|
* Whether user should be prompted to enable 2FA
|
|
147
151
|
*/
|
|
148
152
|
should_prompt_2fa?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether this login should persist across browser restarts
|
|
155
|
+
*/
|
|
156
|
+
persistent_session?: boolean;
|
|
149
157
|
};
|
|
150
158
|
/**
|
|
151
159
|
* Serializer for updating user profile.
|
|
@@ -371,6 +379,8 @@ interface AuthFormState {
|
|
|
371
379
|
* jurisdiction-aware default on mount.
|
|
372
380
|
*/
|
|
373
381
|
marketingConsent: boolean | null;
|
|
382
|
+
/** Keep this browser signed in for 30 days after successful verification. */
|
|
383
|
+
rememberMe: boolean;
|
|
374
384
|
/** Current form step */
|
|
375
385
|
step: AuthStep;
|
|
376
386
|
/** Error message */
|
|
@@ -397,6 +407,7 @@ interface AuthFormStateHandlers {
|
|
|
397
407
|
setOtp: (otp: string) => void;
|
|
398
408
|
setAcceptedTerms: (accepted: boolean) => void;
|
|
399
409
|
setMarketingConsent: (consent: boolean | null) => void;
|
|
410
|
+
setRememberMe: (rememberMe: boolean) => void;
|
|
400
411
|
setError: (error: string) => void;
|
|
401
412
|
clearError: () => void;
|
|
402
413
|
setStep: (step: AuthStep) => void;
|
|
@@ -502,7 +513,7 @@ interface AuthContextType {
|
|
|
502
513
|
saveEmail: (email: string) => void;
|
|
503
514
|
clearSavedEmail: () => void;
|
|
504
515
|
requestOTP: (identifier: string, sourceUrl?: string, consent?: OTPRequestConsent) => Promise<OTPRequestResult>;
|
|
505
|
-
verifyOTP: (identifier: string, otpCode: string, sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean) => Promise<{
|
|
516
|
+
verifyOTP: (identifier: string, otpCode: string, sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean, rememberMe?: boolean) => Promise<{
|
|
506
517
|
success: boolean;
|
|
507
518
|
message: string;
|
|
508
519
|
user?: UserProfile;
|
|
@@ -696,6 +707,8 @@ declare const useAutoAuth: (options?: UseAutoAuthOptions) => {
|
|
|
696
707
|
|
|
697
708
|
interface UseGithubAuthOptions {
|
|
698
709
|
sourceUrl?: string;
|
|
710
|
+
/** Keep the completed browser session for 30 days. */
|
|
711
|
+
rememberMe?: boolean;
|
|
699
712
|
onSuccess?: (user: any, isNewUser: boolean) => void;
|
|
700
713
|
onError?: (error: string) => void;
|
|
701
714
|
/** Callback when 2FA is required */
|
package/dist/auth.d.ts
CHANGED
|
@@ -107,6 +107,10 @@ type OtpVerifyRequest = {
|
|
|
107
107
|
* Source URL for tracking login (e.g., https://my.djangocfg.com)
|
|
108
108
|
*/
|
|
109
109
|
source_url?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Keep this browser signed in for 30 days
|
|
112
|
+
*/
|
|
113
|
+
remember_me?: boolean;
|
|
110
114
|
};
|
|
111
115
|
/**
|
|
112
116
|
* OTP verification response.
|
|
@@ -146,6 +150,10 @@ type OtpVerifyResponse = {
|
|
|
146
150
|
* Whether user should be prompted to enable 2FA
|
|
147
151
|
*/
|
|
148
152
|
should_prompt_2fa?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Whether this login should persist across browser restarts
|
|
155
|
+
*/
|
|
156
|
+
persistent_session?: boolean;
|
|
149
157
|
};
|
|
150
158
|
/**
|
|
151
159
|
* Serializer for updating user profile.
|
|
@@ -371,6 +379,8 @@ interface AuthFormState {
|
|
|
371
379
|
* jurisdiction-aware default on mount.
|
|
372
380
|
*/
|
|
373
381
|
marketingConsent: boolean | null;
|
|
382
|
+
/** Keep this browser signed in for 30 days after successful verification. */
|
|
383
|
+
rememberMe: boolean;
|
|
374
384
|
/** Current form step */
|
|
375
385
|
step: AuthStep;
|
|
376
386
|
/** Error message */
|
|
@@ -397,6 +407,7 @@ interface AuthFormStateHandlers {
|
|
|
397
407
|
setOtp: (otp: string) => void;
|
|
398
408
|
setAcceptedTerms: (accepted: boolean) => void;
|
|
399
409
|
setMarketingConsent: (consent: boolean | null) => void;
|
|
410
|
+
setRememberMe: (rememberMe: boolean) => void;
|
|
400
411
|
setError: (error: string) => void;
|
|
401
412
|
clearError: () => void;
|
|
402
413
|
setStep: (step: AuthStep) => void;
|
|
@@ -502,7 +513,7 @@ interface AuthContextType {
|
|
|
502
513
|
saveEmail: (email: string) => void;
|
|
503
514
|
clearSavedEmail: () => void;
|
|
504
515
|
requestOTP: (identifier: string, sourceUrl?: string, consent?: OTPRequestConsent) => Promise<OTPRequestResult>;
|
|
505
|
-
verifyOTP: (identifier: string, otpCode: string, sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean) => Promise<{
|
|
516
|
+
verifyOTP: (identifier: string, otpCode: string, sourceUrl?: string, redirectUrl?: string, skipRedirect?: boolean, rememberMe?: boolean) => Promise<{
|
|
506
517
|
success: boolean;
|
|
507
518
|
message: string;
|
|
508
519
|
user?: UserProfile;
|
|
@@ -696,6 +707,8 @@ declare const useAutoAuth: (options?: UseAutoAuthOptions) => {
|
|
|
696
707
|
|
|
697
708
|
interface UseGithubAuthOptions {
|
|
698
709
|
sourceUrl?: string;
|
|
710
|
+
/** Keep the completed browser session for 30 days. */
|
|
711
|
+
rememberMe?: boolean;
|
|
699
712
|
onSuccess?: (user: any, isNewUser: boolean) => void;
|
|
700
713
|
onError?: (error: string) => void;
|
|
701
714
|
/** Callback when 2FA is required */
|
package/dist/auth.mjs
CHANGED
|
@@ -112,6 +112,24 @@ var localStorageBackend = {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
};
|
|
115
|
+
var sessionStorageBackend = {
|
|
116
|
+
get(key) {
|
|
117
|
+
if (!isBrowser) return null;
|
|
118
|
+
try {
|
|
119
|
+
return window.sessionStorage.getItem(key);
|
|
120
|
+
} catch {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
set(key, value) {
|
|
125
|
+
if (!isBrowser) return;
|
|
126
|
+
try {
|
|
127
|
+
if (value === null) window.sessionStorage.removeItem(key);
|
|
128
|
+
else window.sessionStorage.setItem(key, value);
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
115
133
|
var COOKIE_MAX_AGE = 60 * 60 * 24 * 30;
|
|
116
134
|
var cookieBackend = {
|
|
117
135
|
get(key) {
|
|
@@ -119,7 +137,8 @@ var cookieBackend = {
|
|
|
119
137
|
try {
|
|
120
138
|
const re = new RegExp(`(?:^|;\\s*)${encodeURIComponent(key)}=([^;]*)`);
|
|
121
139
|
const m = document.cookie.match(re);
|
|
122
|
-
|
|
140
|
+
const value = m?.[1];
|
|
141
|
+
return value === void 0 ? null : decodeURIComponent(value);
|
|
123
142
|
} catch {
|
|
124
143
|
return null;
|
|
125
144
|
}
|
|
@@ -145,7 +164,8 @@ function detectLocale() {
|
|
|
145
164
|
try {
|
|
146
165
|
if (typeof document !== "undefined") {
|
|
147
166
|
const m = document.cookie.match(/(?:^|;\s*)NEXT_LOCALE=([^;]*)/);
|
|
148
|
-
|
|
167
|
+
const locale = m?.[1];
|
|
168
|
+
if (locale !== void 0) return decodeURIComponent(locale);
|
|
149
169
|
}
|
|
150
170
|
if (typeof navigator !== "undefined" && navigator.language) {
|
|
151
171
|
return navigator.language;
|
|
@@ -295,7 +315,7 @@ var auth = {
|
|
|
295
315
|
},
|
|
296
316
|
setStorageMode(mode) {
|
|
297
317
|
_storageMode = mode;
|
|
298
|
-
_storage = mode === "cookie" ? cookieBackend : localStorageBackend;
|
|
318
|
+
_storage = mode === "cookie" ? cookieBackend : mode === "sessionStorage" ? sessionStorageBackend : localStorageBackend;
|
|
299
319
|
notifySessionChanged();
|
|
300
320
|
},
|
|
301
321
|
// ── Bearer token ──────────────────────────────────────────────────
|
|
@@ -559,7 +579,7 @@ __name(_getDpopKeyPair, "_getDpopKeyPair");
|
|
|
559
579
|
function _b64urlFromBytes(bytes) {
|
|
560
580
|
const arr = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
|
|
561
581
|
let s = "";
|
|
562
|
-
for (let i = 0; i < arr.length; i++) s += String.fromCharCode(arr[i]);
|
|
582
|
+
for (let i = 0; i < arr.length; i++) s += String.fromCharCode(arr[i] ?? 0);
|
|
563
583
|
return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
564
584
|
}
|
|
565
585
|
__name(_b64urlFromBytes, "_b64urlFromBytes");
|
|
@@ -577,7 +597,8 @@ async function _makeDpopProof(method, url) {
|
|
|
577
597
|
const pair = await _getDpopKeyPair();
|
|
578
598
|
const jwk = await _publicJwk(pair.publicKey);
|
|
579
599
|
const header = { typ: "dpop+jwt", alg: "ES256", jwk };
|
|
580
|
-
const
|
|
600
|
+
const withoutFragment = url.split("#")[0] ?? url;
|
|
601
|
+
const htu = withoutFragment.split("?")[0] ?? withoutFragment;
|
|
581
602
|
const jti = crypto.randomUUID && crypto.randomUUID() || _b64urlFromBytes(crypto.getRandomValues(new Uint8Array(16)));
|
|
582
603
|
const payload = { htm: method.toUpperCase(), htu, iat: Math.floor(Date.now() / 1e3), jti };
|
|
583
604
|
const signingInput = `${_b64urlFromString(JSON.stringify(header))}.${_b64urlFromString(JSON.stringify(payload))}`;
|
|
@@ -949,6 +970,7 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "") => {
|
|
|
949
970
|
const [isLoading, setIsLoading] = useState2(false);
|
|
950
971
|
const [acceptedTerms, setAcceptedTerms] = useState2(true);
|
|
951
972
|
const [marketingConsent, setMarketingConsent] = useState2(null);
|
|
973
|
+
const [rememberMe, setRememberMe] = useState2(false);
|
|
952
974
|
const [step, setStep] = useState2("identifier");
|
|
953
975
|
const [error, setError] = useState2("");
|
|
954
976
|
const [webmail, setWebmail] = useState2(null);
|
|
@@ -983,6 +1005,7 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "") => {
|
|
|
983
1005
|
isLoading,
|
|
984
1006
|
acceptedTerms,
|
|
985
1007
|
marketingConsent,
|
|
1008
|
+
rememberMe,
|
|
986
1009
|
step,
|
|
987
1010
|
error,
|
|
988
1011
|
twoFactorSessionId,
|
|
@@ -998,6 +1021,7 @@ var useAuthFormState = /* @__PURE__ */ __name((initialIdentifier = "") => {
|
|
|
998
1021
|
setOtp,
|
|
999
1022
|
setAcceptedTerms,
|
|
1000
1023
|
setMarketingConsent,
|
|
1024
|
+
setRememberMe,
|
|
1001
1025
|
setError,
|
|
1002
1026
|
clearError,
|
|
1003
1027
|
setStep,
|
|
@@ -1991,9 +2015,9 @@ var CfgAccountsOauth = class {
|
|
|
1991
2015
|
return (options?.client ?? client).get({ url: "/cfg/accounts/oauth/providers/", ...options });
|
|
1992
2016
|
}
|
|
1993
2017
|
};
|
|
1994
|
-
var
|
|
2018
|
+
var CfgAccountsOtp = class {
|
|
1995
2019
|
static {
|
|
1996
|
-
__name(this, "
|
|
2020
|
+
__name(this, "CfgAccountsOtp");
|
|
1997
2021
|
}
|
|
1998
2022
|
/**
|
|
1999
2023
|
* Marketing-consent checkbox policy for the caller's jurisdiction.
|
|
@@ -2604,7 +2628,7 @@ var consumeSavedRedirect = /* @__PURE__ */ __name(() => {
|
|
|
2604
2628
|
return stored || null;
|
|
2605
2629
|
}, "consumeSavedRedirect");
|
|
2606
2630
|
var useAuthRedirectManager = /* @__PURE__ */ __name((options = {}) => {
|
|
2607
|
-
const { fallbackUrl = "/
|
|
2631
|
+
const { fallbackUrl = "/private", clearOnUse = true } = options;
|
|
2608
2632
|
const [redirectUrl, setRedirectUrl, removeRedirectUrl] = useSessionStorage(AUTH_REDIRECT_KEY, "");
|
|
2609
2633
|
const setRedirect = /* @__PURE__ */ __name((url) => {
|
|
2610
2634
|
setRedirectUrl(url);
|
|
@@ -2683,6 +2707,7 @@ var useTwoFactorVerify = /* @__PURE__ */ __name((options = {}) => {
|
|
|
2683
2707
|
setError(null);
|
|
2684
2708
|
}, []);
|
|
2685
2709
|
const handleSuccess = useCallback4((response) => {
|
|
2710
|
+
auth.setStorageMode(response.persistent_session ? "localStorage" : "sessionStorage");
|
|
2686
2711
|
auth.setSession({ access: response.access_token, refresh: response.refresh_token });
|
|
2687
2712
|
if (response.warning) {
|
|
2688
2713
|
setWarning(response.warning);
|
|
@@ -2699,7 +2724,7 @@ var useTwoFactorVerify = /* @__PURE__ */ __name((options = {}) => {
|
|
|
2699
2724
|
}
|
|
2700
2725
|
onSuccess?.(response.user);
|
|
2701
2726
|
if (!skipRedirect) {
|
|
2702
|
-
const finalRedirectUrl = consumeSavedRedirect() || redirectUrl || "/";
|
|
2727
|
+
const finalRedirectUrl = consumeSavedRedirect() || redirectUrl || "/private";
|
|
2703
2728
|
authLogger.info("2FA successful, redirecting to:", finalRedirectUrl);
|
|
2704
2729
|
router.hardPush(finalRedirectUrl);
|
|
2705
2730
|
}
|
|
@@ -2833,6 +2858,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
2833
2858
|
isLoading,
|
|
2834
2859
|
acceptedTerms,
|
|
2835
2860
|
marketingConsent,
|
|
2861
|
+
rememberMe,
|
|
2836
2862
|
twoFactorSessionId,
|
|
2837
2863
|
twoFactorCode,
|
|
2838
2864
|
useBackupCode,
|
|
@@ -2948,7 +2974,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
2948
2974
|
setIsLoading(true);
|
|
2949
2975
|
clearError();
|
|
2950
2976
|
try {
|
|
2951
|
-
const result = await verifyOTP(submitIdentifier, submitOtp, sourceUrl, redirectUrl, true);
|
|
2977
|
+
const result = await verifyOTP(submitIdentifier, submitOtp, sourceUrl, redirectUrl, true, rememberMe);
|
|
2952
2978
|
if (result.requires_2fa && result.session_id) {
|
|
2953
2979
|
authLogger.info("2FA required after OTP verification");
|
|
2954
2980
|
setTwoFactorSessionId(result.session_id);
|
|
@@ -2976,7 +3002,7 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
2976
3002
|
} finally {
|
|
2977
3003
|
setIsLoading(false);
|
|
2978
3004
|
}
|
|
2979
|
-
}, [verifyOTP, saveIdentifierToStorage, setError, setIsLoading, clearError, onOTPSuccess, onError, sourceUrl, redirectUrl, setTwoFactorSessionId, setShouldPrompt2FA, setStep]);
|
|
3005
|
+
}, [verifyOTP, saveIdentifierToStorage, setError, setIsLoading, clearError, onOTPSuccess, onError, sourceUrl, redirectUrl, rememberMe, setTwoFactorSessionId, setShouldPrompt2FA, setStep]);
|
|
2980
3006
|
const handleOTPSubmit = useCallback5(async (e) => {
|
|
2981
3007
|
e.preventDefault();
|
|
2982
3008
|
await submitOTP(identifier, otp);
|
|
@@ -3095,13 +3121,14 @@ var useAuthForm = /* @__PURE__ */ __name((options) => {
|
|
|
3095
3121
|
// src/auth/hooks/useGithubAuth.ts
|
|
3096
3122
|
import { useCallback as useCallback6, useState as useState5 } from "react";
|
|
3097
3123
|
var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
3098
|
-
const { sourceUrl, onSuccess, onError, onRequires2FA, redirectUrl, skipRedirect = false } = options;
|
|
3124
|
+
const { sourceUrl, rememberMe = false, onSuccess, onError, onRequires2FA, redirectUrl, skipRedirect = false } = options;
|
|
3099
3125
|
const router = useCfgRouter();
|
|
3100
3126
|
const [isLoading, setIsLoading] = useState5(false);
|
|
3101
3127
|
const [error, setError] = useState5(null);
|
|
3102
3128
|
const startGithubAuth = useCallback6(async () => {
|
|
3103
3129
|
setIsLoading(true);
|
|
3104
3130
|
setError(null);
|
|
3131
|
+
auth.clearSession();
|
|
3105
3132
|
try {
|
|
3106
3133
|
authLogger.info("Starting GitHub OAuth flow...");
|
|
3107
3134
|
Analytics.event("auth_oauth_start" /* AUTH_OAUTH_START */, {
|
|
@@ -3122,6 +3149,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3122
3149
|
if (typeof window !== "undefined") {
|
|
3123
3150
|
sessionStorage.setItem("oauth_state", response.state);
|
|
3124
3151
|
sessionStorage.setItem("oauth_provider", "github");
|
|
3152
|
+
sessionStorage.setItem("cfg.oauth.remember_me", String(rememberMe));
|
|
3125
3153
|
}
|
|
3126
3154
|
window.location.href = response.authorization_url;
|
|
3127
3155
|
} catch (err) {
|
|
@@ -3136,22 +3164,25 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3136
3164
|
} finally {
|
|
3137
3165
|
setIsLoading(false);
|
|
3138
3166
|
}
|
|
3139
|
-
}, [sourceUrl, onError]);
|
|
3167
|
+
}, [sourceUrl, rememberMe, onError]);
|
|
3140
3168
|
const handleGithubCallback = useCallback6(async (code, state) => {
|
|
3141
3169
|
setIsLoading(true);
|
|
3142
3170
|
setError(null);
|
|
3143
3171
|
try {
|
|
3144
3172
|
authLogger.info("Processing GitHub OAuth callback...");
|
|
3173
|
+
let rememberMeForSession = false;
|
|
3145
3174
|
if (typeof window !== "undefined") {
|
|
3146
3175
|
const storedState = sessionStorage.getItem("oauth_state");
|
|
3147
3176
|
if (storedState && storedState !== state) {
|
|
3148
3177
|
throw new Error("Invalid OAuth state - possible CSRF attack");
|
|
3149
3178
|
}
|
|
3179
|
+
rememberMeForSession = sessionStorage.getItem("cfg.oauth.remember_me") === "true";
|
|
3150
3180
|
sessionStorage.removeItem("oauth_state");
|
|
3151
3181
|
sessionStorage.removeItem("oauth_provider");
|
|
3182
|
+
sessionStorage.removeItem("cfg.oauth.remember_me");
|
|
3152
3183
|
}
|
|
3153
3184
|
const result = await CfgAccountsOauth.cfgAccountsOauthGithubCallbackCreate({
|
|
3154
|
-
body: { code, state },
|
|
3185
|
+
body: { code, state, remember_me: rememberMeForSession },
|
|
3155
3186
|
throwOnError: true
|
|
3156
3187
|
});
|
|
3157
3188
|
const response = result.data;
|
|
@@ -3168,6 +3199,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3168
3199
|
throw new Error("Invalid response from OAuth callback");
|
|
3169
3200
|
}
|
|
3170
3201
|
authLogger.info("GitHub OAuth successful, user:", response.user);
|
|
3202
|
+
auth.setStorageMode(response.persistent_session ? "localStorage" : "sessionStorage");
|
|
3171
3203
|
auth.setSession({ access: response.access, refresh: response.refresh });
|
|
3172
3204
|
Analytics.event("auth_login_success" /* AUTH_LOGIN_SUCCESS */, {
|
|
3173
3205
|
category: "auth" /* AUTH */,
|
|
@@ -3178,9 +3210,10 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3178
3210
|
}
|
|
3179
3211
|
onSuccess?.(response.user, response.is_new_user || false);
|
|
3180
3212
|
if (!skipRedirect) {
|
|
3181
|
-
const finalRedirectUrl = redirectUrl || "/
|
|
3213
|
+
const finalRedirectUrl = redirectUrl || "/private";
|
|
3182
3214
|
router.hardPush(finalRedirectUrl);
|
|
3183
3215
|
}
|
|
3216
|
+
return;
|
|
3184
3217
|
} catch (err) {
|
|
3185
3218
|
const errorMessage = err instanceof Error ? err.message : "GitHub authentication failed";
|
|
3186
3219
|
authLogger.error("GitHub OAuth callback error:", err);
|
|
@@ -3193,7 +3226,7 @@ var useGithubAuth = /* @__PURE__ */ __name((options = {}) => {
|
|
|
3193
3226
|
} finally {
|
|
3194
3227
|
setIsLoading(false);
|
|
3195
3228
|
}
|
|
3196
|
-
}, [onSuccess, onError, redirectUrl, router]);
|
|
3229
|
+
}, [onSuccess, onError, onRequires2FA, redirectUrl, router, skipRedirect]);
|
|
3197
3230
|
return {
|
|
3198
3231
|
isLoading,
|
|
3199
3232
|
error,
|
|
@@ -3835,7 +3868,8 @@ var OAuthTokenResponseSchema = z10.object({
|
|
|
3835
3868
|
user: z10.object({}).passthrough().nullable().optional(),
|
|
3836
3869
|
is_new_user: z10.boolean().default(false).optional(),
|
|
3837
3870
|
is_new_connection: z10.boolean().default(false).optional(),
|
|
3838
|
-
should_prompt_2fa: z10.boolean().optional()
|
|
3871
|
+
should_prompt_2fa: z10.boolean().optional(),
|
|
3872
|
+
persistent_session: z10.boolean().optional()
|
|
3839
3873
|
});
|
|
3840
3874
|
|
|
3841
3875
|
// src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOauthProvidersRetrieve.ts
|
|
@@ -3895,7 +3929,7 @@ function useCfgAccountsOtpRequestCreate(config) {
|
|
|
3895
3929
|
return useSWRMutation7(
|
|
3896
3930
|
["cfg_accounts_otp_request_create"],
|
|
3897
3931
|
async (_key, { arg }) => {
|
|
3898
|
-
const res = await
|
|
3932
|
+
const res = await CfgAccountsOtp.cfgAccountsOtpRequestCreate({ ...arg, throwOnError: true });
|
|
3899
3933
|
const data = res.data;
|
|
3900
3934
|
const parsed = OTPRequestResponseSchema.safeParse(data);
|
|
3901
3935
|
if (!parsed.success) {
|
|
@@ -3986,7 +4020,8 @@ var OTPVerifyResponseSchema = z19.object({
|
|
|
3986
4020
|
refresh: z19.string().nullable().optional(),
|
|
3987
4021
|
access: z19.string().nullable().optional(),
|
|
3988
4022
|
user: UserSchema.nullable().optional(),
|
|
3989
|
-
should_prompt_2fa: z19.boolean().optional()
|
|
4023
|
+
should_prompt_2fa: z19.boolean().optional(),
|
|
4024
|
+
persistent_session: z19.boolean().optional()
|
|
3990
4025
|
});
|
|
3991
4026
|
|
|
3992
4027
|
// src/_api/generated/_cfg_accounts/hooks/useCfgAccountsOtpVerifyCreate.ts
|
|
@@ -3994,7 +4029,7 @@ function useCfgAccountsOtpVerifyCreate(config) {
|
|
|
3994
4029
|
return useSWRMutation8(
|
|
3995
4030
|
["cfg_accounts_otp_verify_create"],
|
|
3996
4031
|
async (_key, { arg }) => {
|
|
3997
|
-
const res = await
|
|
4032
|
+
const res = await CfgAccountsOtp.cfgAccountsOtpVerifyCreate({ ...arg, throwOnError: true });
|
|
3998
4033
|
const data = res.data;
|
|
3999
4034
|
const parsed = OTPVerifyResponseSchema.safeParse(data);
|
|
4000
4035
|
if (!parsed.success) {
|
|
@@ -4250,7 +4285,8 @@ import { z as z26 } from "zod";
|
|
|
4250
4285
|
var OAuthCallbackRequestRequestSchema = z26.object({
|
|
4251
4286
|
code: z26.string().min(10).max(500),
|
|
4252
4287
|
state: z26.string().min(20).max(100),
|
|
4253
|
-
redirect_uri: z26.string().optional()
|
|
4288
|
+
redirect_uri: z26.string().optional(),
|
|
4289
|
+
remember_me: z26.boolean().default(false).optional()
|
|
4254
4290
|
});
|
|
4255
4291
|
|
|
4256
4292
|
// src/_api/generated/_cfg_accounts/schemas/OAuthDisconnectRequestRequest.ts
|
|
@@ -4288,7 +4324,8 @@ import { z as z31 } from "zod";
|
|
|
4288
4324
|
var OTPVerifyRequestSchema = z31.object({
|
|
4289
4325
|
identifier: z31.string().min(1),
|
|
4290
4326
|
otp: z31.string().min(4).max(4),
|
|
4291
|
-
source_url: z31.string().optional()
|
|
4327
|
+
source_url: z31.string().optional(),
|
|
4328
|
+
remember_me: z31.boolean().default(false).optional()
|
|
4292
4329
|
});
|
|
4293
4330
|
|
|
4294
4331
|
// src/_api/generated/_cfg_accounts/schemas/PatchedCfgUserUpdateRequest.ts
|
|
@@ -4390,6 +4427,7 @@ function AccountsProvider({ children }) {
|
|
|
4390
4427
|
return result;
|
|
4391
4428
|
}
|
|
4392
4429
|
if (result.access && result.refresh) {
|
|
4430
|
+
auth.setStorageMode(result.persistent_session ? "localStorage" : "sessionStorage");
|
|
4393
4431
|
auth.setSession({ access: result.access, refresh: result.refresh });
|
|
4394
4432
|
try {
|
|
4395
4433
|
await refreshProfile({ callerId: "verifyOTP", force: true });
|
|
@@ -4450,7 +4488,7 @@ __name(useAccountsContext, "useAccountsContext");
|
|
|
4450
4488
|
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
4451
4489
|
var defaultRoutes = {
|
|
4452
4490
|
auth: "/auth",
|
|
4453
|
-
defaultCallback: "/",
|
|
4491
|
+
defaultCallback: "/private",
|
|
4454
4492
|
defaultAuthCallback: "/auth"
|
|
4455
4493
|
};
|
|
4456
4494
|
var resolveAuthRoutes = /* @__PURE__ */ __name((routes) => ({
|
|
@@ -4608,13 +4646,14 @@ var AuthProviderInternal = /* @__PURE__ */ __name(({ children, config }) => {
|
|
|
4608
4646
|
[]
|
|
4609
4647
|
);
|
|
4610
4648
|
const verifyOTP = useCallback11(
|
|
4611
|
-
async (identifier, otpCode, sourceUrl, redirectUrl, skipRedirect) => {
|
|
4649
|
+
async (identifier, otpCode, sourceUrl, redirectUrl, skipRedirect, rememberMe = false) => {
|
|
4612
4650
|
try {
|
|
4613
4651
|
pendingManualNavRef.current = Boolean(skipRedirect);
|
|
4614
4652
|
const result = await accountsRef.current.verifyOTP({
|
|
4615
4653
|
identifier,
|
|
4616
4654
|
otp: otpCode,
|
|
4617
|
-
source_url: sourceUrl
|
|
4655
|
+
source_url: sourceUrl,
|
|
4656
|
+
remember_me: rememberMe
|
|
4618
4657
|
});
|
|
4619
4658
|
if (result.requires_2fa && result.session_id) {
|
|
4620
4659
|
authLogger.info("2FA required, session:", result.session_id);
|