Handle invalid return-to payloads without misclassifying login as failed
Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
@@ -71,16 +71,20 @@ export const useLoginStore = defineStore("loginStore", {
|
|||||||
// However, if the user pasted a URL while not logged in,
|
// However, if the user pasted a URL while not logged in,
|
||||||
// redirect them to the remembered return-to URL after login.
|
// redirect them to the remembered return-to URL after login.
|
||||||
if (this.rememberedReturnToUrl !== "") {
|
if (this.rememberedReturnToUrl !== "") {
|
||||||
const decodedUrl = atob(this.rememberedReturnToUrl);
|
let decodedUrl = "";
|
||||||
|
try {
|
||||||
|
decodedUrl = atob(this.rememberedReturnToUrl);
|
||||||
|
} catch {
|
||||||
|
this.$router.push("/files");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Only allow relative paths to prevent open redirect attacks
|
// Only allow relative paths to prevent open redirect attacks
|
||||||
if (decodedUrl.startsWith("/") && !decodedUrl.startsWith("//")) {
|
if (decodedUrl.startsWith("/") && !decodedUrl.startsWith("//")) {
|
||||||
window.location.href = decodedUrl;
|
window.location.href = decodedUrl;
|
||||||
} else {
|
return;
|
||||||
this.$router.push("/files");
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
this.$router.push("/files");
|
|
||||||
}
|
}
|
||||||
|
this.$router.push("/files");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isInvalid = true;
|
this.isInvalid = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,22 @@ describe("loginStore", () => {
|
|||||||
window.location = originalLocation;
|
window.location = originalLocation;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("falls back to /files when return-to is not valid base64", async () => {
|
||||||
|
axios.post.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
access_token: "token",
|
||||||
|
refresh_token: "refresh",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
store.rememberedReturnToUrl = "@@@not-base64@@@";
|
||||||
|
|
||||||
|
await store.signIn();
|
||||||
|
|
||||||
|
expect(store.isLoggedIn).toBe(true);
|
||||||
|
expect(store.isInvalid).toBe(false);
|
||||||
|
expect(store.$router.push).toHaveBeenCalledWith("/files");
|
||||||
|
});
|
||||||
|
|
||||||
it("sets isInvalid on error", async () => {
|
it("sets isInvalid on error", async () => {
|
||||||
axios.post.mockRejectedValue(new Error("401"));
|
axios.post.mockRejectedValue(new Error("401"));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user