fix(login): split passwordLogin / devLogin so SIGN IN cannot bypass
Oracle round-3 finding: passing password=undefined to api.signIn silently
hit /api/v1/auth/dev-login. With dev-login disabled in a production
build, a buyer typing only their email and pressing SIGN IN would still
have been authenticated as that user.
- api.passwordLogin(email, password) explicitly requires a password and
always hits /api/v1/auth/login. Throws on missing password.
- api.devLogin(email) explicitly hits /api/v1/auth/dev-login and is the
only entry point to that endpoint.
- store.loginAs(email, password, { method: 'password' | 'dev' }) routes
to the right call. Default is password (requires password).
- Login.handleSubmit rejects empty password with 'Password required'
before any network call.
- Login.handleDevLogin bails when devLoginEnabled is false.
- SSO button is disabled while probe state is 'unknown'.
- Login.test.tsx: regression test 'blocks empty-password SIGN IN —
must NOT silently call dev-login'. Plus SSO test asserts the button
starts disabled.
29/29 unit tests green.
This commit is contained in:
+8
-3
@@ -96,7 +96,7 @@ interface AppState {
|
||||
userDisplayName: string | null;
|
||||
isAuthed: boolean;
|
||||
setUserEmail: (e: string) => void;
|
||||
loginAs: (email: string, password?: string) => Promise<void>;
|
||||
loginAs: (email: string, password?: string, options?: { method?: "password" | "dev" }) => Promise<void>;
|
||||
|
||||
/** Live polling — lightweight tick that only refreshes the active
|
||||
* scenario's work-items + headline runtime. Full refresh is manual. */
|
||||
@@ -258,13 +258,18 @@ export const useApp = create<AppState>((set, get) => {
|
||||
userDisplayName: null,
|
||||
isAuthed: typeof sessionStorage !== "undefined" && !!sessionStorage.getItem("fm.mc.token.v1"),
|
||||
setUserEmail: (e) => { set({ userEmail: e }); persist(); },
|
||||
loginAs: async (email, password) => {
|
||||
loginAs: async (email, password, options) => {
|
||||
api.clearToken();
|
||||
api.config = { ...api.config, email };
|
||||
set({ userEmail: email });
|
||||
persist();
|
||||
try {
|
||||
await api.signIn(email, password);
|
||||
if (options?.method === "dev") {
|
||||
await api.devLogin(email);
|
||||
} else {
|
||||
if (!password) throw new Error("Password required");
|
||||
await api.passwordLogin(email, password);
|
||||
}
|
||||
const me = await api.me();
|
||||
set({
|
||||
actor: { mode: "direct_user", user_id: me.user_id },
|
||||
|
||||
Reference in New Issue
Block a user