diff --git a/backend/src/db/migrations/20251127192155_adds-scope-org-id-to-identity-access-tokens.ts b/backend/src/db/migrations/20251127192155_adds-scope-org-id-to-identity-access-tokens.ts deleted file mode 100644 index dd7f0c3a0..000000000 --- a/backend/src/db/migrations/20251127192155_adds-scope-org-id-to-identity-access-tokens.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Knex } from "knex"; - -import { TableName } from "../schemas"; - -export async function up(knex: Knex): Promise { - const hasScopeOrgIdColumn = await knex.schema.hasColumn(TableName.IdentityAccessToken, "scopeOrgId"); - if (!hasScopeOrgIdColumn) { - await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => { - t.uuid("scopeOrgId"); - t.foreign("scopeOrgId").references("id").inTable(TableName.Organization).onDelete("CASCADE"); - }); - } -} - -export async function down(knex: Knex): Promise { - const hasScopeOrgIdColumn = await knex.schema.hasColumn(TableName.IdentityAccessToken, "scopeOrgId"); - if (hasScopeOrgIdColumn) { - await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => { - t.dropColumn("scopeOrgId"); - }); - } -} diff --git a/backend/src/db/migrations/20251127192155_adds-sub-organization-id-to-identity-access-tokens.ts b/backend/src/db/migrations/20251127192155_adds-sub-organization-id-to-identity-access-tokens.ts new file mode 100644 index 000000000..31de94dd3 --- /dev/null +++ b/backend/src/db/migrations/20251127192155_adds-sub-organization-id-to-identity-access-tokens.ts @@ -0,0 +1,22 @@ +import { Knex } from "knex"; + +import { TableName } from "../schemas"; + +export async function up(knex: Knex): Promise { + const hasSubOrganizationIdColumn = await knex.schema.hasColumn(TableName.IdentityAccessToken, "subOrganizationId"); + if (!hasSubOrganizationIdColumn) { + await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => { + t.uuid("subOrganizationId").nullable(); + t.foreign("subOrganizationId").references("id").inTable(TableName.Organization).onDelete("CASCADE"); + }); + } +} + +export async function down(knex: Knex): Promise { + const hasSubOrganizationIdColumn = await knex.schema.hasColumn(TableName.IdentityAccessToken, "subOrganizationId"); + if (hasSubOrganizationIdColumn) { + await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => { + t.dropColumn("subOrganizationId"); + }); + } +} diff --git a/backend/src/db/schemas/identity-access-tokens.ts b/backend/src/db/schemas/identity-access-tokens.ts index dfa962439..fcda42d4b 100644 --- a/backend/src/db/schemas/identity-access-tokens.ts +++ b/backend/src/db/schemas/identity-access-tokens.ts @@ -23,7 +23,7 @@ export const IdentityAccessTokensSchema = z.object({ name: z.string().nullable().optional(), authMethod: z.string(), accessTokenPeriod: z.coerce.number().default(0), - scopeOrgId: z.string().uuid().nullable().optional() + subOrganizationId: z.string().uuid().nullable().optional() }); export type TIdentityAccessTokens = z.infer; diff --git a/backend/src/services/identity-access-token/identity-access-token-dal.ts b/backend/src/services/identity-access-token/identity-access-token-dal.ts index 7c98ac9f9..c6ae78fe1 100644 --- a/backend/src/services/identity-access-token/identity-access-token-dal.ts +++ b/backend/src/services/identity-access-token/identity-access-token-dal.ts @@ -19,7 +19,7 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => { .join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityAccessToken}.identityId`) .select(selectAllTableCols(TableName.IdentityAccessToken)) .select(db.ref("orgId").withSchema(TableName.Identity).as("identityOrgId")) - .select(db.ref("scopeOrgId").withSchema(TableName.IdentityAccessToken).as("scopeOrgId")) + .select(db.ref("subOrganizationId").withSchema(TableName.IdentityAccessToken).as("subOrganizationId")) .first(); return doc; diff --git a/backend/src/services/identity-access-token/identity-access-token-service.ts b/backend/src/services/identity-access-token/identity-access-token-service.ts index ab4d7ef5d..4aaff748c 100644 --- a/backend/src/services/identity-access-token/identity-access-token-service.ts +++ b/backend/src/services/identity-access-token/identity-access-token-service.ts @@ -206,7 +206,7 @@ export const identityAccessTokenServiceFactory = ({ }); } - const scopeOrgId = identityAccessToken.scopeOrgId || identityAccessToken.identityOrgId; + const scopeOrgId = identityAccessToken.subOrganizationId || identityAccessToken.identityOrgId; const identityOrgDetails = await orgDAL.findOne({ id: scopeOrgId }); diff --git a/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts b/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts index 4790067ff..c74326548 100644 --- a/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts +++ b/backend/src/services/identity-alicloud-auth/identity-alicloud-auth-service.ts @@ -80,26 +80,23 @@ export const identityAliCloudAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -157,7 +154,7 @@ export const identityAliCloudAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityAliCloudAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.ALICLOUD_AUTH, - scopeOrgId + subOrganizationId }, tx ); 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 a06ec4838..fb95b95cf 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 @@ -118,27 +118,23 @@ export const identityAwsAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const isSubOrg = Boolean(org.rootOrgId); + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; - - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -240,7 +236,7 @@ export const identityAwsAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityAwsAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.AWS_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts index 92ad82fd7..0157cc281 100644 --- a/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts +++ b/backend/src/services/identity-azure-auth/identity-azure-auth-service.ts @@ -74,28 +74,23 @@ export const identityAzureAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const isSubOrg = Boolean(org.rootOrgId); - - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; - - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -153,7 +148,7 @@ export const identityAzureAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityAzureAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.AZURE_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts index 797103de1..b7db92c3a 100644 --- a/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts +++ b/backend/src/services/identity-gcp-auth/identity-gcp-auth-service.ts @@ -72,26 +72,23 @@ export const identityGcpAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -192,7 +189,7 @@ export const identityGcpAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityGcpAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.GCP_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts b/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts index c6b309c5c..3ac0dddaa 100644 --- a/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts +++ b/backend/src/services/identity-jwt-auth/identity-jwt-auth-service.ts @@ -86,26 +86,23 @@ export const identityJwtAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -271,7 +268,7 @@ export const identityJwtAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityJwtAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.JWT_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts index 1f4ec1e11..237687982 100644 --- a/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts +++ b/backend/src/services/identity-kubernetes-auth/identity-kubernetes-auth-service.ts @@ -198,26 +198,23 @@ export const identityKubernetesAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -512,7 +509,7 @@ export const identityKubernetesAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityKubernetesAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.KUBERNETES_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts b/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts index f84f95839..1b82837b7 100644 --- a/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts +++ b/backend/src/services/identity-ldap-auth/identity-ldap-auth-service.ts @@ -167,30 +167,28 @@ export const identityLdapAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } } + const plan = await licenseService.getPlan(identity.orgId); if (!plan.ldap) { throw new BadRequestError({ @@ -229,7 +227,7 @@ export const identityLdapAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityLdapAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.LDAP_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts b/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts index 3daa9c754..e17aa6ce6 100644 --- a/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts +++ b/backend/src/services/identity-oci-auth/identity-oci-auth-service.ts @@ -76,30 +76,28 @@ export const identityOciAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } } + try { // Validate OCI host format. Ensures that the host is in "identity..oraclecloud.com" format. if (!headers.host || !new RE2("^identity\\.([a-z]{2}-[a-z]+-[1-9])\\.oraclecloud\\.com$").test(headers.host)) { @@ -162,7 +160,7 @@ export const identityOciAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityOciAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.OCI_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts index d47bca36d..06b385523 100644 --- a/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts +++ b/backend/src/services/identity-oidc-auth/identity-oidc-auth-service.ts @@ -87,30 +87,28 @@ export const identityOidcAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } } + try { const { decryptor } = await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.Organization, @@ -339,7 +337,7 @@ export const identityOidcAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityOidcAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.OIDC_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts b/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts index 88d40fd8e..38b2bee73 100644 --- a/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts +++ b/backend/src/services/identity-tls-cert-auth/identity-tls-cert-auth-service.ts @@ -85,26 +85,23 @@ export const identityTlsCertAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -186,7 +183,7 @@ export const identityTlsCertAuthServiceFactory = ({ accessTokenNumUses: 0, accessTokenNumUsesLimit: identityTlsCertAuth.accessTokenNumUsesLimit, authMethod: IdentityAuthMethod.TLS_CERT_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-token-auth/identity-token-auth-service.ts b/backend/src/services/identity-token-auth/identity-token-auth-service.ts index ff7dd9dfb..f36e8df5c 100644 --- a/backend/src/services/identity-token-auth/identity-token-auth-service.ts +++ b/backend/src/services/identity-token-auth/identity-token-auth-service.ts @@ -505,26 +505,23 @@ export const identityTokenAuthServiceFactory = ({ if (!identity) throw new UnauthorizedError({ message: "Identity not found" }); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || org.id : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -557,7 +554,7 @@ export const identityTokenAuthServiceFactory = ({ accessTokenNumUsesLimit: identityTokenAuth.accessTokenNumUsesLimit, name, authMethod: IdentityAuthMethod.TOKEN_AUTH, - scopeOrgId + subOrganizationId }, tx ); diff --git a/backend/src/services/identity-ua/identity-ua-service.ts b/backend/src/services/identity-ua/identity-ua-service.ts index 4ff1f6203..74d5c7d0f 100644 --- a/backend/src/services/identity-ua/identity-ua-service.ts +++ b/backend/src/services/identity-ua/identity-ua-service.ts @@ -91,26 +91,23 @@ export const identityUaServiceFactory = ({ const identity = await identityDAL.findById(identityUa.identityId); const org = await orgDAL.findById(identity.orgId); - const isSubOrg = Boolean(org.rootOrgId); + const isSubOrgIdentity = Boolean(org.rootOrgId); - const rootOrgId = isSubOrg ? org.rootOrgId || "" : org.id; + // If the identity is a sub-org identity, then the scope is always the org.id, and if it's a root org identity, then we need to resolve the scope if a subOrganizationName is specified + let subOrganizationId = isSubOrgIdentity ? org.id : null; - // Resolve sub-organization if specified - let scopeOrgId = rootOrgId; if (subOrganizationName) { - const subOrg = await orgDAL.findOne({ slug: subOrganizationName }); + if (!isSubOrgIdentity) { + const subOrg = await orgDAL.findOne({ rootOrgId: org.id, slug: subOrganizationName }); - if (subOrg) { - if (subOrg.rootOrgId === rootOrgId) { - // Verify identity has membership in the sub-organization + if (subOrg) { const subOrgMembership = await membershipIdentityDAL.findOne({ scope: AccessScope.Organization, actorIdentityId: identity.id, scopeOrgId: subOrg.id }); - if (subOrgMembership) { - scopeOrgId = subOrg.id; + subOrganizationId = subOrg.id; } } } @@ -284,7 +281,7 @@ export const identityUaServiceFactory = ({ accessTokenNumUsesLimit: identityUa.accessTokenNumUsesLimit, accessTokenPeriod: identityUa.accessTokenPeriod, authMethod: IdentityAuthMethod.UNIVERSAL_AUTH, - scopeOrgId, + subOrganizationId, ...accessTokenTTLParams }, tx