mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
misc: resolve shared secret within org and added login redirect
This commit is contained in:
@@ -206,8 +206,13 @@ export const secretSharingServiceFactory = ({
|
||||
|
||||
const orgName = sharedSecret.orgId ? (await orgDAL.findOrgById(sharedSecret.orgId))?.name : "";
|
||||
|
||||
if (accessType === SecretSharingAccessType.Organization && orgId !== sharedSecret.orgId)
|
||||
if (accessType === SecretSharingAccessType.Organization && orgId === undefined) {
|
||||
throw new UnauthorizedError();
|
||||
}
|
||||
|
||||
if (accessType === SecretSharingAccessType.Organization && orgId !== sharedSecret.orgId) {
|
||||
throw new ForbiddenRequestError();
|
||||
}
|
||||
|
||||
// all secrets pass through here, meaning we check if its expired first and then check if it needs verification
|
||||
// or can be safely sent to the client.
|
||||
|
||||
@@ -58,7 +58,8 @@ export const leaveConfirmDefaultMessage =
|
||||
"Your changes will be lost if you leave the page. Are you sure you want to continue?";
|
||||
|
||||
export enum SessionStorageKeys {
|
||||
CLI_TERMINAL_TOKEN = "CLI_TERMINAL_TOKEN"
|
||||
CLI_TERMINAL_TOKEN = "CLI_TERMINAL_TOKEN",
|
||||
ORG_LOGIN_SUCCESS_REDIRECT_URL = "ORG_LOGIN_SUCCESS_REDIRECT_URL"
|
||||
}
|
||||
|
||||
export const secretTagsColors = [
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||
import { apiRequest } from "@app/config/request";
|
||||
import { SessionStorageKeys } from "@app/const";
|
||||
|
||||
import { organizationKeys } from "../organization/queries";
|
||||
import { setAuthToken } from "../reactQuery";
|
||||
@@ -86,6 +87,21 @@ export const useSelectOrganization = () => {
|
||||
SecurityClient.setProviderAuthToken("");
|
||||
}
|
||||
|
||||
if (data.token && !data.isMfaEnabled) {
|
||||
// We check if there is a pending callback after organization login success and redirect to it if valid
|
||||
const loginRedirectInfo = sessionStorage.getItem(
|
||||
SessionStorageKeys.ORG_LOGIN_SUCCESS_REDIRECT_URL
|
||||
);
|
||||
sessionStorage.removeItem(SessionStorageKeys.ORG_LOGIN_SUCCESS_REDIRECT_URL);
|
||||
|
||||
if (loginRedirectInfo) {
|
||||
const { expiry, data: redirectUrl } = JSON.parse(loginRedirectInfo);
|
||||
if (new Date() < new Date(expiry)) {
|
||||
window.location.assign(redirectUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useParams, useSearch } from "@tanstack/react-router";
|
||||
import { useNavigate, useParams, useSearch } from "@tanstack/react-router";
|
||||
import { AxiosError } from "axios";
|
||||
import { addSeconds, formatISO } from "date-fns";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { SessionStorageKeys } from "@app/const";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { useGetActiveSharedSecretById } from "@app/hooks/api/secretSharing";
|
||||
|
||||
@@ -36,7 +39,6 @@ export const ViewSharedSecretByIDPage = () => {
|
||||
select: (el) => el.key
|
||||
});
|
||||
const [password, setPassword] = useState<string>();
|
||||
|
||||
const { hashedHex, key } = extractDetailsFromUrl(urlEncodedKey);
|
||||
|
||||
const {
|
||||
@@ -50,10 +52,47 @@ export const ViewSharedSecretByIDPage = () => {
|
||||
password
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const isUnauthorized =
|
||||
((error as AxiosError)?.response?.data as { statusCode: number })?.statusCode === 401;
|
||||
|
||||
const isForbidden =
|
||||
((error as AxiosError)?.response?.data as { statusCode: number })?.statusCode === 403;
|
||||
|
||||
const isInvalidCredential =
|
||||
((error as AxiosError)?.response?.data as { message: string })?.message ===
|
||||
"Invalid credentials";
|
||||
|
||||
useEffect(() => {
|
||||
if (isUnauthorized && !isInvalidCredential) {
|
||||
// persist current URL in session storage so that we can come back to this after successful login
|
||||
sessionStorage.setItem(
|
||||
SessionStorageKeys.ORG_LOGIN_SUCCESS_REDIRECT_URL,
|
||||
JSON.stringify({
|
||||
expiry: formatISO(addSeconds(new Date(), 60)),
|
||||
data: window.location.href
|
||||
})
|
||||
);
|
||||
|
||||
createNotification({
|
||||
type: "info",
|
||||
text: "Login is required in order to access the shared secret."
|
||||
});
|
||||
|
||||
navigate({
|
||||
to: "/login"
|
||||
});
|
||||
}
|
||||
|
||||
if (isForbidden) {
|
||||
createNotification({
|
||||
type: "error",
|
||||
text: "You do not have access to this shared secret."
|
||||
});
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
const shouldShowPasswordPrompt =
|
||||
isInvalidCredential || (fetchSecret?.isPasswordProtected && !fetchSecret.secret);
|
||||
const isValidatingPassword = Boolean(password) && isFetching;
|
||||
@@ -111,7 +150,7 @@ export const ViewSharedSecretByIDPage = () => {
|
||||
{!error && fetchSecret?.secret && (
|
||||
<SecretContainer secret={fetchSecret.secret} secretKey={key} />
|
||||
)}
|
||||
{error && !isInvalidCredential && <SecretErrorContainer />}
|
||||
{error && !isInvalidCredential && !isUnauthorized && <SecretErrorContainer />}
|
||||
</>
|
||||
)}
|
||||
<div className="m-auto my-8 flex w-full">
|
||||
|
||||
@@ -2,6 +2,8 @@ import { createFileRoute, stripSearchParams } from "@tanstack/react-router";
|
||||
import { zodValidator } from "@tanstack/zod-adapter";
|
||||
import { z } from "zod";
|
||||
|
||||
import { authKeys, fetchAuthToken } from "@app/hooks/api/auth/queries";
|
||||
|
||||
import { ViewSharedSecretByIDPage } from "./ViewSharedSecretByIDPage";
|
||||
|
||||
const SharedSecretByIDPageQuerySchema = z.object({
|
||||
@@ -9,9 +11,18 @@ const SharedSecretByIDPageQuerySchema = z.object({
|
||||
});
|
||||
|
||||
export const Route = createFileRoute("/shared/secret/$secretId")({
|
||||
component: ViewSharedSecretByIDPage,
|
||||
validateSearch: zodValidator(SharedSecretByIDPageQuerySchema),
|
||||
component: ViewSharedSecretByIDPage,
|
||||
search: {
|
||||
middlewares: [stripSearchParams({ key: "" })]
|
||||
},
|
||||
beforeLoad: async ({ context }) => {
|
||||
// we load the auth token because the view shared secret screen serves both public and authenticated users
|
||||
await context.queryClient
|
||||
.ensureQueryData({
|
||||
queryKey: authKeys.getAuthToken,
|
||||
queryFn: fetchAuthToken
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user