mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat(infisical-pg): fixed radix issue, bugs in oauth and tag cascade on
This commit is contained in:
2
backend-pg/src/@types/fastify.d.ts
vendored
2
backend-pg/src/@types/fastify.d.ts
vendored
@@ -59,7 +59,7 @@ declare module "fastify" {
|
||||
};
|
||||
// passport data
|
||||
passportUser: {
|
||||
isCompleted: string;
|
||||
isUserCompleted: string;
|
||||
providerAuthToken: string;
|
||||
};
|
||||
auditLogInfo: Pick<TCreateAuditLogDTO, "userAgent" | "userAgentType" | "ipAddress" | "actor">;
|
||||
|
||||
@@ -12,8 +12,8 @@ export const createJunctionTable = (
|
||||
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
table.uuid(`${table1Name}Id`).unsigned().notNullable(); // Foreign key for table1
|
||||
table.uuid(`${table2Name}Id`).unsigned().notNullable(); // Foreign key for table2
|
||||
table.foreign(`${table1Name}Id`).references("id").inTable(table1Name);
|
||||
table.foreign(`${table2Name}Id`).references("id").inTable(table2Name);
|
||||
table.foreign(`${table1Name}Id`).references("id").inTable(table1Name).onDelete("CASCADE");
|
||||
table.foreign(`${table2Name}Id`).references("id").inTable(table2Name).onDelete("CASCADE");
|
||||
});
|
||||
|
||||
// one time logic
|
||||
|
||||
@@ -28,7 +28,8 @@ import {
|
||||
projectAdminPermissions,
|
||||
projectMemberPermissions,
|
||||
projectNoAccessPermissions,
|
||||
ProjectPermissionSet
|
||||
ProjectPermissionSet,
|
||||
projectViewerPermission
|
||||
} from "./project-permission";
|
||||
|
||||
type TPermissionServiceFactoryDep = {
|
||||
@@ -74,6 +75,8 @@ export const permissionServiceFactory = ({
|
||||
return projectAdminPermissions;
|
||||
case ProjectMembershipRole.Member:
|
||||
return projectMemberPermissions;
|
||||
case ProjectMembershipRole.Viewer:
|
||||
return projectViewerPermission;
|
||||
case ProjectMembershipRole.NoAccess:
|
||||
return projectNoAccessPermissions;
|
||||
case ProjectMembershipRole.Custom:
|
||||
|
||||
@@ -114,6 +114,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
|
||||
authMethod: AuthMethod.GITLAB,
|
||||
callbackPort: req.query.state as string
|
||||
});
|
||||
console.log({ isUserCompleted, providerAuthToken });
|
||||
|
||||
return cb(null, { isUserCompleted, providerAuthToken });
|
||||
}
|
||||
@@ -152,7 +153,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
|
||||
// this is due to zod type difference
|
||||
}) as any,
|
||||
handler: (req, res) => {
|
||||
if (req.passportUser.isCompleted) {
|
||||
if (req.passportUser.isUserCompleted) {
|
||||
return res.redirect(
|
||||
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(
|
||||
req.passportUser.providerAuthToken
|
||||
@@ -197,7 +198,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
|
||||
// this is due to zod type difference
|
||||
}) as any,
|
||||
handler: (req, res) => {
|
||||
if (req.passportUser.isCompleted) {
|
||||
if (req.passportUser.isUserCompleted) {
|
||||
return res.redirect(
|
||||
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(
|
||||
req.passportUser.providerAuthToken
|
||||
@@ -242,7 +243,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
|
||||
// this is due to zod type difference
|
||||
}) as any,
|
||||
handler: (req, res) => {
|
||||
if (req.passportUser.isCompleted) {
|
||||
if (req.passportUser.isUserCompleted) {
|
||||
return res.redirect(
|
||||
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(
|
||||
req.passportUser.providerAuthToken
|
||||
|
||||
@@ -66,6 +66,7 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
||||
email: req.body.email,
|
||||
ip: req.realIp,
|
||||
userAgent,
|
||||
providerAuthToken: req.body.providerAuthToken,
|
||||
clientProof: req.body.clientProof
|
||||
});
|
||||
|
||||
|
||||
@@ -86,7 +86,8 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
||||
await server.services.signup.completeEmailAccountSignup({
|
||||
...req.body,
|
||||
ip: req.realIp,
|
||||
userAgent
|
||||
userAgent,
|
||||
authorization: req.headers.authorization
|
||||
});
|
||||
|
||||
res.setCookie("jid", refreshToken, {
|
||||
|
||||
50
backend-pg/src/services/auth/auth-fns.ts
Normal file
50
backend-pg/src/services/auth/auth-fns.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import jwt from "jsonwebtoken";
|
||||
import {
|
||||
AuthModeProviderJwtTokenPayload,
|
||||
AuthModeProviderSignUpTokenPayload,
|
||||
AuthTokenType
|
||||
} from "./auth-type";
|
||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||
|
||||
export const validateProviderAuthToken = (providerToken: string, email: string) => {
|
||||
if (!providerToken) throw new UnauthorizedError();
|
||||
const appCfg = getConfig();
|
||||
const decodedToken = jwt.verify(
|
||||
providerToken,
|
||||
appCfg.JWT_AUTH_SECRET
|
||||
) as AuthModeProviderJwtTokenPayload;
|
||||
|
||||
console.log(decodedToken);
|
||||
if (decodedToken.authTokenType !== AuthTokenType.PROVIDER_TOKEN) throw new UnauthorizedError();
|
||||
if (decodedToken.email !== email) throw new Error("Invalid auth credentials");
|
||||
};
|
||||
|
||||
export const validateSignUpAuthorization = async (token: string, userId: string) => {
|
||||
const appCfg = getConfig();
|
||||
const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>token?.split(" ", 2) ?? [
|
||||
null,
|
||||
null
|
||||
];
|
||||
if (AUTH_TOKEN_TYPE === null) {
|
||||
throw new BadRequestError({ message: "Missing Authorization Header in the request header." });
|
||||
}
|
||||
if (AUTH_TOKEN_TYPE.toLowerCase() !== "bearer") {
|
||||
throw new BadRequestError({
|
||||
message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.`
|
||||
});
|
||||
}
|
||||
if (AUTH_TOKEN_VALUE === null) {
|
||||
throw new BadRequestError({
|
||||
message: "Missing Authorization Body in the request header"
|
||||
});
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(
|
||||
AUTH_TOKEN_VALUE,
|
||||
appCfg.JWT_AUTH_SECRET
|
||||
) as AuthModeProviderSignUpTokenPayload;
|
||||
|
||||
if (decodedToken.authTokenType !== AuthTokenType.SIGNUP_TOKEN) throw new UnauthorizedError();
|
||||
if (decodedToken.userId !== userId) throw new UnauthorizedError();
|
||||
};
|
||||
@@ -16,15 +16,7 @@ import {
|
||||
TVerifyMfaTokenDTO
|
||||
} from "./auth-login-type";
|
||||
import { AuthMethod, AuthTokenType } from "./auth-type";
|
||||
|
||||
const isValidProviderAuthToken = (email: string, jwtSecret: string, providerAuthToken?: string) => {
|
||||
if (!providerAuthToken) return false;
|
||||
const decodedToken = jwt.verify(providerAuthToken, jwtSecret) as jwt.JwtPayload;
|
||||
|
||||
if (decodedToken.authTokenType !== AuthTokenType.PROVIDER_TOKEN) return false;
|
||||
if (decodedToken.email !== email) return false;
|
||||
return true;
|
||||
};
|
||||
import { validateProviderAuthToken } from "./auth-fns";
|
||||
|
||||
type TAuthLoginServiceFactoryDep = {
|
||||
userDal: TUserDalFactory;
|
||||
@@ -136,13 +128,10 @@ export const authLoginServiceFactory = ({
|
||||
if (!userEnc || (userEnc && !userEnc.isAccepted)) {
|
||||
throw new Error("Failed to find user");
|
||||
}
|
||||
const cfg = getConfig();
|
||||
if (
|
||||
!userEnc.authMethods?.includes(AuthMethod.EMAIL) &&
|
||||
!isValidProviderAuthToken(email, cfg.JWT_AUTH_SECRET, providerAuthToken)
|
||||
) {
|
||||
throw new Error("Invalid authorization request");
|
||||
if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) {
|
||||
validateProviderAuthToken(providerAuthToken as string, email);
|
||||
}
|
||||
|
||||
const serverSrpKey = await generateSrpServerKey(userEnc.salt, userEnc.verifier);
|
||||
const userEncKeys = await userDal.updateUserEncryptionByUserId(userEnc.userId, {
|
||||
clientPublicKey,
|
||||
@@ -166,11 +155,8 @@ export const authLoginServiceFactory = ({
|
||||
if (!userEnc) throw new Error("Failed to find user");
|
||||
const cfg = getConfig();
|
||||
|
||||
if (
|
||||
!userEnc.authMethods?.includes(AuthMethod.EMAIL) &&
|
||||
!isValidProviderAuthToken(email, cfg.JWT_AUTH_SECRET, providerAuthToken)
|
||||
) {
|
||||
throw new Error("Invalid authorization request");
|
||||
if (!userEnc.authMethods?.includes(AuthMethod.EMAIL)) {
|
||||
validateProviderAuthToken(providerAuthToken as string, email);
|
||||
}
|
||||
|
||||
if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey)
|
||||
@@ -252,7 +238,6 @@ export const authLoginServiceFactory = ({
|
||||
}
|
||||
const isLinkingRequired = !user?.authMethods?.includes(authMethod);
|
||||
const isUserCompleted = user.isAccepted;
|
||||
|
||||
const providerAuthToken = jwt.sign(
|
||||
{
|
||||
authTokenType: AuthTokenType.PROVIDER_TOKEN,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { TUserDalFactory } from "../user/user-dal";
|
||||
import { TAuthDalFactory } from "./auth-dal";
|
||||
import { TCompleteAccountInviteDTO, TCompleteAccountSignupDTO } from "./auth-signup-type";
|
||||
import { AuthMethod, AuthTokenType } from "./auth-type";
|
||||
import { validateProviderAuthToken, validateSignUpAuthorization } from "./auth-fns";
|
||||
|
||||
type TAuthSignupDep = {
|
||||
authDal: TAuthDalFactory;
|
||||
@@ -98,7 +99,7 @@ export const authSignupServiceFactory = ({
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
// providerAuthToken,
|
||||
providerAuthToken,
|
||||
salt,
|
||||
verifier,
|
||||
publicKey,
|
||||
@@ -111,13 +112,20 @@ export const authSignupServiceFactory = ({
|
||||
encryptedPrivateKeyIV,
|
||||
encryptedPrivateKeyTag,
|
||||
ip,
|
||||
userAgent
|
||||
userAgent,
|
||||
authorization
|
||||
}: TCompleteAccountSignupDTO) => {
|
||||
const user = await userDal.findUserByEmail(email);
|
||||
if (!user || (user && user.isAccepted)) {
|
||||
throw new Error("Failed to complete account for complete user");
|
||||
}
|
||||
|
||||
if (providerAuthToken) {
|
||||
validateProviderAuthToken(providerAuthToken, user.email);
|
||||
} else {
|
||||
validateSignUpAuthorization(authorization, user.id);
|
||||
}
|
||||
|
||||
const updateduser = await authDal.transaction(async (tx) => {
|
||||
const us = await userDal.updateById(user.id, { firstName, lastName, isAccepted: true }, tx);
|
||||
if (!us) throw new Error("User not found");
|
||||
|
||||
@@ -16,6 +16,7 @@ export type TCompleteAccountSignupDTO = {
|
||||
attributionSource?: string | undefined;
|
||||
ip: string;
|
||||
userAgent: string;
|
||||
authorization: string;
|
||||
};
|
||||
|
||||
export type TCompleteAccountInviteDTO = {
|
||||
|
||||
@@ -47,3 +47,13 @@ export type AuthModeRefreshJwtTokenPayload = {
|
||||
tokenVersionId: string;
|
||||
refreshVersion: number;
|
||||
};
|
||||
|
||||
export type AuthModeProviderJwtTokenPayload = {
|
||||
authTokenType: AuthTokenType.PROVIDER_TOKEN;
|
||||
email: string;
|
||||
};
|
||||
|
||||
export type AuthModeProviderSignUpTokenPayload = {
|
||||
authTokenType: AuthTokenType.SIGNUP_TOKEN;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
49283
frontend/package-lock.json
generated
49283
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,9 +12,6 @@
|
||||
"storybook": "storybook dev -p 6006 -s ./public",
|
||||
"build-storybook": "storybook build"
|
||||
},
|
||||
"overrides": {
|
||||
"@radix-ui/react-focus-scope": "1.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@casl/ability": "^6.5.0",
|
||||
"@casl/react": "^3.1.0",
|
||||
@@ -34,19 +31,19 @@
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||
"@radix-ui/react-checkbox": "^1.0.1",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
||||
"@radix-ui/react-hover-card": "^1.0.3",
|
||||
"@radix-ui/react-label": "^2.0.0",
|
||||
"@radix-ui/react-popover": "^1.0.3",
|
||||
"@radix-ui/react-popper": "^1.1.1",
|
||||
"@radix-ui/react-progress": "^1.0.1",
|
||||
"@radix-ui/react-hover-card": "^1.0.7",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-popover": "^1.0.7",
|
||||
"@radix-ui/react-popper": "^1.1.3",
|
||||
"@radix-ui/react-progress": "^1.0.3",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
"@radix-ui/react-switch": "^1.0.1",
|
||||
"@radix-ui/react-tabs": "^1.0.2",
|
||||
"@radix-ui/react-toast": "^1.1.2",
|
||||
"@radix-ui/react-tooltip": "^1.0.4",
|
||||
"@radix-ui/react-switch": "^1.0.3",
|
||||
"@radix-ui/react-tabs": "^1.0.4",
|
||||
"@radix-ui/react-toast": "^1.1.5",
|
||||
"@radix-ui/react-tooltip": "^1.0.7",
|
||||
"@reduxjs/toolkit": "^1.8.3",
|
||||
"@stripe/react-stripe-js": "^1.16.3",
|
||||
"@stripe/stripe-js": "^1.46.0",
|
||||
|
||||
@@ -6,14 +6,22 @@ export const createJunctionTable = (
|
||||
knex: Knex,
|
||||
tableName: TableName,
|
||||
table1Name: TableName,
|
||||
table2Name: TableName
|
||||
table2Name: TableName,
|
||||
) =>
|
||||
knex.schema.createTable(tableName, (table) => {
|
||||
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
table.uuid(`${table1Name}Id`).unsigned().notNullable(); // Foreign key for table1
|
||||
table.uuid(`${table2Name}Id`).unsigned().notNullable(); // Foreign key for table2
|
||||
table.foreign(`${table1Name}Id`).references("id").inTable(table1Name);
|
||||
table.foreign(`${table2Name}Id`).references("id").inTable(table2Name);
|
||||
table
|
||||
.foreign(`${table1Name}Id`)
|
||||
.references("id")
|
||||
.inTable(table1Name)
|
||||
.onDelete("CASCADE");
|
||||
table
|
||||
.foreign(`${table2Name}Id`)
|
||||
.references("id")
|
||||
.inTable(table2Name)
|
||||
.onDelete("CASCADE");
|
||||
});
|
||||
|
||||
// one time logic
|
||||
|
||||
Reference in New Issue
Block a user