mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
chore(core): guard idp-initiated sso console and api (#6690)
* chore(core): guard idp-initiated sso management api to cloud only guard idp-initiated sso management api to cloud only * fix(test): enable routes for integration tests enable routes for integration tests * feat(core, console): apply idp-initiated sso quota guard apply idp-initiate sso quota guard
This commit is contained in:
parent
c7f326edce
commit
14e65924f2
12 changed files with 287 additions and 268 deletions
|
@ -52,7 +52,7 @@
|
|||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@logto/cloud": "0.2.5-1661979",
|
||||
"@logto/cloud": "0.2.5-5e334eb",
|
||||
"@silverhand/eslint-config": "6.0.1",
|
||||
"@silverhand/ts-config": "6.0.0",
|
||||
"@types/node": "^20.11.20",
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"devDependencies": {
|
||||
"@fontsource/roboto-mono": "^5.0.0",
|
||||
"@jest/types": "^29.5.0",
|
||||
"@logto/cloud": "0.2.5-6654b82",
|
||||
"@logto/cloud": "0.2.5-5e334eb",
|
||||
"@logto/connector-kit": "workspace:^4.0.0",
|
||||
"@logto/core-kit": "workspace:^2.5.0",
|
||||
"@logto/elements": "workspace:^0.0.1",
|
||||
|
|
|
@ -28,6 +28,7 @@ export const skuQuotaItemPhrasesMap: Record<
|
|||
customJwtEnabled: 'custom_jwt_enabled.name',
|
||||
subjectTokenEnabled: 'impersonation_enabled.name',
|
||||
bringYourUiEnabled: 'bring_your_ui_enabled.name',
|
||||
idpInitiatedSsoEnabled: 'idp_initiated_sso_enabled.name',
|
||||
};
|
||||
|
||||
export const skuQuotaItemUnlimitedPhrasesMap: Record<
|
||||
|
@ -55,6 +56,7 @@ export const skuQuotaItemUnlimitedPhrasesMap: Record<
|
|||
customJwtEnabled: 'custom_jwt_enabled.unlimited',
|
||||
subjectTokenEnabled: 'impersonation_enabled.unlimited',
|
||||
bringYourUiEnabled: 'bring_your_ui_enabled.unlimited',
|
||||
idpInitiatedSsoEnabled: 'idp_initiated_sso_enabled.unlimited',
|
||||
};
|
||||
|
||||
export const skuQuotaItemLimitedPhrasesMap: Record<
|
||||
|
@ -82,6 +84,7 @@ export const skuQuotaItemLimitedPhrasesMap: Record<
|
|||
customJwtEnabled: 'custom_jwt_enabled.limited',
|
||||
subjectTokenEnabled: 'impersonation_enabled.limited',
|
||||
bringYourUiEnabled: 'bring_your_ui_enabled.limited',
|
||||
idpInitiatedSsoEnabled: 'idp_initiated_sso_enabled.limited',
|
||||
};
|
||||
|
||||
export const skuQuotaItemNotEligiblePhrasesMap: Record<
|
||||
|
@ -109,5 +112,6 @@ export const skuQuotaItemNotEligiblePhrasesMap: Record<
|
|||
customJwtEnabled: 'custom_jwt_enabled.not_eligible',
|
||||
subjectTokenEnabled: 'impersonation_enabled.not_eligible',
|
||||
bringYourUiEnabled: 'bring_your_ui_enabled.not_eligible',
|
||||
idpInitiatedSsoEnabled: 'idp_initiated_sso_enabled.not_eligible',
|
||||
};
|
||||
/* === for new pricing model === */
|
||||
|
|
|
@ -58,6 +58,8 @@ export const defaultLogtoSku: LogtoSkuResponse = {
|
|||
updatedAt: new Date(),
|
||||
type: LogtoSkuType.Basic,
|
||||
unitPrice: 0,
|
||||
productId: null,
|
||||
defaultPriceId: null,
|
||||
quota: {
|
||||
// A soft limit for abuse monitoring
|
||||
mauLimit: 100,
|
||||
|
@ -80,6 +82,7 @@ export const defaultLogtoSku: LogtoSkuResponse = {
|
|||
customJwtEnabled: true,
|
||||
subjectTokenEnabled: true,
|
||||
bringYourUiEnabled: true,
|
||||
idpInitiatedSsoEnabled: false,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -105,6 +108,7 @@ export const defaultSubscriptionQuota: NewSubscriptionQuota = {
|
|||
customJwtEnabled: false,
|
||||
subjectTokenEnabled: false,
|
||||
bringYourUiEnabled: false,
|
||||
idpInitiatedSsoEnabled: false,
|
||||
};
|
||||
|
||||
export const defaultSubscriptionUsage: NewSubscriptionCountBasedUsage = {
|
||||
|
@ -125,6 +129,7 @@ export const defaultSubscriptionUsage: NewSubscriptionCountBasedUsage = {
|
|||
customJwtEnabled: false,
|
||||
subjectTokenEnabled: false,
|
||||
bringYourUiEnabled: false,
|
||||
idpInitiatedSsoEnabled: false,
|
||||
};
|
||||
|
||||
const getAdminTenantEndpoint = () => {
|
||||
|
|
|
@ -67,12 +67,11 @@ function EnterpriseSsoDetails() {
|
|||
|
||||
const isDarkModeEnabled = signInExperience?.color.isDarkModeEnabled ?? false;
|
||||
|
||||
const isIdpInitiatedAuthEnabled = useMemo(
|
||||
const isIdpInitiatedAuthConfigEnabled = useMemo(
|
||||
() =>
|
||||
isCloud &&
|
||||
ssoConnector?.providerType === SsoProviderType.SAML &&
|
||||
// TODO: @simeng: Replace this with new IdP-initiated auth quota guard
|
||||
Boolean(currentSubscriptionQuota.enterpriseSsoLimit),
|
||||
currentSubscriptionQuota.idpInitiatedSsoEnabled,
|
||||
[ssoConnector, currentSubscriptionQuota]
|
||||
);
|
||||
|
||||
|
@ -153,7 +152,7 @@ function EnterpriseSsoDetails() {
|
|||
>
|
||||
<DynamicT forKey="enterprise_sso_details.tab_experience" />
|
||||
</TabNavItem>
|
||||
{isIdpInitiatedAuthEnabled && (
|
||||
{isIdpInitiatedAuthConfigEnabled && (
|
||||
<TabNavItem
|
||||
href={getSsoConnectorDetailsPathname(
|
||||
ssoConnectorId,
|
||||
|
@ -183,7 +182,7 @@ function EnterpriseSsoDetails() {
|
|||
}}
|
||||
/>
|
||||
)}
|
||||
{isIdpInitiatedAuthEnabled && tab === EnterpriseSsoDetailsTabs.IdpInitiatedAuth && (
|
||||
{isIdpInitiatedAuthConfigEnabled && tab === EnterpriseSsoDetailsTabs.IdpInitiatedAuth && (
|
||||
<IdpInitiatedAuth ssoConnector={ssoConnector} />
|
||||
)}
|
||||
<ConfirmModal
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@logto/cloud": "0.2.5-1661979",
|
||||
"@logto/cloud": "0.2.5-5e334eb",
|
||||
"@silverhand/eslint-config": "6.0.1",
|
||||
"@silverhand/ts-config": "6.0.0",
|
||||
"@types/adm-zip": "^0.5.5",
|
||||
|
|
|
@ -205,8 +205,7 @@ export default function authnRoutes<T extends AnonymousRouter>(
|
|||
// All the rest of the request body will be validated and parsed by the connector.
|
||||
const { RelayState: jti } = body;
|
||||
|
||||
// IdP initiated SSO will not have the jti in the RelayState.
|
||||
// Trigger the IdP initiated SSO flow if enabled for the current connector.
|
||||
// IdP initiated SSO does not provide the RelayState, we need to check if the IdP initiated SSO flow is enabled.
|
||||
if (!jti && EnvSet.values.isDevFeaturesEnabled) {
|
||||
const idpInitiatedAuthConfig =
|
||||
await queries.ssoConnectors.getIdpInitiatedAuthConfigByConnectorId(connectorId);
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"tags": [
|
||||
{
|
||||
"name": "Dev feature"
|
||||
},
|
||||
{
|
||||
"name": "Cloud only"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
|
|
|
@ -10,6 +10,7 @@ import koaGuard from '#src/middleware/koa-guard.js';
|
|||
import { ssoConnectorFactories } from '#src/sso/index.js';
|
||||
import { tableToPathname } from '#src/utils/SchemaRouter.js';
|
||||
|
||||
import { koaQuotaGuard } from '../../middleware/koa-quota-guard.js';
|
||||
import assertThat from '../../utils/assert-that.js';
|
||||
import { type ManagementApiRouter, type RouterInitArgs } from '../types.js';
|
||||
|
||||
|
@ -24,6 +25,7 @@ export default function ssoConnectorIdpInitiatedAuthConfigRoutes<T extends Manag
|
|||
queries,
|
||||
libraries: {
|
||||
ssoConnectors: { getSsoConnectorById, createSsoConnectorIdpInitiatedAuthConfig },
|
||||
quota,
|
||||
},
|
||||
},
|
||||
] = args;
|
||||
|
@ -32,6 +34,7 @@ export default function ssoConnectorIdpInitiatedAuthConfigRoutes<T extends Manag
|
|||
|
||||
router.put(
|
||||
pathPrefix,
|
||||
koaQuotaGuard({ key: 'idpInitiatedSsoEnabled', quota }),
|
||||
koaGuard({
|
||||
body: ssoConnectorIdpInitiatedAuthConfigCreateGuard,
|
||||
params: z.object({ id: z.string().min(1) }),
|
||||
|
|
|
@ -303,7 +303,10 @@ export default function singleSignOnConnectorsRoutes<T extends ManagementApiRout
|
|||
}
|
||||
);
|
||||
|
||||
if (EnvSet.values.isDevFeaturesEnabled) {
|
||||
if (
|
||||
EnvSet.values.isDevFeaturesEnabled &&
|
||||
(EnvSet.values.isCloud || EnvSet.values.isIntegrationTest)
|
||||
) {
|
||||
ssoConnectorIdpInitiatedAuthConfigRoutes(...args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,6 +171,12 @@ const quota_item = {
|
|||
unlimited: 'Bring your UI',
|
||||
not_eligible: 'Remove your custom UI assets',
|
||||
},
|
||||
idp_initiated_sso_enabled: {
|
||||
name: 'IDP-initiated SSO',
|
||||
limited: 'IDP-initiated SSO',
|
||||
unlimited: 'IDP-initiated SSO',
|
||||
not_eligible: 'IDP-initiated SSO not allowed',
|
||||
},
|
||||
};
|
||||
|
||||
export default Object.freeze(quota_item);
|
||||
|
|
511
pnpm-lock.yaml
511
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue