fix: prevent infinite redirect oauth auth flow (#10430)

* fix: prevent infinite redirect oauth auth flow
This commit is contained in:
Steven Masley
2023-10-30 15:45:06 -04:00
committed by GitHub
parent 7fc1a65b14
commit 9d2b805fb7
2 changed files with 38 additions and 3 deletions

View File

@ -268,8 +268,9 @@ func (api *API) externalAuthCallback(externalAuthConfig *externalauth.Config) ht
redirect := state.Redirect
if redirect == "" {
// This is a nicely rendered screen on the frontend
redirect = fmt.Sprintf("/external-auth/%s", externalAuthConfig.ID)
// This is a nicely rendered screen on the frontend. Passing the query param lets the
// FE know not to enter the authentication loop again, and instead display an error.
redirect = fmt.Sprintf("/external-auth/%s?redirected=true", externalAuthConfig.ID)
}
http.Redirect(rw, r, redirect, http.StatusTemporaryRedirect)
}

View File

@ -6,16 +6,21 @@ import {
} from "api/api";
import { usePermissions } from "hooks";
import { type FC } from "react";
import { useParams } from "react-router-dom";
import { useParams, useSearchParams } from "react-router-dom";
import ExternalAuthPageView from "./ExternalAuthPageView";
import { ApiErrorResponse } from "api/errors";
import { isAxiosError } from "axios";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import { SignInLayout } from "components/SignInLayout/SignInLayout";
import { Welcome } from "components/Welcome/Welcome";
const ExternalAuthPage: FC = () => {
const { provider } = useParams();
if (!provider) {
throw new Error("provider must exist");
}
const [searchParams] = useSearchParams();
const permissions = usePermissions();
const queryClient = useQueryClient();
const getExternalAuthProviderQuery = useQuery({
@ -72,6 +77,35 @@ const ExternalAuthPage: FC = () => {
!getExternalAuthProviderQuery.data.authenticated &&
!getExternalAuthProviderQuery.data.device
) {
const redirectedParam = searchParams?.get("redirected");
if (redirectedParam && redirectedParam.toLowerCase() === "true") {
// The auth flow redirected the user here. If we redirect back to the
// callback, that resets the flow and we'll end up in an infinite loop.
// So instead, show an error, as the user expects to be authenticated at
// this point.
// TODO: Unsure what to do about the device auth flow, should we also
// show an error there?
return (
<SignInLayout>
<Welcome message="Failed to validate oauth access token" />
<Box textAlign="center">
Attempted to validate the user&apos;s oauth access token from the
authentication flow. This situation may occur as a result of an
external authentication provider misconfiguration. Verify the
external authentication validation URL is accurately configured.
</Box>
<br />
<Button
onClick={() => {
// Redirect to the auth flow again. *crosses fingers*
window.location.href = `/external-auth/${provider}/callback`;
}}
>
Retry
</Button>
</SignInLayout>
);
}
window.location.href = `/external-auth/${provider}/callback`;
return null;
}