Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f256c25
chore(deps): bump react-virtuoso from 4.18.5 to 4.18.7
dependabot[bot] May 28, 2026
8316c60
chore(deps): bump @react-pdf/renderer from 4.3.2 to 4.5.1
dependabot[bot] May 28, 2026
4919288
chore(deps): bump axios from 1.15.0 to 1.16.1
dependabot[bot] May 28, 2026
c04cd7c
chore(deps): bump @tiptap/extension-heading from 3.20.5 to 3.22.3
dependabot[bot] May 28, 2026
0995677
chore(deps): bump react-hook-form from 7.72.0 to 7.76.1
dependabot[bot] May 28, 2026
580b66f
repair and fix failed SSO app creations and password addition failures
Zacgoose Jun 8, 2026
1ea0324
fix: ensure search happens when data is done loading
kris6673 Jun 8, 2026
0de0910
Merge pull request #6132 from kris6673/tables-search
KelvinTegelaar Jun 8, 2026
cfbf350
Removed dublicate appliesToTest key
JNRavnIT Jun 9, 2026
8cfb8ca
Merge pull request #6138 from JNRavnIT/patch-1
KelvinTegelaar Jun 9, 2026
7ea75e7
Merge pull request #6072 from KelvinTegelaar/dependabot/npm_and_yarn/…
KelvinTegelaar Jun 9, 2026
f1475e8
Merge pull request #6073 from KelvinTegelaar/dependabot/npm_and_yarn/…
KelvinTegelaar Jun 9, 2026
87d543d
Merge pull request #6075 from KelvinTegelaar/dependabot/npm_and_yarn/…
KelvinTegelaar Jun 9, 2026
e53ab04
Merge pull request #6074 from KelvinTegelaar/dependabot/npm_and_yarn/…
KelvinTegelaar Jun 9, 2026
91bb02b
Merge pull request #6071 from KelvinTegelaar/dependabot/npm_and_yarn/…
KelvinTegelaar Jun 9, 2026
ae695a9
Update CippAddEditUser.jsx
Zacgoose Jun 9, 2026
0e10e08
Update index.js
Zacgoose Jun 9, 2026
6a2e7b3
chore: bump version to 10.5.1
JohnDuprey Jun 9, 2026
f4448a5
Merge pull request #6140 from KelvinTegelaar/dev
JohnDuprey Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cipp",
"version": "10.5.0",
"version": "10.5.1",
"author": "CIPP Contributors",
"homepage": "https://cipp.app/",
"bugs": {
Expand Down Expand Up @@ -39,22 +39,22 @@
"@musement/iso-duration": "^1.0.0",
"@nivo/core": "^0.99.0",
"@nivo/sankey": "^0.99.0",
"@react-pdf/renderer": "^4.3.2",
"@react-pdf/renderer": "^4.5.1",
"@reduxjs/toolkit": "^2.11.2",
"@tanstack/query-sync-storage-persister": "^5.90.25",
"@tanstack/react-query": "^5.100.10",
"@tanstack/react-query-devtools": "^5.96.2",
"@tanstack/react-query-persist-client": "^5.96.2",
"@tanstack/react-table": "^8.19.2",
"@tiptap/core": "^3.22.3",
"@tiptap/extension-heading": "^3.4.1",
"@tiptap/extension-heading": "^3.22.3",
"@tiptap/extension-table": "^3.20.5",
"@tiptap/pm": "^3.22.3",
"@tiptap/react": "^3.20.5",
"@tiptap/starter-kit": "^3.20.5",
"@vvo/tzdb": "^6.198.0",
"apexcharts": "5.10.4",
"axios": "1.15.0",
"axios": "1.16.1",
"date-fns": "4.1.0",
"diff": "^8.0.3",
"dompurify": "^3.4.3",
Expand Down Expand Up @@ -84,7 +84,7 @@
"react-dom": "19.2.6",
"react-dropzone": "15.0.0",
"react-error-boundary": "^6.1.1",
"react-hook-form": "^7.72.0",
"react-hook-form": "^7.76.1",
"react-hot-toast": "2.6.0",
"react-html-parser": "^2.0.2",
"react-leaflet": "5.0.0",
Expand All @@ -96,7 +96,7 @@
"react-redux": "9.2.0",
"react-syntax-highlighter": "^16.1.0",
"react-time-ago": "^7.3.3",
"react-virtuoso": "^4.18.5",
"react-virtuoso": "^4.18.7",
"recharts": "^3.8.1",
"redux": "5.0.1",
"redux-persist": "^6.0.0",
Expand Down
2 changes: 1 addition & 1 deletion public/version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "10.5.0"
"version": "10.5.1"
}
4 changes: 3 additions & 1 deletion src/components/CippComponents/ForcedSsoMigrationDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ export const ForcedSsoMigrationDialog = () => {
'SSO migration failed. Please try again.'}
</Alert>
<Typography variant="body2" color="text.secondary">
If this error persists, contact your CIPP administrator.
The app registration may have been created already — clicking <strong>Try Again</strong>{' '}
will pick up where it left off rather than starting over. If the error persists,
contact your CIPP administrator.
</Typography>
</>
) : null}
Expand Down
17 changes: 16 additions & 1 deletion src/components/CippComponents/SsoMigrationDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ export const SsoMigrationDialog = ({ meData }) => {

const result = ssoSetup.data?.data?.Results ?? ssoSetup.data?.Results
const isSuccess = result?.severity === 'success'
const isError = ssoSetup.isError || result?.severity === 'failed'
const isPartial = result?.severity === 'warning' && result?.canRepair
const isError = ssoSetup.isError || result?.severity === 'failed' || (result?.severity === 'warning' && !result?.canRepair)

return (
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
Expand Down Expand Up @@ -109,6 +110,20 @@ export const SsoMigrationDialog = ({ meData }) => {
<Alert severity="success" sx={{ mb: 1 }}>
{result.message}
</Alert>
) : isPartial ? (
<Alert severity="warning" sx={{ mb: 1 }}>
<Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
App created — secret creation failed
</Typography>
<Typography variant="body2" sx={{ mb: 1 }}>
The CIPP-SSO app registration ({result.appId}) was created successfully, but the
client secret could not be generated. The app ID is saved.
</Typography>
<Typography variant="body2">
Open <strong>Advanced &rarr; Super Admin &rarr; SSO</strong> and click{' '}
<strong>Repair</strong> to finish setup.
</Typography>
</Alert>
) : isError ? (
<Alert severity="error" sx={{ mb: 1 }}>
{result?.message || ssoSetup.error?.message || 'SSO setup failed. It will be retried automatically.'}
Expand Down
2 changes: 1 addition & 1 deletion src/components/CippFormPages/CippAddEditUser.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ const CippAddEditUser = (props) => {
label: group.displayName,
value: group.id,
addedFields: {
groupType: group.calculatedGroupType || group.groupType,
groupType: group.groupType,
},
})) || []
}
Expand Down
153 changes: 124 additions & 29 deletions src/components/CippSettings/CippSSOSettings.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useEffect, useState } from "react";
import { useEffect } from "react";
import {
Alert,
Button,
CardActions,
CardContent,
CardHeader,
Chip,
Divider,
Skeleton,
Expand All @@ -20,16 +19,16 @@ import { CippApiResults } from "../CippComponents/CippApiResults";

const statusLabels = {
none: { label: "Not Configured", color: "default" },
app_created: { label: "App Created", color: "info" },
appid_stored: { label: "App ID Stored", color: "info" },
app_created: { label: "App Created — Secret Pending", color: "warning" },
appid_stored: { label: "App ID Stored — Secret Pending", color: "warning" },
secrets_stored: { label: "Secrets Stored", color: "success" },
complete: { label: "Complete", color: "success" },
error: { label: "Error", color: "error" },
};

export const CippSSOSettings = () => {
const [showCreate, setShowCreate] = useState(false);
const repairableStatuses = new Set(["error", "app_created", "appid_stored"]);

export const CippSSOSettings = () => {
const formControl = useForm({
mode: "onChange",
defaultValues: { multiTenant: false },
Expand All @@ -49,32 +48,82 @@ export const CippSSOSettings = () => {
if (ssoStatus.isSuccess && ssoStatus.data?.Results) {
const data = ssoStatus.data.Results;
formControl.reset({ multiTenant: data.multiTenant ?? false });
setShowCreate(!data.configured);
}
}, [ssoStatus.isSuccess, ssoStatus.data]);

const handleUpdate = () => {
const data = ssoStatus.data?.Results;
const statusKey = data?.status ?? "none";
const statusInfo = statusLabels[statusKey] ?? statusLabels.none;
const hasAppId = Boolean(data?.appId);
// Server-provided canRepair is authoritative when present; fall back to local heuristic.
const canRepair =
data?.canRepair ??
(hasAppId && repairableStatuses.has(statusKey));
const isProvisioned =
statusKey === "complete" || (statusKey === "secrets_stored" && hasAppId);
// Show "Create SSO App" whenever there isn't a working app AND there's nothing to repair —
// covers fresh installs AND legacy broken installs where the AppId was never persisted
// (the original "Failed to create client secret after 5 attempts" bug).
const showCreate = !isProvisioned && !canRepair;
const isOrphanedError = statusKey === "error" && !hasAppId;

const handleCreate = () => {
ssoAction.mutate({
url: "/api/ExecSSOSetup",
data: {
Action: "Create",
multiTenant: formControl.getValues("multiTenant"),
},
});
};

const handleRepair = () => {
ssoAction.mutate({
url: "/api/ExecSSOSetup",
data: { Action: "Repair" },
});
};

const handleRecreate = () => {
if (
!window.confirm(
"Updating SSO settings will restart the CIPP instance. Changes may take up to 60 seconds to reflect. Do you want to continue?"
"Recreate will clear the current SSO record and provision a brand new CIPP-SSO app. The previous app registration will be left in your Entra tenant (you can delete it manually). Continue?"
)
) {
return;
}
ssoAction.mutate({
url: "/api/ExecSSOSetup",
data: {
Action: "Update",
multiTenant: formControl.getValues("multiTenant"),
// Clear first, then create. ApiPostCall chains via the success refetch — call sequentially.
ssoAction.mutate(
{
url: "/api/ExecSSOSetup",
data: { Action: "Recreate" },
},
});
{
onSuccess: () => {
ssoAction.mutate({
url: "/api/ExecSSOSetup",
data: {
Action: "Create",
multiTenant: formControl.getValues("multiTenant"),
},
});
},
}
);
};

const handleCreate = () => {
const handleUpdate = () => {
if (
!window.confirm(
"Updating SSO settings will restart the CIPP instance. Changes may take up to 60 seconds to reflect. Do you want to continue?"
)
) {
return;
}
ssoAction.mutate({
url: "/api/ExecSSOSetup",
data: {
Action: "Create",
Action: "Update",
multiTenant: formControl.getValues("multiTenant"),
},
});
Expand All @@ -87,9 +136,6 @@ export const CippSSOSettings = () => {
});
};

const data = ssoStatus.data?.Results;
const statusInfo = statusLabels[data?.status] ?? statusLabels.none;

return (
<CippButtonCard title="SSO App Registration" isFetching={ssoStatus.isFetching}>
<CardContent>
Expand Down Expand Up @@ -141,13 +187,38 @@ export const CippSSOSettings = () => {
)}

{data?.lastError && (
<>
<Grid size={{ xs: 12 }}>
<Alert severity="error" sx={{ mt: 1 }}>
{data.lastError}
</Alert>
</Grid>
</>
<Grid size={{ xs: 12 }}>
<Alert
severity={canRepair ? "warning" : "error"}
sx={{ mt: 1 }}
>
<Typography variant="body2" sx={{ fontWeight: 600, mb: 0.5 }}>
{canRepair
? "Setup did not finish"
: isOrphanedError
? "Previous setup failed"
: "Error"}
</Typography>
<Typography variant="body2">{data.lastError}</Typography>
{canRepair && (
<Typography variant="caption" sx={{ display: "block", mt: 1 }}>
The app registration ({data.appId}) was created successfully but the
client secret could not be generated. Click <strong>Repair</strong> to
retry the secret on the existing app, or <strong>Recreate</strong> to
start over with a fresh app registration.
</Typography>
)}
{isOrphanedError && (
<Typography variant="caption" sx={{ display: "block", mt: 1 }}>
A previous attempt to set up SSO did not save an App ID, so there's
nothing to repair. An orphaned <strong>CIPP-SSO</strong> app
registration may exist in your Entra tenant — you can delete it
manually. Click <strong>Create SSO App</strong> to provision a fresh
app registration.
</Typography>
)}
</Alert>
</Grid>
)}
</Grid>

Expand All @@ -158,6 +229,7 @@ export const CippSSOSettings = () => {
name="multiTenant"
label="Multi-tenant mode (allow users from multiple Entra ID tenants)"
formControl={formControl}
disabled={!isProvisioned && !showCreate}
/>

<CippApiResults apiObject={ssoAction} />
Expand All @@ -167,15 +239,38 @@ export const CippSSOSettings = () => {
{!ssoStatus.isLoading && (
<CardActions sx={{ justifyContent: "flex-end", px: 2, pb: 2 }}>
<Stack direction="row" spacing={1}>
{showCreate ? (
{showCreate && (
<Button
variant="contained"
onClick={handleCreate}
disabled={ssoAction.isPending}
>
Create SSO App
</Button>
) : (
)}

{canRepair && (
<>
<Button
variant="outlined"
color="warning"
onClick={handleRecreate}
disabled={ssoAction.isPending}
>
Recreate
</Button>
<Button
variant="contained"
color="warning"
onClick={handleRepair}
disabled={ssoAction.isPending}
>
Repair
</Button>
</>
)}

{isProvisioned && (
<>
<Button
variant="outlined"
Expand Down
9 changes: 7 additions & 2 deletions src/components/CippTable/CippDataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -600,8 +600,13 @@ export const CippDataTable = (props) => {
[simple, hasActions, hasOffCanvas, hasOnChange, maxHeightOffset, settings?.tablePageSize?.value]
)

// Include updateTrigger in data memo to force re-render when license backfill completes
const memoizedData = useMemo(() => usedData, [usedData, updateTrigger])
// Include updateTrigger in data memo to force re-render when license backfill completes.
// Also refresh data identity when derived columns change so TanStack re-runs filtering
// for searches entered before columns are available.
const memoizedData = useMemo(
() => (Array.isArray(usedData) ? usedData.slice() : usedData),
[usedData, updateTrigger, usedColumns]
)

// Sanitize columnVisibility to remove any undefined/invalid keys before passing to MRT
const sanitizedColumnVisibility = useMemo(() => {
Expand Down
5 changes: 2 additions & 3 deletions src/data/standards.json
Original file line number Diff line number Diff line change
Expand Up @@ -1791,7 +1791,7 @@
"name": "standards.AppManagementPolicy",
"cat": "Entra (AAD) Standards",
"tag": ["CIS M365 7.0.0 (5.1.5.3)", "CIS M365 7.0.0 (5.1.5.4)", "CIS M365 7.0.0 (5.1.5.5)", "CIS M365 7.0.0 (5.1.5.6)"],
"appliesToTest": ["CIS_5_1_5_3", "CIS_5_1_5_4", "CIS_5_1_5_5", "CIS_5_1_5_6"],
"appliesToTest": ["CIS_5_1_5_3", "CIS_5_1_5_4", "CIS_5_1_5_5", "CIS_5_1_5_6", "ZTNA21773", "ZTNA21896", "ZTNA21992"],
"helpText": "Configures the default app management policy to control application and service principal credential restrictions such as password and key credential lifetimes.",
"docsDescription": "Configures the default app management policy to control application and service principal credential restrictions. This includes password addition restrictions, custom password addition, symmetric key addition, and credential lifetime limits for both applications and service principals.",
"executiveText": "Enforces credential restrictions on application registrations and service principals to limit how secrets and certificates are created and how long they remain valid. This reduces the risk of long-lived or unmanaged credentials being used to access your tenant.",
Expand Down Expand Up @@ -1838,8 +1838,7 @@
"impactColour": "warning",
"addedDate": "2026-03-13",
"powershellEquivalent": "Graph API",
"recommendedBy": [],
"appliesToTest": ["ZTNA21773", "ZTNA21896", "ZTNA21992"]
"recommendedBy": []
},
{
"name": "standards.OutBoundSpamAlert",
Expand Down
2 changes: 1 addition & 1 deletion src/pages/teams-share/sharepoint/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const Page = () => {
const reportDB = useCippReportDB({
apiUrl: '/api/ListSites?type=SharePointSiteUsage',
queryKey: 'ListSites-SharePointSiteUsage',
cacheName: 'Sites',
cacheName: 'SharePointSiteUsage',
syncTitle: 'Sync SharePoint Sites Report',
syncData: { Types: 'SharePointSiteUsage' },
allowToggle: true,
Expand Down
Loading