From b330fdbc58196137fe2696318be8e01307f89ac2 Mon Sep 17 00:00:00 2001 From: x Date: Tue, 22 Apr 2025 14:36:31 -0400 Subject: [PATCH 1/5] Admin SSO bypass (breakglass login) sends out email to all org admins + creates audit log --- .../ee/services/audit-log/audit-log-types.ts | 7 +++ .../src/ee/services/license/license-fns.ts | 6 +- backend/src/server/routes/index.ts | 9 ++- .../src/services/auth/auth-login-service.ts | 61 ++++++++++++++++++- backend/src/services/org/org-dal.ts | 39 ++++++++++++ backend/src/services/smtp/smtp-service.ts | 1 + .../orgAdminBreakglassAccess.handlebars | 20 ++++++ frontend/src/hooks/api/auditLogs/enums.tsx | 1 + frontend/src/hooks/api/auditLogs/types.tsx | 6 ++ 9 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars diff --git a/backend/src/ee/services/audit-log/audit-log-types.ts b/backend/src/ee/services/audit-log/audit-log-types.ts index 91464bc0b..a31200a1b 100644 --- a/backend/src/ee/services/audit-log/audit-log-types.ts +++ b/backend/src/ee/services/audit-log/audit-log-types.ts @@ -234,6 +234,7 @@ export enum EventType { GET_PROJECT_KMS_BACKUP = "get-project-kms-backup", LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup", ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project", + ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso", CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template", UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template", DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template", @@ -1907,6 +1908,11 @@ interface OrgAdminAccessProjectEvent { }; // no metadata yet } +interface OrgAdminBypassSSOEvent { + type: EventType.ORG_ADMIN_BYPASS_SSO; + metadata: Record; // no metadata yet +} + interface CreateCertificateTemplateEstConfig { type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG; metadata: { @@ -2656,6 +2662,7 @@ export type Event = | GetProjectKmsBackupEvent | LoadProjectKmsBackupEvent | OrgAdminAccessProjectEvent + | OrgAdminBypassSSOEvent | CreateCertificateTemplate | UpdateCertificateTemplate | GetCertificateTemplate diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index 3f4af174b..f6d0d0410 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -25,11 +25,11 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ customRateLimits: false, customAlerts: false, secretAccessInsights: false, - auditLogs: false, - auditLogsRetentionDays: 0, + auditLogs: true, + auditLogsRetentionDays: 3, auditLogStreams: false, auditLogStreamLimit: 3, - samlSSO: false, + samlSSO: true, hsm: false, oidcSSO: false, scim: false, diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index c9f2811b5..3b23c7303 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -596,7 +596,14 @@ export const registerRoutes = async ( kmsService }); - const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService, orgDAL, totpService }); + const loginService = authLoginServiceFactory({ + userDAL, + smtpService, + tokenService, + orgDAL, + totpService, + auditLogService + }); const passwordService = authPaswordServiceFactory({ tokenService, smtpService, diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index 0e0f999dd..6af512773 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -3,6 +3,8 @@ import jwt from "jsonwebtoken"; import { Knex } from "knex"; import { OrgMembershipRole, TUsers, UserDeviceSchema } from "@app/db/schemas"; +import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service"; +import { EventType } from "@app/ee/services/audit-log/audit-log-types"; import { isAuthMethodSaml } from "@app/ee/services/permission/permission-fns"; import { getConfig } from "@app/lib/config/env"; import { request } from "@app/lib/config/request"; @@ -11,6 +13,7 @@ import { infisicalSymmetricEncypt } from "@app/lib/crypto/encryption"; import { getUserPrivateKey } from "@app/lib/crypto/srp"; import { BadRequestError, DatabaseError, ForbiddenRequestError, UnauthorizedError } from "@app/lib/errors"; import { logger } from "@app/lib/logger"; +import { getUserAgentType } from "@app/server/plugins/audit-log"; import { getServerCfg } from "@app/services/super-admin/super-admin-service"; import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service"; @@ -28,7 +31,14 @@ import { TOauthTokenExchangeDTO, TVerifyMfaTokenDTO } from "./auth-login-type"; -import { AuthMethod, AuthModeJwtTokenPayload, AuthModeMfaJwtTokenPayload, AuthTokenType, MfaMethod } from "./auth-type"; +import { + ActorType, + AuthMethod, + AuthModeJwtTokenPayload, + AuthModeMfaJwtTokenPayload, + AuthTokenType, + MfaMethod +} from "./auth-type"; type TAuthLoginServiceFactoryDep = { userDAL: TUserDALFactory; @@ -36,6 +46,7 @@ type TAuthLoginServiceFactoryDep = { tokenService: TAuthTokenServiceFactory; smtpService: TSmtpService; totpService: Pick; + auditLogService: Pick; }; export type TAuthLoginFactory = ReturnType; @@ -44,7 +55,8 @@ export const authLoginServiceFactory = ({ tokenService, smtpService, orgDAL, - totpService + totpService, + auditLogService }: TAuthLoginServiceFactoryDep) => { /* * Private @@ -412,6 +424,51 @@ export const authLoginServiceFactory = ({ mfaMethod: decodedToken.mfaMethod }); + // In the event of this being a break-glass request (non-saml / non-oidc, when either is enforced) + if ( + selectedOrg.authEnforced && + selectedOrg.bypassOrgAuthEnabled && + !isAuthMethodSaml(decodedToken.authMethod) && + decodedToken.authMethod !== AuthMethod.OIDC + ) { + await auditLogService.createAuditLog({ + orgId: organizationId, + ipAddress, + userAgent, + userAgentType: getUserAgentType(userAgent), + actor: { + type: ActorType.USER, + metadata: { + email: user.email, + userId: user.id, + username: user.username + } + }, + event: { + type: EventType.ORG_ADMIN_BYPASS_SSO, + metadata: {} + } + }); + + // Notify all admins via email + const orgAdmins = await orgDAL.findOrgMembersByRole(organizationId, OrgMembershipRole.Admin); + const adminEmails = orgAdmins.map((admin) => admin.user?.email).filter(Boolean) as string[]; + + if (adminEmails.length > 0) { + await smtpService.sendMail({ + recipients: adminEmails, + subjectLine: "Security Alert: Admin SSO Bypass", + substitutions: { + email: user.email, + timestamp: new Date().toISOString(), + ip: ipAddress, + userAgent + }, + template: SmtpTemplates.OrgAdminBreakglassAccess + }); + } + } + return { ...tokens, isMfaEnabled: false diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index 02bf58321..8aedddbdd 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -2,6 +2,7 @@ import { Knex } from "knex"; import { TDbClient } from "@app/db"; import { + OrgMembershipRole, TableName, TOrganizations, TOrganizationsInsert, @@ -251,6 +252,43 @@ export const orgDALFactory = (db: TDbClient) => { } }; + const findOrgMembersByRole = async (orgId: string, role: OrgMembershipRole, tx?: Knex) => { + try { + const conn = tx || db; + const members = await conn(TableName.OrgMembership) + .where(`${TableName.OrgMembership}.orgId`, orgId) + .where(`${TableName.OrgMembership}.role`, role) + .join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`) + .leftJoin( + TableName.UserEncryptionKey, + `${TableName.UserEncryptionKey}.userId`, + `${TableName.Users}.id` + ) + .select( + conn.ref("id").withSchema(TableName.OrgMembership), + conn.ref("inviteEmail").withSchema(TableName.OrgMembership), + conn.ref("orgId").withSchema(TableName.OrgMembership), + conn.ref("role").withSchema(TableName.OrgMembership), + conn.ref("roleId").withSchema(TableName.OrgMembership), + conn.ref("status").withSchema(TableName.OrgMembership), + conn.ref("username").withSchema(TableName.Users), + conn.ref("email").withSchema(TableName.Users), + conn.ref("firstName").withSchema(TableName.Users), + conn.ref("lastName").withSchema(TableName.Users), + conn.ref("id").withSchema(TableName.Users).as("userId"), + conn.ref("publicKey").withSchema(TableName.UserEncryptionKey) + ) + .where({ isGhost: false }); + + return members.map(({ username, email, firstName, lastName, userId, publicKey, ...data }) => ({ + ...data, + user: { username, email, firstName, lastName, id: userId, publicKey } + })); + } catch (error) { + throw new DatabaseError({ error, name: "Find org members by role" }); + } + }; + const findOrgGhostUser = async (orgId: string) => { try { const member = await db @@ -472,6 +510,7 @@ export const orgDALFactory = (db: TDbClient) => { findAllOrgsByUserId, ghostUserExists, findOrgMembersByUsername, + findOrgMembersByRole, findOrgGhostUser, create, updateById, diff --git a/backend/src/services/smtp/smtp-service.ts b/backend/src/services/smtp/smtp-service.ts index 25f5f3949..0e028968d 100644 --- a/backend/src/services/smtp/smtp-service.ts +++ b/backend/src/services/smtp/smtp-service.ts @@ -44,6 +44,7 @@ export enum SmtpTemplates { SecretRotationFailed = "secretRotationFailed.handlebars", ProjectAccessRequest = "projectAccess.handlebars", OrgAdminProjectDirectAccess = "orgAdminProjectGrantAccess.handlebars", + OrgAdminBreakglassAccess = "OrgAdminBreakglassAccess.handlebars", ServiceTokenExpired = "serviceTokenExpired.handlebars" } diff --git a/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars b/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars new file mode 100644 index 000000000..c15eb6896 --- /dev/null +++ b/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars @@ -0,0 +1,20 @@ + + + + + + Organization admin has bypassed SSO + + + +

Infisical

+

The organization admin {{email}} has just bypassed enforced SSO login.

+

Timestamp: {{timestamp}}

+

IP address: {{ip}}

+

User agent: {{userAgent}}

+

If you'd like to disable Admin SSO Bypass, please visit Organization Settings > Security.

+ + {{emailFooter}} + + + diff --git a/frontend/src/hooks/api/auditLogs/enums.tsx b/frontend/src/hooks/api/auditLogs/enums.tsx index 15adb0272..d465fb820 100644 --- a/frontend/src/hooks/api/auditLogs/enums.tsx +++ b/frontend/src/hooks/api/auditLogs/enums.tsx @@ -90,6 +90,7 @@ export enum EventType { ADD_PKI_COLLECTION_ITEM = "add-pki-collection-item", DELETE_PKI_COLLECTION_ITEM = "delete-pki-collection-item", ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project", + ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso", CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template", UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template", DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template", diff --git a/frontend/src/hooks/api/auditLogs/types.tsx b/frontend/src/hooks/api/auditLogs/types.tsx index a18974f2e..2524f84f4 100644 --- a/frontend/src/hooks/api/auditLogs/types.tsx +++ b/frontend/src/hooks/api/auditLogs/types.tsx @@ -718,6 +718,11 @@ interface OrgAdminAccessProjectEvent { }; // no metadata yet } +interface OrgAdminBypassSSOEvent { + type: EventType.ORG_ADMIN_BYPASS_SSO; + metadata: Record; // no metadata yet +} + interface CreateCertificateTemplate { type: EventType.CREATE_CERTIFICATE_TEMPLATE; metadata: { @@ -885,6 +890,7 @@ export type Event = | AddPkiCollectionItem | DeletePkiCollectionItem | OrgAdminAccessProjectEvent + | OrgAdminBypassSSOEvent | CreateCertificateTemplate | UpdateCertificateTemplate | GetCertificateTemplate From a838f84601d51fc4d3ad63b0fa8d3f0d9b6a90b6 Mon Sep 17 00:00:00 2001 From: x Date: Tue, 22 Apr 2025 14:58:17 -0400 Subject: [PATCH 2/5] Revert license overwrites, fix type errors, add error handling to email function --- .../src/ee/services/license/license-fns.ts | 6 ++-- .../src/services/auth/auth-login-service.ts | 28 +++++++++++-------- .../identity-aws-auth-service.ts | 13 ++++----- backend/src/services/smtp/smtp-service.ts | 2 +- .../src/hooks/api/auditLogs/constants.tsx | 1 + 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/backend/src/ee/services/license/license-fns.ts b/backend/src/ee/services/license/license-fns.ts index f6d0d0410..3f4af174b 100644 --- a/backend/src/ee/services/license/license-fns.ts +++ b/backend/src/ee/services/license/license-fns.ts @@ -25,11 +25,11 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({ customRateLimits: false, customAlerts: false, secretAccessInsights: false, - auditLogs: true, - auditLogsRetentionDays: 3, + auditLogs: false, + auditLogsRetentionDays: 0, auditLogStreams: false, auditLogStreamLimit: 3, - samlSSO: true, + samlSSO: false, hsm: false, oidcSSO: false, scim: false, diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index 6af512773..e0d964017 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -454,18 +454,22 @@ export const authLoginServiceFactory = ({ const orgAdmins = await orgDAL.findOrgMembersByRole(organizationId, OrgMembershipRole.Admin); const adminEmails = orgAdmins.map((admin) => admin.user?.email).filter(Boolean) as string[]; - if (adminEmails.length > 0) { - await smtpService.sendMail({ - recipients: adminEmails, - subjectLine: "Security Alert: Admin SSO Bypass", - substitutions: { - email: user.email, - timestamp: new Date().toISOString(), - ip: ipAddress, - userAgent - }, - template: SmtpTemplates.OrgAdminBreakglassAccess - }); + try { + if (adminEmails.length > 0) { + await smtpService.sendMail({ + recipients: adminEmails, + subjectLine: "Security Alert: Admin SSO Bypass", + substitutions: { + email: user.email, + timestamp: new Date().toISOString(), + ip: ipAddress, + userAgent + }, + template: SmtpTemplates.OrgAdminBreakglassAccess + }); + } + } catch (error) { + logger.error(error, `Failed to send SSO bypass notification emails for user ${user.email}`); } } diff --git a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts index 0849a7523..fe7b24783 100644 --- a/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts +++ b/backend/src/services/identity-aws-auth/identity-aws-auth-service.ts @@ -68,18 +68,15 @@ const awsRegionFromHeader = (authorizationHeader: string): string | null => { return null; }; - - -function isValidAwsRegion(region: (string | null)): boolean { - const validRegionPattern = new RE2('^[a-z0-9-]+$'); - if (typeof region !== 'string' || region.length === 0 || region.length > 20) { +function isValidAwsRegion(region: string | null): boolean { + const validRegionPattern = new RE2("^[a-z0-9-]+$"); + if (typeof region !== "string" || region.length === 0 || region.length > 20) { return false; } - + return validRegionPattern.test(region); } - export const identityAwsAuthServiceFactory = ({ identityAccessTokenDAL, identityAwsAuthDAL, @@ -100,7 +97,7 @@ export const identityAwsAuthServiceFactory = ({ const region = headers.Authorization ? awsRegionFromHeader(headers.Authorization) : null; if (!isValidAwsRegion(region)) { - throw new BadRequestError({message: "Invalid AWS region"}); + throw new BadRequestError({ message: "Invalid AWS region" }); } const url = region ? `https://sts.${region}.amazonaws.com` : identityAwsAuth.stsEndpoint; diff --git a/backend/src/services/smtp/smtp-service.ts b/backend/src/services/smtp/smtp-service.ts index 0e028968d..550e1bb07 100644 --- a/backend/src/services/smtp/smtp-service.ts +++ b/backend/src/services/smtp/smtp-service.ts @@ -44,7 +44,7 @@ export enum SmtpTemplates { SecretRotationFailed = "secretRotationFailed.handlebars", ProjectAccessRequest = "projectAccess.handlebars", OrgAdminProjectDirectAccess = "orgAdminProjectGrantAccess.handlebars", - OrgAdminBreakglassAccess = "OrgAdminBreakglassAccess.handlebars", + OrgAdminBreakglassAccess = "orgAdminBreakglassAccess.handlebars", ServiceTokenExpired = "serviceTokenExpired.handlebars" } diff --git a/frontend/src/hooks/api/auditLogs/constants.tsx b/frontend/src/hooks/api/auditLogs/constants.tsx index 159e840ec..229f822da 100644 --- a/frontend/src/hooks/api/auditLogs/constants.tsx +++ b/frontend/src/hooks/api/auditLogs/constants.tsx @@ -84,6 +84,7 @@ export const eventToNameMap: { [K in EventType]: string } = { [EventType.ADD_PKI_COLLECTION_ITEM]: "Add PKI collection item", [EventType.DELETE_PKI_COLLECTION_ITEM]: "Delete PKI collection item", [EventType.ORG_ADMIN_ACCESS_PROJECT]: "Org admin accessed project", + [EventType.ORG_ADMIN_BYPASS_SSO]: "Org admin bypassed SSO enforcement", [EventType.CREATE_CERTIFICATE_TEMPLATE]: "Create certificate template", [EventType.UPDATE_CERTIFICATE_TEMPLATE]: "Update certificate template", [EventType.DELETE_CERTIFICATE_TEMPLATE]: "Delete certificate template", From 8bd21ffa63e2871d32cc60e1d3f5f2c7aa7febad Mon Sep 17 00:00:00 2001 From: x Date: Wed, 23 Apr 2025 19:46:25 -0400 Subject: [PATCH 3/5] Attached settings URL to email, actor no longer a recipient, removed error handling for email send, used read replica node for findOrgMembersByRole --- .../src/services/auth/auth-login-service.ts | 35 +++++++++---------- backend/src/services/org/org-dal.ts | 2 +- .../orgAdminBreakglassAccess.handlebars | 4 +-- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index e0d964017..03281baca 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -450,26 +450,25 @@ export const authLoginServiceFactory = ({ } }); - // Notify all admins via email + // Notify all admins via email (besides the actor) const orgAdmins = await orgDAL.findOrgMembersByRole(organizationId, OrgMembershipRole.Admin); - const adminEmails = orgAdmins.map((admin) => admin.user?.email).filter(Boolean) as string[]; + const adminEmails = orgAdmins + .filter((admin) => admin.user.id !== user.id) + .map((admin) => admin.user.email) + .filter(Boolean) as string[]; - try { - if (adminEmails.length > 0) { - await smtpService.sendMail({ - recipients: adminEmails, - subjectLine: "Security Alert: Admin SSO Bypass", - substitutions: { - email: user.email, - timestamp: new Date().toISOString(), - ip: ipAddress, - userAgent - }, - template: SmtpTemplates.OrgAdminBreakglassAccess - }); - } - } catch (error) { - logger.error(error, `Failed to send SSO bypass notification emails for user ${user.email}`); + if (adminEmails.length > 0) { + await smtpService.sendMail({ + recipients: adminEmails, + subjectLine: "Security Alert: Admin SSO Bypass", + substitutions: { + email: user.email, + timestamp: new Date().toISOString(), + ip: ipAddress, + userAgent + }, + template: SmtpTemplates.OrgAdminBreakglassAccess + }); } } diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index 8aedddbdd..3f4215a6b 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -254,7 +254,7 @@ export const orgDALFactory = (db: TDbClient) => { const findOrgMembersByRole = async (orgId: string, role: OrgMembershipRole, tx?: Knex) => { try { - const conn = tx || db; + const conn = tx || db.replicaNode(); const members = await conn(TableName.OrgMembership) .where(`${TableName.OrgMembership}.orgId`, orgId) .where(`${TableName.OrgMembership}.role`, role) diff --git a/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars b/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars index c15eb6896..0ad3bf2b5 100644 --- a/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars +++ b/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars @@ -8,11 +8,11 @@

Infisical

-

The organization admin {{email}} has just bypassed enforced SSO login.

+

The organization admin {{email}} has bypassed enforced SSO login.

Timestamp: {{timestamp}}

IP address: {{ip}}

User agent: {{userAgent}}

-

If you'd like to disable Admin SSO Bypass, please visit Organization Settings > Security.

+

If you'd like to disable Admin SSO Bypass, please visit Organization Settings > Security.

{{emailFooter}} From d019011822e25a30c37621c18629ebc9af50be8e Mon Sep 17 00:00:00 2001 From: x Date: Wed, 23 Apr 2025 19:53:14 -0400 Subject: [PATCH 4/5] Made findOrgMembersByUsername use replicaNode to stay consistent --- backend/src/services/org/org-dal.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/services/org/org-dal.ts b/backend/src/services/org/org-dal.ts index 3f4215a6b..54b0e1b0f 100644 --- a/backend/src/services/org/org-dal.ts +++ b/backend/src/services/org/org-dal.ts @@ -217,9 +217,8 @@ export const orgDALFactory = (db: TDbClient) => { const findOrgMembersByUsername = async (orgId: string, usernames: string[], tx?: Knex) => { try { - const conn = tx || db; + const conn = tx || db.replicaNode(); const members = await conn(TableName.OrgMembership) - // .replicaNode()(TableName.OrgMembership) .where(`${TableName.OrgMembership}.orgId`, orgId) .join(TableName.Users, `${TableName.OrgMembership}.userId`, `${TableName.Users}.id`) .leftJoin( From e25c1199bc673f82b247cd307bcdae91bfc4d27c Mon Sep 17 00:00:00 2001 From: x Date: Thu, 24 Apr 2025 10:24:42 -0400 Subject: [PATCH 5/5] Made email URL use SITE_URL --- backend/src/services/auth/auth-login-service.ts | 4 +++- .../smtp/templates/orgAdminBreakglassAccess.handlebars | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/src/services/auth/auth-login-service.ts b/backend/src/services/auth/auth-login-service.ts index 03281baca..e576d6768 100644 --- a/backend/src/services/auth/auth-login-service.ts +++ b/backend/src/services/auth/auth-login-service.ts @@ -39,6 +39,7 @@ import { AuthTokenType, MfaMethod } from "./auth-type"; +import { removeTrailingSlash } from "@app/lib/fn"; type TAuthLoginServiceFactoryDep = { userDAL: TUserDALFactory; @@ -465,7 +466,8 @@ export const authLoginServiceFactory = ({ email: user.email, timestamp: new Date().toISOString(), ip: ipAddress, - userAgent + userAgent, + siteUrl: removeTrailingSlash(cfg.SITE_URL || "https://app.infisical.com") }, template: SmtpTemplates.OrgAdminBreakglassAccess }); diff --git a/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars b/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars index 0ad3bf2b5..cc97ff201 100644 --- a/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars +++ b/backend/src/services/smtp/templates/orgAdminBreakglassAccess.handlebars @@ -12,7 +12,7 @@

Timestamp: {{timestamp}}

IP address: {{ip}}

User agent: {{userAgent}}

-

If you'd like to disable Admin SSO Bypass, please visit Organization Settings > Security.

+

If you'd like to disable Admin SSO Bypass, please visit Organization Settings > Security.

{{emailFooter}}