mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-15 17:36:37 +00:00
successful log in loop poc
This commit is contained in:
@@ -4,56 +4,58 @@ import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { createApiClient, formatAxiosError } from "@app/lib/api";
|
||||
import { ValidateOidcUrlCallbackResponse } from "@server/routers/idp";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
type ValidateOidcTokenParams = {
|
||||
orgId: string;
|
||||
idpId: string;
|
||||
code: string | undefined;
|
||||
verifier: string | undefined;
|
||||
storedState: string | undefined;
|
||||
expectedState: string | undefined;
|
||||
stateCookie: string | undefined;
|
||||
};
|
||||
|
||||
export default function ValidateOidcToken(props: ValidateOidcTokenParams) {
|
||||
const { env } = useEnvContext();
|
||||
const api = createApiClient({ env });
|
||||
const router = useRouter();
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.code || !props.verifier) {
|
||||
setError("Missing code or verifier");
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!props.storedState) {
|
||||
setError("Missing stored state");
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.storedState !== props.expectedState) {
|
||||
setError("Invalid state");
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
async function validate() {
|
||||
setLoading(true);
|
||||
|
||||
console.log("Validating OIDC token", {
|
||||
code: props.code,
|
||||
expectedState: props.expectedState,
|
||||
stateCookie: props.stateCookie
|
||||
});
|
||||
|
||||
try {
|
||||
const res = await api.post<
|
||||
AxiosResponse<ValidateOidcUrlCallbackResponse>
|
||||
>(
|
||||
`/auth/org/${props.orgId}/idp/${props.idpId}/oidc/validate-callback`,
|
||||
{
|
||||
code: props.code,
|
||||
codeVerifier: props.verifier
|
||||
}
|
||||
);
|
||||
>(`/auth/idp/${props.idpId}/oidc/validate-callback`, {
|
||||
code: props.code,
|
||||
state: props.expectedState,
|
||||
storedState: props.stateCookie
|
||||
});
|
||||
|
||||
console.log("Validate OIDC token response", res.data);
|
||||
|
||||
const redirectUrl = res.data.data.redirectUrl;
|
||||
|
||||
if (!redirectUrl) {
|
||||
router.push("/");
|
||||
}
|
||||
|
||||
if (redirectUrl.startsWith("http")) {
|
||||
window.location.href = res.data.data.redirectUrl; // TODO: validate this to make sure it's safe
|
||||
} else {
|
||||
router.push(res.data.data.redirectUrl);
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
setError(formatAxiosError(e, "Error validating OIDC token"));
|
||||
} finally {
|
||||
@@ -12,8 +12,7 @@ export default async function Page(props: {
|
||||
const searchParams = await props.searchParams;
|
||||
|
||||
const allCookies = await cookies();
|
||||
const stateCookie = allCookies.get("oidc_state")?.value;
|
||||
const verifier = allCookies.get("oidc_code_verifier")?.value;
|
||||
const stateCookie = allCookies.get("p_oidc_state")?.value;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -21,9 +20,8 @@ export default async function Page(props: {
|
||||
orgId={params.orgId}
|
||||
idpId={params.idpId}
|
||||
code={searchParams.code}
|
||||
storedState={stateCookie}
|
||||
expectedState={searchParams.state}
|
||||
verifier={verifier}
|
||||
stateCookie={stateCookie}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@@ -36,7 +36,7 @@ export default async function Page(props: {
|
||||
return (
|
||||
<>
|
||||
<VerifyEmailForm
|
||||
email={user.email}
|
||||
email={user.email!}
|
||||
redirect={redirectUrl}
|
||||
/>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user