react-oauth icon indicating copy to clipboard operation
react-oauth copied to clipboard

Error 400: origin_mismatch

Open angelof-exe opened this issue 10 months ago • 0 comments

I dont know exactly if this problem is caused by this package, but I used it for the last 2 weeks and today my Google Login stopped to work on my desktop PC, while I can login on my smartphone.

Image

The detailer error is :

Error 400: origin_mismatch
Richiedi dettagli: origin=https://www.<DOMAIN>.it flowName=GeneralOAuthFlow 

This is the code

export const LoginPage: React.FC<LoginPageProps> = ({ onLogin }) => {
  const [error, setError] = useState<string | null>(null);
  const [isRateLimited, setIsRateLimited] = useState(false);
  const [remainingTime, setRemainingTime] = useState<number | null>(null);

  useEffect(() => {
    const sessionExpired = localStorage.getItem("sessionExpired");
    if (sessionExpired === "true") {
      setError("La sessione è scaduta. Rifare l'accesso.");
      localStorage.removeItem("sessionExpired");
    }
  }, []);

  const handleGoogleLogin = async (credentialResponse: any) => {
    try {
      const loginResponse = await apiClient.post<LoginResponse>("/login", {
        token: credentialResponse.credential,
      });

      const { user_id } = loginResponse.data;

      // Set auth data in localStorage
      localStorage.setItem("userId", String(user_id));
      localStorage.setItem("isAuthenticated", "true");

      // Fetch user profile
      const profileResponse = await apiClient.get<UserProfile>(
        `/get_user_profile/${user_id}`
      );

      // Store user data
      localStorage.setItem("user_fullName", profileResponse.data.full_name);
      localStorage.setItem("user_mainColor", profileResponse.data.color);
      localStorage.setItem(
        "user_isDriver",
        String(profileResponse.data.is_driver)
      );

      // Update auth state
      onLogin();
    } catch (err) {
      const error = err as AxiosError;
      if (error.response) {
        const { status, headers, data } = error.response;
        if (status === 401) {
          setError("Credenziali errate. Riprova.");
        } else if (status === 429) {
          setIsRateLimited(true);
          const retryAfter = parseInt(headers?.["retry-after"] || "60", 10);
          setRemainingTime(retryAfter);
          setError(
            `Troppi tentativi falliti. Riprova tra ${retryAfter} secondi.`
          );
        } else {
          setError(
            (data as { msg?: string })?.msg ||
              "Si è verificato un errore. Riprova più tardi."
          );
        }
      } else {
        setError("Errore di connessione al server. Riprova più tardi.");
      }
    }
  };

  useEffect(() => {
    let timer: ReturnType<typeof setTimeout>;
    if (isRateLimited && remainingTime) {
      timer = setInterval(() => {
        setRemainingTime((prev) => {
          if (prev && prev > 1) return prev - 1;
          setIsRateLimited(false);
          setError(null);
          clearInterval(timer);
          return null;
        });
      }, 1000);
    }
    return () => clearInterval(timer);
  }, [isRateLimited, remainingTime]);

  const theme = createTheme(themeOptions);
  return (
    <GoogleOAuthProvider clientId={import.meta.env.VITE_GOOGLE_CLIENT_ID}>
      <ThemeProvider theme={theme}>
        <Box
          sx={{
            height: "80vh",
            display: "flex",
            flexDirection: "column",
            justifyContent: "center",
            alignItems: "center",
            backgroundColor: "inherit",
          }}
        >
          <Box
            sx={{
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
              marginBottom: 4,
            }}
          >
            <SvgIcon
              component={Icon}
              sx={{
                fontSize: 100,
                display: "flex",
              }}
            >
              <img src={"favicon.svg"} alt="logo" />
            </SvgIcon>
            <Typography
              variant="h4"
              sx={{ fontSize: 50, color: "#01579b" }}
              textAlign="center"
              paddingBottom={2}
            >
              SIKAMANAGE
            </Typography>
          </Box>
          <Box
            sx={{
              width: { xs: "80%", sm: 400 },
              height: 200,
              padding: 2,
              backgroundColor: "white",
              boxShadow: 3,
              display: "flex",
              flexDirection: "column",
              justifyContent: "center",
              alignItems: "center",
            }}
          >
            <Typography
              variant="h4"
              gutterBottom
              textAlign="center"
              sx={{ fontWeight: 900 }}
            >
              LOGIN
            </Typography>
            {error && (
              <Typography color="error" variant="body2" textAlign="center">
                {error}
              </Typography>
            )}
            <GoogleLogin
              theme="filled_black"
              size="large"
              onSuccess={handleGoogleLogin}
              onError={() => setError("Google login failed")}
            />
            {isRateLimited && remainingTime && (
              <Typography
                variant="body2"
                color="textSecondary"
                textAlign="center"
                sx={{ marginTop: 1 }}
              >
                Attendi {remainingTime} secondi prima di riprovare.
              </Typography>
            )}
          </Box>
        </Box>
      </ThemeProvider>
    </GoogleOAuthProvider>
  );
};

EDIT: I attach the JavaScript Origin authorized and the Authorized URIs

Image

angelof-exe avatar Jan 30 '25 09:01 angelof-exe