mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: added support for limiting email domains
This commit is contained in:
@@ -17,6 +17,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
tb.text("encryptedClientSecret").notNullable();
|
tb.text("encryptedClientSecret").notNullable();
|
||||||
tb.string("clientSecretIV").notNullable();
|
tb.string("clientSecretIV").notNullable();
|
||||||
tb.string("clientSecretTag").notNullable();
|
tb.string("clientSecretTag").notNullable();
|
||||||
|
tb.string("allowedEmailDomains").nullable();
|
||||||
tb.boolean("isActive").notNullable();
|
tb.boolean("isActive").notNullable();
|
||||||
tb.timestamps(true, true, true);
|
tb.timestamps(true, true, true);
|
||||||
tb.uuid("orgId").notNullable().unique();
|
tb.uuid("orgId").notNullable().unique();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const OidcConfigsSchema = z.object({
|
|||||||
encryptedClientSecret: z.string(),
|
encryptedClientSecret: z.string(),
|
||||||
clientSecretIV: z.string(),
|
clientSecretIV: z.string(),
|
||||||
clientSecretTag: z.string(),
|
clientSecretTag: z.string(),
|
||||||
|
allowedEmailDomains: z.string().nullable().optional(),
|
||||||
isActive: z.boolean(),
|
isActive: z.boolean(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
|
|||||||
@@ -137,7 +137,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
tokenEndpoint: true,
|
tokenEndpoint: true,
|
||||||
userinfoEndpoint: true,
|
userinfoEndpoint: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
orgId: true
|
orgId: true,
|
||||||
|
allowedEmailDomains: true
|
||||||
}).extend({
|
}).extend({
|
||||||
clientId: z.string(),
|
clientId: z.string(),
|
||||||
clientSecret: z.string()
|
clientSecret: z.string()
|
||||||
@@ -169,6 +170,19 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
|
allowedEmailDomains: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.optional()
|
||||||
|
.default("")
|
||||||
|
.transform((data) => {
|
||||||
|
if (data === "") return "";
|
||||||
|
// Trim each ID and join with ', ' to ensure formatting
|
||||||
|
return data
|
||||||
|
.split(",")
|
||||||
|
.map((id) => id.trim())
|
||||||
|
.join(", ");
|
||||||
|
}),
|
||||||
issuer: z.string().trim(),
|
issuer: z.string().trim(),
|
||||||
authorizationEndpoint: z.string().trim(),
|
authorizationEndpoint: z.string().trim(),
|
||||||
jwksUri: z.string().trim(),
|
jwksUri: z.string().trim(),
|
||||||
@@ -189,6 +203,7 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
tokenEndpoint: true,
|
tokenEndpoint: true,
|
||||||
userinfoEndpoint: true,
|
userinfoEndpoint: true,
|
||||||
orgId: true,
|
orgId: true,
|
||||||
|
allowedEmailDomains: true,
|
||||||
isActive: true
|
isActive: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -215,6 +230,19 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
issuer: z.string().trim(),
|
issuer: z.string().trim(),
|
||||||
|
allowedEmailDomains: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.optional()
|
||||||
|
.default("")
|
||||||
|
.transform((data) => {
|
||||||
|
if (data === "") return "";
|
||||||
|
// Trim each ID and join with ', ' to ensure formatting
|
||||||
|
return data
|
||||||
|
.split(",")
|
||||||
|
.map((id) => id.trim())
|
||||||
|
.join(", ");
|
||||||
|
}),
|
||||||
authorizationEndpoint: z.string().trim(),
|
authorizationEndpoint: z.string().trim(),
|
||||||
jwksUri: z.string().trim(),
|
jwksUri: z.string().trim(),
|
||||||
tokenEndpoint: z.string().trim(),
|
tokenEndpoint: z.string().trim(),
|
||||||
@@ -233,7 +261,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
tokenEndpoint: true,
|
tokenEndpoint: true,
|
||||||
userinfoEndpoint: true,
|
userinfoEndpoint: true,
|
||||||
orgId: true,
|
orgId: true,
|
||||||
isActive: true
|
isActive: true,
|
||||||
|
allowedEmailDomains: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -63,6 +63,86 @@ export const oidcConfigServiceFactory = ({
|
|||||||
smtpService,
|
smtpService,
|
||||||
oidcConfigDAL
|
oidcConfigDAL
|
||||||
}: TOidcConfigServiceFactoryDep) => {
|
}: TOidcConfigServiceFactoryDep) => {
|
||||||
|
const getOidc = async (dto: TGetOidcCfgDTO) => {
|
||||||
|
const org = await orgDAL.findOne({ slug: dto.orgSlug });
|
||||||
|
if (!org) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Organization not found",
|
||||||
|
name: "OrgNotFound"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (dto.type === "external") {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
dto.actor,
|
||||||
|
dto.actorId,
|
||||||
|
org.id,
|
||||||
|
dto.actorAuthMethod,
|
||||||
|
dto.actorOrgId
|
||||||
|
);
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso);
|
||||||
|
}
|
||||||
|
|
||||||
|
const oidcCfg = await oidcConfigDAL.findOne({
|
||||||
|
orgId: org.id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!oidcCfg) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Failed to find organization OIDC configuration"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrypt and return cfg
|
||||||
|
const orgBot = await orgBotDAL.findOne({ orgId: oidcCfg.orgId });
|
||||||
|
if (!orgBot) {
|
||||||
|
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = infisicalSymmetricDecrypt({
|
||||||
|
ciphertext: orgBot.encryptedSymmetricKey,
|
||||||
|
iv: orgBot.symmetricKeyIV,
|
||||||
|
tag: orgBot.symmetricKeyTag,
|
||||||
|
keyEncoding: orgBot.symmetricKeyKeyEncoding as SecretKeyEncoding
|
||||||
|
});
|
||||||
|
|
||||||
|
const { encryptedClientId, clientIdIV, clientIdTag, encryptedClientSecret, clientSecretIV, clientSecretTag } =
|
||||||
|
oidcCfg;
|
||||||
|
|
||||||
|
let clientId = "";
|
||||||
|
if (encryptedClientId && clientIdIV && clientIdTag) {
|
||||||
|
clientId = decryptSymmetric({
|
||||||
|
ciphertext: encryptedClientId,
|
||||||
|
key,
|
||||||
|
tag: clientIdTag,
|
||||||
|
iv: clientIdIV
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let clientSecret = "";
|
||||||
|
if (encryptedClientSecret && clientSecretIV && clientSecretTag) {
|
||||||
|
clientSecret = decryptSymmetric({
|
||||||
|
key,
|
||||||
|
tag: clientSecretTag,
|
||||||
|
iv: clientSecretIV,
|
||||||
|
ciphertext: encryptedClientSecret
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: oidcCfg.id,
|
||||||
|
issuer: oidcCfg.issuer,
|
||||||
|
authorizationEndpoint: oidcCfg.authorizationEndpoint,
|
||||||
|
jwksUri: oidcCfg.jwksUri,
|
||||||
|
tokenEndpoint: oidcCfg.tokenEndpoint,
|
||||||
|
userinfoEndpoint: oidcCfg.userinfoEndpoint,
|
||||||
|
orgId: oidcCfg.orgId,
|
||||||
|
isActive: oidcCfg.isActive,
|
||||||
|
allowedEmailDomains: oidcCfg.allowedEmailDomains,
|
||||||
|
clientId,
|
||||||
|
clientSecret
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const oidcLogin = async ({ externalId, email, firstName, lastName, orgId, callbackPort }: TOidcLoginDTO) => {
|
const oidcLogin = async ({ externalId, email, firstName, lastName, orgId, callbackPort }: TOidcLoginDTO) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
const userAlias = await userAliasDAL.findOne({
|
const userAlias = await userAliasDAL.findOne({
|
||||||
@@ -216,87 +296,9 @@ export const oidcConfigServiceFactory = ({
|
|||||||
return { isUserCompleted, providerAuthToken };
|
return { isUserCompleted, providerAuthToken };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOidc = async (dto: TGetOidcCfgDTO) => {
|
|
||||||
const org = await orgDAL.findOne({ slug: dto.orgSlug });
|
|
||||||
if (!org) {
|
|
||||||
throw new BadRequestError({
|
|
||||||
message: "Organization not found",
|
|
||||||
name: "OrgNotFound"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (dto.type === "external") {
|
|
||||||
const { permission } = await permissionService.getOrgPermission(
|
|
||||||
dto.actor,
|
|
||||||
dto.actorId,
|
|
||||||
org.id,
|
|
||||||
dto.actorAuthMethod,
|
|
||||||
dto.actorOrgId
|
|
||||||
);
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso);
|
|
||||||
}
|
|
||||||
|
|
||||||
const oidcCfg = await oidcConfigDAL.findOne({
|
|
||||||
orgId: org.id
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!oidcCfg) {
|
|
||||||
throw new BadRequestError({
|
|
||||||
message: "Failed to find organization OIDC configuration"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// decrypt and return cfg
|
|
||||||
const orgBot = await orgBotDAL.findOne({ orgId: oidcCfg.orgId });
|
|
||||||
if (!orgBot) {
|
|
||||||
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = infisicalSymmetricDecrypt({
|
|
||||||
ciphertext: orgBot.encryptedSymmetricKey,
|
|
||||||
iv: orgBot.symmetricKeyIV,
|
|
||||||
tag: orgBot.symmetricKeyTag,
|
|
||||||
keyEncoding: orgBot.symmetricKeyKeyEncoding as SecretKeyEncoding
|
|
||||||
});
|
|
||||||
|
|
||||||
const { encryptedClientId, clientIdIV, clientIdTag, encryptedClientSecret, clientSecretIV, clientSecretTag } =
|
|
||||||
oidcCfg;
|
|
||||||
|
|
||||||
let clientId = "";
|
|
||||||
if (encryptedClientId && clientIdIV && clientIdTag) {
|
|
||||||
clientId = decryptSymmetric({
|
|
||||||
ciphertext: encryptedClientId,
|
|
||||||
key,
|
|
||||||
tag: clientIdTag,
|
|
||||||
iv: clientIdIV
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let clientSecret = "";
|
|
||||||
if (encryptedClientSecret && clientSecretIV && clientSecretTag) {
|
|
||||||
clientSecret = decryptSymmetric({
|
|
||||||
key,
|
|
||||||
tag: clientSecretTag,
|
|
||||||
iv: clientSecretIV,
|
|
||||||
ciphertext: encryptedClientSecret
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: oidcCfg.id,
|
|
||||||
issuer: oidcCfg.issuer,
|
|
||||||
authorizationEndpoint: oidcCfg.authorizationEndpoint,
|
|
||||||
jwksUri: oidcCfg.jwksUri,
|
|
||||||
tokenEndpoint: oidcCfg.tokenEndpoint,
|
|
||||||
userinfoEndpoint: oidcCfg.userinfoEndpoint,
|
|
||||||
orgId: oidcCfg.orgId,
|
|
||||||
isActive: oidcCfg.isActive,
|
|
||||||
clientId,
|
|
||||||
clientSecret
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateOidcCfg = async ({
|
const updateOidcCfg = async ({
|
||||||
orgSlug,
|
orgSlug,
|
||||||
|
allowedEmailDomains,
|
||||||
actor,
|
actor,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
@@ -346,6 +348,7 @@ export const oidcConfigServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const updateQuery: TOidcConfigsUpdate = {
|
const updateQuery: TOidcConfigsUpdate = {
|
||||||
|
allowedEmailDomains,
|
||||||
issuer,
|
issuer,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
@@ -374,12 +377,12 @@ export const oidcConfigServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const [ssoConfig] = await oidcConfigDAL.update({ orgId: org.id }, updateQuery);
|
const [ssoConfig] = await oidcConfigDAL.update({ orgId: org.id }, updateQuery);
|
||||||
|
|
||||||
return ssoConfig;
|
return ssoConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
const createOidcCfg = async ({
|
const createOidcCfg = async ({
|
||||||
orgSlug,
|
orgSlug,
|
||||||
|
allowedEmailDomains,
|
||||||
actor,
|
actor,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
@@ -477,6 +480,7 @@ export const oidcConfigServiceFactory = ({
|
|||||||
issuer,
|
issuer,
|
||||||
isActive,
|
isActive,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
|
allowedEmailDomains,
|
||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
userinfoEndpoint,
|
userinfoEndpoint,
|
||||||
@@ -544,6 +548,15 @@ export const oidcConfigServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oidcCfg.allowedEmailDomains) {
|
||||||
|
const allowedDomains = oidcCfg.allowedEmailDomains.split(", ");
|
||||||
|
if (!allowedDomains.includes(claims.email.split("@")[1])) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Email not allowed."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
oidcLogin({
|
oidcLogin({
|
||||||
email: claims.email,
|
email: claims.email,
|
||||||
externalId: claims.sub,
|
externalId: claims.sub,
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export type TGetOidcCfgDTO =
|
|||||||
export type TCreateOidcCfgDTO = {
|
export type TCreateOidcCfgDTO = {
|
||||||
issuer: string;
|
issuer: string;
|
||||||
authorizationEndpoint: string;
|
authorizationEndpoint: string;
|
||||||
|
allowedEmailDomains: string;
|
||||||
jwksUri: string;
|
jwksUri: string;
|
||||||
tokenEndpoint: string;
|
tokenEndpoint: string;
|
||||||
userinfoEndpoint: string;
|
userinfoEndpoint: string;
|
||||||
@@ -34,6 +35,7 @@ export type TCreateOidcCfgDTO = {
|
|||||||
export type TUpdateOidcCfgDTO = Partial<{
|
export type TUpdateOidcCfgDTO = Partial<{
|
||||||
issuer: string;
|
issuer: string;
|
||||||
authorizationEndpoint: string;
|
authorizationEndpoint: string;
|
||||||
|
allowedEmailDomains: string;
|
||||||
jwksUri: string;
|
jwksUri: string;
|
||||||
tokenEndpoint: string;
|
tokenEndpoint: string;
|
||||||
userinfoEndpoint: string;
|
userinfoEndpoint: string;
|
||||||
|
|||||||
@@ -13,11 +13,13 @@ export const useUpdateOIDCConfig = () => {
|
|||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
userinfoEndpoint,
|
userinfoEndpoint,
|
||||||
|
allowedEmailDomains,
|
||||||
clientId,
|
clientId,
|
||||||
clientSecret,
|
clientSecret,
|
||||||
isActive,
|
isActive,
|
||||||
orgSlug
|
orgSlug
|
||||||
}: {
|
}: {
|
||||||
|
allowedEmailDomains?: string;
|
||||||
issuer?: string;
|
issuer?: string;
|
||||||
authorizationEndpoint?: string;
|
authorizationEndpoint?: string;
|
||||||
jwksUri?: string;
|
jwksUri?: string;
|
||||||
@@ -30,6 +32,7 @@ export const useUpdateOIDCConfig = () => {
|
|||||||
}) => {
|
}) => {
|
||||||
const { data } = await apiRequest.patch("/api/v1/sso/oidc/config", {
|
const { data } = await apiRequest.patch("/api/v1/sso/oidc/config", {
|
||||||
issuer,
|
issuer,
|
||||||
|
allowedEmailDomains,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
@@ -54,6 +57,7 @@ export const useCreateOIDCConfig = () => {
|
|||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
issuer,
|
issuer,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
|
allowedEmailDomains,
|
||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
userinfoEndpoint,
|
userinfoEndpoint,
|
||||||
@@ -71,10 +75,12 @@ export const useCreateOIDCConfig = () => {
|
|||||||
clientSecret: string;
|
clientSecret: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
orgSlug: string;
|
orgSlug: string;
|
||||||
|
allowedEmailDomains?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { data } = await apiRequest.post("/api/v1/sso/oidc/config", {
|
const { data } = await apiRequest.post("/api/v1/sso/oidc/config", {
|
||||||
issuer,
|
issuer,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
|
allowedEmailDomains,
|
||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
userinfoEndpoint,
|
userinfoEndpoint,
|
||||||
|
|||||||
@@ -9,4 +9,5 @@ export type OIDCConfigData = {
|
|||||||
orgId: string;
|
orgId: string;
|
||||||
clientId: string;
|
clientId: string;
|
||||||
clientSecret: string;
|
clientSecret: string;
|
||||||
|
allowedEmailDomains?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ const schema = z.object({
|
|||||||
tokenEndpoint: z.string().min(1),
|
tokenEndpoint: z.string().min(1),
|
||||||
userinfoEndpoint: z.string().min(1),
|
userinfoEndpoint: z.string().min(1),
|
||||||
clientId: z.string().min(1),
|
clientId: z.string().min(1),
|
||||||
clientSecret: z.string().min(1)
|
clientSecret: z.string().min(1),
|
||||||
|
allowedEmailDomains: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type OIDCFormData = z.infer<typeof schema>;
|
export type OIDCFormData = z.infer<typeof schema>;
|
||||||
@@ -48,12 +49,14 @@ export const OIDCModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
|
|||||||
setValue("userinfoEndpoint", data.userinfoEndpoint);
|
setValue("userinfoEndpoint", data.userinfoEndpoint);
|
||||||
setValue("clientId", data.clientId);
|
setValue("clientId", data.clientId);
|
||||||
setValue("clientSecret", data.clientSecret);
|
setValue("clientSecret", data.clientSecret);
|
||||||
|
setValue("allowedEmailDomains", data.allowedEmailDomains);
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
const onOIDCModalSubmit = async ({
|
const onOIDCModalSubmit = async ({
|
||||||
issuer,
|
issuer,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
|
allowedEmailDomains,
|
||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
userinfoEndpoint,
|
userinfoEndpoint,
|
||||||
@@ -67,6 +70,7 @@ export const OIDCModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
|
|||||||
await createMutateAsync({
|
await createMutateAsync({
|
||||||
issuer,
|
issuer,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
|
allowedEmailDomains,
|
||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
userinfoEndpoint,
|
userinfoEndpoint,
|
||||||
@@ -79,6 +83,7 @@ export const OIDCModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
|
|||||||
await updateMutateAsync({
|
await updateMutateAsync({
|
||||||
issuer,
|
issuer,
|
||||||
authorizationEndpoint,
|
authorizationEndpoint,
|
||||||
|
allowedEmailDomains,
|
||||||
jwksUri,
|
jwksUri,
|
||||||
tokenEndpoint,
|
tokenEndpoint,
|
||||||
userinfoEndpoint,
|
userinfoEndpoint,
|
||||||
@@ -187,6 +192,19 @@ export const OIDCModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="allowedEmailDomains"
|
||||||
|
render={({ field, fieldState: { error } }) => (
|
||||||
|
<FormControl
|
||||||
|
label="Allowed Email Domains (defaults to any)"
|
||||||
|
errorText={error?.message}
|
||||||
|
isError={Boolean(error)}
|
||||||
|
>
|
||||||
|
<Input {...field} placeholder="infisical.com, google.com" autoComplete="off" />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="clientId"
|
name="clientId"
|
||||||
|
|||||||
Reference in New Issue
Block a user