Skip to content

feat(okta): add complete Okta identity management integration#3685

Merged
waleedlatif1 merged 7 commits intostagingfrom
waleedlatif1/add-okta-integration
Mar 19, 2026
Merged

feat(okta): add complete Okta identity management integration#3685
waleedlatif1 merged 7 commits intostagingfrom
waleedlatif1/add-okta-integration

Conversation

@waleedlatif1
Copy link
Collaborator

@waleedlatif1 waleedlatif1 commented Mar 19, 2026

Summary

  • Add 18 Okta Management API tools: user lifecycle (list, get, create, update, activate, deactivate, suspend, unsuspend, reset password, delete) and group management (list, get, create, update, delete, add/remove members, list members)
  • Add Okta block with conditional UI fields, operation dropdown, and proper param mapping
  • Add Okta icon, registry entries (tools + block), and generated docs
  • All endpoints validated against official Okta Developer API documentation via Context7

Test plan

  • Verify Okta block appears in the toolbar and all 18 operations are selectable
  • Verify conditional fields show/hide correctly per operation
  • Test List Users with search and filter params against a real Okta org
  • Test user lifecycle operations (create → activate → suspend → unsuspend → deactivate → delete)
  • Test group CRUD and membership operations
  • Verify error handling for invalid API tokens and missing required fields

@vercel
Copy link

vercel bot commented Mar 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 19, 2026 10:53pm

Request Review

@cursor
Copy link

cursor bot commented Mar 19, 2026

PR Summary

Medium Risk
Introduces new Okta identity-management tooling (user lifecycle + group membership) that makes authenticated calls to a security-sensitive system; mistakes could impact account access or allow unsafe outbound requests (partly mitigated by Okta domain validation).

Overview
Adds an Okta integration end-to-end: 18 new Okta Management API tools (users, groups, membership, lifecycle actions), a new OktaBlock with conditional fields and param mapping, and registration in the block/tool registries.

Updates docs and UI metadata: generates new okta.mdx/workday.mdx, adds OktaIcon and WorkdayIcon and wires them into icon mappings and meta.json, and expands the Ashby docs + landing-page metadata (new operations + updated output field names).

Extends landing-page integrations.json/icon mapping to include new integrations for okta and workday, and also adds box and docusign entries (metadata/icon wiring only in this PR).

Written by Cursor Bugbot for commit c613e78. Configure here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 19, 2026

Greptile Summary

This PR adds a complete Okta identity management integration with 18 tools covering full user lifecycle (list, get, create, update, activate, deactivate, suspend, unsuspend, reset password, delete) and group management (list, get, create, update, delete, add/remove members, list members). It also ships the corresponding block, icon, registry entries, and docs. Additionally, the PR includes landing-page/doc stubs for Workday, Box, and DocuSign (without block implementations) and expands the Ashby docs.

  • The previously-reported issues (SSRF via unvalidated domain, unguarded response.json() before ok check, inconsistent sendEmail handling) have all been addressed: validateOktaDomain() enforces an allowlist regex, all 9 affected tools now check response.ok first with try/catch on the error body, and deactivate_user/delete_user use the explicit === true pattern.
  • Limit default mismatch: list_groups.ts documents "default: 10000" and list_group_members.ts documents "default: 1000", but neither enforces those defaults in the URL construction — Okta's own page default (200) applies when no limit param is passed. list_users.ts is correct because its documented default (200) coincidentally matches Okta's default.
  • okta_update_user sends { profile: {} } to Okta when no profile fields are provided, resulting in a valid but no-op network request.
  • Workday, Box, and DocuSign entries are added to the integrations landing page and docs without corresponding block/tool implementations in this PR — these appear to be pre-announcement stubs.

Confidence Score: 4/5

  • Safe to merge with minor fixes; the security issues from earlier rounds are resolved and the new issues are documentation/behavioral mismatches, not correctness bugs.
  • The integration is well-structured and the critical security fixes (SSRF, JSON parse, sendEmail consistency) from previous review rounds are properly applied. The remaining issues are the limit-default mismatch (which causes unexpected truncation for large Okta orgs) and an empty-profile no-op edge case. Neither is a data-integrity or security risk, but the limit mismatch could confuse users of large orgs.
  • apps/sim/tools/okta/list_groups.ts and apps/sim/tools/okta/list_group_members.ts need their documented defaults either enforced in code or corrected to reflect Okta's actual per-page default.

Important Files Changed

Filename Overview
apps/sim/tools/okta/types.ts Defines all Okta types, interfaces, and the SSRF-protective validateOktaDomain() with a well-scoped regex allowing only known Okta domain suffixes. Clean and comprehensive.
apps/sim/tools/okta/list_groups.ts Implements group listing with search/filter support. Issue: documented default limit of 10000 is not enforced in code — when no limit is provided, Okta's own per-page default (200) applies instead.
apps/sim/tools/okta/list_group_members.ts Implements group member listing. Same default-limit discrepancy as list_groups.ts: documents "default: 1000" but omits the limit param from requests when not provided, leaving Okta to apply its own default of 200.
apps/sim/tools/okta/list_users.ts Implements user listing with search/filter/limit support. Response handling and domain validation are correct; documented default of 200 matches Okta's own default, so no discrepancy here.
apps/sim/tools/okta/update_user.ts Implements partial user profile update via POST. Correctly only sends changed fields. Minor: no guard against empty-profile submissions (sends { profile: {} } which is a valid but no-op request).
apps/sim/tools/okta/create_user.ts Correctly builds user creation request with profile and optional credential fields. Password visibility is user-only. Domain is validated. Response transformation is solid.
apps/sim/blocks/blocks/okta.ts Well-structured block definition with all 18 operations, proper conditional UI field visibility, and correct mapping of UI-specific field names (groupName→name, groupDescription→description) to tool param names.
apps/sim/tools/okta/activate_user.ts Correctly handles the Okta activation endpoint. Empty response body (when sendEmail=true) is handled with try/catch. activationUrl/activationToken are parsed defensively.
apps/sim/tools/okta/deactivate_user.ts Uses explicit sendEmail boolean pattern (sendEmail === true) as required by previous review fix. Domain validation applied. Clean and correct.
apps/sim/tools/registry.ts All 18 Okta tools correctly registered in alphabetical position.
apps/sim/app/(landing)/integrations/data/integrations.json Okta entry correctly added with 18 operations listed. Also adds Workday, Box, and DocuSign landing-page entries without corresponding block/tool implementations in this PR — these appear to be pre-announcement stubs.

Sequence Diagram

sequenceDiagram
    participant User as User / LLM
    participant Block as Okta Block<br/>(okta.ts)
    participant Registry as Tool Registry
    participant Tool as Okta Tool<br/>(e.g. list_users.ts)
    participant Validator as validateOktaDomain()
    participant OktaAPI as Okta API<br/>(your-org.okta.com)

    User->>Block: Select operation + enter apiKey, domain, params
    Block->>Registry: config.tool(params) → tool id
    Block->>Registry: config.params(params) → mapped params
    Registry->>Tool: execute(params)
    Tool->>Validator: validateOktaDomain(params.domain)
    alt Domain fails regex
        Validator-->>Tool: throw Error("Invalid Okta domain")
        Tool-->>User: Error: invalid domain
    else Domain is valid
        Validator-->>Tool: sanitized domain string
        Tool->>OktaAPI: SSWS ${apiKey} authenticated request
        alt HTTP error (4xx/5xx)
            OktaAPI-->>Tool: error response
            Tool->>Tool: try response.json() for OktaApiError
            Tool-->>User: throw Error(errorSummary)
        else HTTP 200 / 204
            OktaAPI-->>Tool: JSON or empty body
            Tool->>Tool: transform response → typed output
            Tool-->>User: success: true + output fields
        end
    end
Loading

Last reviewed commit: "fix(okta): prevent s..."

Add 18 Okta Management API tools covering user lifecycle (list, get,
create, update, activate, deactivate, suspend, unsuspend, reset password,
delete) and group management (list, get, create, update, delete, add/remove
members, list members). Includes block with conditional UI, icon, registry
entries, and generated docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1 waleedlatif1 force-pushed the waleedlatif1/add-okta-integration branch from 3323d5f to 3704fca Compare March 19, 2026 21:47
@waleedlatif1 waleedlatif1 changed the base branch from main to staging March 19, 2026 21:47
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…, consistent sendEmail

- Add validateOktaDomain() to prevent SSRF via user-supplied domain param
- Fix 9 tools to check response.ok before calling response.json()
- Make sendEmail query param explicit in deactivate_user and delete_user

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Switch subBlocks default to OFF (false), which was being forwarded to
tools and overriding their default-true behavior for sendEmail and
activate params. Now only forward these when explicitly toggled ON.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

Block now forwards sendEmail/activate values as-is (including false).
Tools use ?? operator so: explicit true/false from switches are respected,
undefined (programmatic calls) still defaults to true.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

- update_group: always include description in PUT body (defaults to '')
  since PUT replaces the full profile object
- update_user: use !== undefined checks so empty strings can clear fields
  via Okta's POST partial update
- block: allow empty strings through passthrough loop and use !== undefined
  for groupDescription mapping

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Domain validation missing whitespace trimming causes confusing errors
    • Added .trim() to validateOktaDomain function to remove leading and trailing whitespace before domain validation.

Create PR

Or push these changes by commenting:

@cursor push 1b4322d39b
Preview (1b4322d39b)
diff --git a/apps/sim/tools/okta/types.ts b/apps/sim/tools/okta/types.ts
--- a/apps/sim/tools/okta/types.ts
+++ b/apps/sim/tools/okta/types.ts
@@ -8,7 +8,7 @@
  * Ensures the domain matches a known Okta domain suffix.
  */
 export function validateOktaDomain(rawDomain: string): string {
-  const domain = rawDomain.replace(/^https?:\/\//, '').replace(/\/$/, '')
+  const domain = rawDomain.trim().replace(/^https?:\/\//, '').replace(/\/$/, '')
   if (!OKTA_DOMAIN_PATTERN.test(domain)) {
     throw new Error(
       `Invalid Okta domain: "${domain}". Must be a valid Okta domain (e.g., dev-123456.okta.com)`

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

- Moved validateOktaDomain from tools/okta/types.ts to
  lib/core/security/input-validation.ts alongside other validation utils
- Added .trim() to handle copy-paste whitespace in domain input
- Updated all 18 tool files to import from the new location

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1 waleedlatif1 merged commit 6326353 into staging Mar 19, 2026
11 checks passed
@waleedlatif1 waleedlatif1 deleted the waleedlatif1/add-okta-integration branch March 19, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant