# Okta Cis To Descope

> >

- **Type:** Skill
- **Install:** `agentstack add skill-descope-skills-okta-cis-to-descope`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [descope](https://agentstack.voostack.com/s/descope)
- **Installs:** 0
- **Category:** [Security](https://agentstack.voostack.com/c/security)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [descope](https://github.com/descope)
- **Source:** https://github.com/descope/skills/tree/main/skills/okta-cis-to-descope

## Install

```sh
agentstack add skill-descope-skills-okta-cis-to-descope
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Okta CIS → Descope Migration Skill

This skill guides self-service migrations from Okta Customer Identity Service (CIS) to Descope.
It runs in three parts:

1. **MCP Check** — confirm whether the Descope Docs MCP is available and suggest installing it if not
2. **Migration Plan** — gather context via triage questions, analyze the codebase's auth touchpoints, and produce a human-readable `MIGRATION-PLAN.md` for the user to review
3. **Execution** — if the user confirms they want to proceed, execute the plan

Do not collapse these parts or skip ahead. The plan must be reviewed before code changes begin.

**Primary references** (all in this skill's directory):
- `references/implementation-nuances.md` — verified migration patterns for each JS/TS framework, Okta CIS feature-to-Descope mappings, and known gotchas
- `references/flows-and-widgets.md` — Descope terminology/lingo (Okta→Descope), Flow structure and templates, Widgets, SSO Setup Suite, Console-vs-code decision guide
- `references/backend-sdks.md` — Python and Java backend migration patterns (Flask, FastAPI, Django, Spring Boot, management SDK, M2M)

---

## Guiding Principles

**Console-first.** Before recommending SDK code for any user-facing auth feature, check whether the Console, a Flow, or a Widget covers the use case. Okta CIS is a low-code platform — users configure auth logic through the Okta Sign-In Widget, the visual policy builder (OIE), email customization, and the admin console. Descope has direct equivalents for all of these: Flows replace the visual policy builder, the Descope Flow component replaces the Sign-In Widget, Messaging Templates replace email customization, and Widgets replace custom management UIs. Engineers integrate once (SDK setup + session validation). All subsequent auth evolution — new methods, MFA changes, UI updates, branding — should happen in the Console without code deployments. See `references/flows-and-widgets.md` → Console vs. Code.

**Ask, don't assume.** At any design decision point — especially Inbound Apps vs. Federated Apps (the core Okta strategy fork), Flow vs. custom code, Widget vs. custom page, MFA inline vs. separate enrollment — use `AskUserQuestion` rather than proceeding with an assumption. The cost of a wrong assumption compounds across 20+ files. Always confirm whether the backend validates `scp` claims before recommending the Inbound Apps path.

**MCP over memory.** When the Docs MCP is available (confirmed in Part 1), use `ask-question-about-descope` to verify every SDK method name, option shape, and return type before writing it. Do not fall back to "verify the exact method name in the SDK type declarations" as a hedge — just verify it directly.

---

## Part 1: MCP Check (BLOCKING)

Before doing anything else, check whether the Descope Docs MCP is available by calling
`search-descope-docs` with a simple query (e.g., "session validation").

**If the tool is available:** proceed to Part 2 immediately.

**If the tool is not available**, show this message and use `AskUserQuestion` to ask whether
they want to install it first:

> **Descope Docs MCP is not installed.**
>
> This skill uses the Descope Docs MCP to look up current API signatures, SDK methods, and
> feature availability during migration. Without it, guidance is based on static training data,
> which may be stale and can produce SDK calls that don't exist.
>
> You can install it in a few minutes at **https://docs-mcp.descope.com/** (server URL:
> `https://docs-mcp.descope.com/mcp`). It significantly improves the accuracy of the
> migration output — especially for SDK lookups and flow-specific configuration.
>
> **Would you like to install the MCP before we continue, or proceed without it?**

- If they choose to install: pause and wait. Once they confirm it's installed, re-check by calling `search-descope-docs` again before proceeding.
- If they choose to proceed without it: continue, but flag any SDK-specific answers as "based on last known documentation — verify against the current SDK."

Do not proceed to Part 2 until this step is resolved.

---

## Part 2: Migration Plan

Part 2 has two sub-steps:

1. **Triage** — ask the questions needed to understand scope
2. **Codebase Analysis + Plan File** — scan the project, produce `MIGRATION-PLAN.md`, and pause for review

### Step 0: Triage (BLOCKING — requires `AskUserQuestion`)

**Use the `AskUserQuestion` tool to gather the information below. Do not infer answers
from memory, prior conversations, or assumptions — even if you think you know.**
The migration path differs significantly based on these answers.

Do not proceed to Step 0.5 until the user has answered.

**Decision 0 — Login mode (resolve this before anything else):**

Ask this as the first `AskUserQuestion`:

> "Is the app using Okta's **hosted/redirect login** — for example, `loginWithRedirect`, `@okta/oidc-middleware`, or users being sent to an Okta-hosted login page to authenticate? Or does it use an **embedded login UI** — the Okta Sign-In Widget embedded in the page, or a custom auth form built with `okta-auth-js` in non-redirect mode?"

Decision tree:
```
Login mode?
├── REDIRECT (hosted Okta page, loginWithRedirect, oidc-middleware, passport-openidconnect)
│     → Default to OIDC path: update OIDC client config to point at Descope endpoints
│       Set up Federated App or Inbound App in Console (Decision 1 determines which)
│       No new login page, no new SDK required — redirect/callback plumbing stays intact
│
└── EMBEDDED (Okta Sign-In Widget in-page, custom okta-auth-js non-redirect flow)
      → Default to embedded Descope Flow component path
        Replace widget/form with 
        Still determine Federated vs. Inbound App via Decision 1
```

Do not proceed until this is resolved — it determines the entire migration approach.

---

**Decision 1 — Inbound Apps vs. Federated Apps:**

Ask as the second `AskUserQuestion` (applies to both login modes — it determines which type of app to configure in the Console):

> "Does the backend validate OAuth scopes from the Okta access token? (i.e., is there backend code that reads `token.scp`, `claims["scp"]`, or similar to make authorization decisions?)"

Decision tree:
```
Does any backend service validate token scopes (scp claim)?
├── YES  → Inbound Apps path
│          (Descope enforces scopes; custom claims go in JWT Template on the Inbound App)
├── NO   → Federated Apps + OIDC layer
│          (Okta used for identity only; often just update JWKS URL + Issuer, no scope changes)
└── UNSURE → Ask them to grep: token.scp  claims["scp"]  req.auth.scp
             Then re-ask.
```

Do not proceed until this is resolved.

---

**Remaining triage — first `AskUserQuestion` call (up to 3 questions):**

1. **Backend language / framework** — Present the most likely options based on cues in the conversation (Node.js/Express, Next.js, Angular, React SPA, Go, Python, Java). The user can always pick "Other."
2. **Migration goal** — Full cut-over, incremental/phased migration, or just evaluating.
3. **Existing user base** — Are they migrating an app with active users in Okta, or starting fresh? This determines whether user migration planning is needed.

**Second `AskUserQuestion` call — Okta CIS feature usage (use `multiSelect: true`):**

Which Okta CIS features are in use? Present these options:
- Okta Sign-In Widget (`@okta/okta-signin-widget` — embedded login UI component)
- Sign-On Policies (per-app auth rule chains / visual policy builder)
- Authenticator Enrollment Policies (MFA factor requirements)
- Authorization Servers / APIs (custom OAuth audiences and scopes)
- Identity Providers (external SAML/OIDC SSO per customer org)
- Authenticators (WebAuthn/Passkeys, TOTP, Okta Verify, SMS, etc.)
- Log Streams (Splunk Cloud, Amazon EventBridge)
- Service Apps / API Services (M2M / client credentials)
- Token Inline Hooks (custom logic during auth)
- Groups (used for RBAC/access control)

The user can add others via "Other." Follow up on anything selected — e.g., if Authorization
Servers is selected, ask about custom claims using Okta Expression Language. If Authenticators
is selected, ask which specific types.

After both calls, summarize findings and flag high-complexity items (Token Inline Hooks with
external dependencies, complex Sign-On Policy rule chains, custom Expression Language claims)
before proceeding to Step 0.5.

---

### Step 0.5: Engineer Review Checkpoint (BLOCKING — requires `AskUserQuestion`)

These questions surface blockers the framework doesn't expose. Ask even the ones you think
you know. Use `AskUserQuestion` before proceeding to codebase analysis.

Batch into calls of up to 4 questions. Skip questions that are clearly inapplicable given
Step 0 answers (e.g., skip user migration planning if they said they're starting fresh).

**Strategy confirmation**
- Does the backend validate `scp` claims from the Okta access token? (If yes → Inbound Apps. If unsure, show them what to grep for: `token.scp`, `claims["scp"]`, `req.auth.scp`.) — skip if already resolved in Decision 1
- For redirect-mode apps: is the migration goal to keep the redirect flow (OIDC endpoint swap only) or eventually move to the embedded Descope Flow component? (The OIDC path is a valid permanent solution — not just a stepping stone.)
- Are Sign-On Policies per-app, global, or both? (Determines scope of Flow migration.)
- Is scope validation in application code or in an API gateway / JWT authorizer? (If gateway → just update JWKS URL and Issuer, no code change.)

**Access and credentials**
- Do they have access to the Descope Console and a Project ID? (If not, see Step 1.5.)
- Do they need a Management Key? (Required for user CRUD, role management, tenant management, SCIM.)

**Codebase scope**
- Are there places in the app that read claims directly from the token (e.g., `token.scp`, `req.auth.permissions`, `token.groups`)? These need a JWT Template configured before they'll work.
- Do they have Token Inline Hooks? Each one needs to be recreated as a Descope Flow Scriptlet or Generic HTTP Connector.
- Are there multiple services or microservices validating Okta tokens? Each needs to be updated to validate Descope JWTs (or have its JWKS URL + Issuer updated if using an API gateway).

**Deployment and risk**
- Do they have multiple environments (dev / staging / prod)? Each needs its own Descope project and Project ID.
- Is there a maintenance window, or does this need to be zero-downtime?

**User migration** (if they indicated existing users in Step 0)

There are three migration paths — pick one or combine them. Confirm which fits before planning.

- **Full migration**: Export all users from Okta (Management API `GET /api/v1/users`, paginated), transform attributes, and bulk-import into Descope before cutover. Use the Batch Create Users Management API directly. Optionally set a `freshlyMigrated` custom attribute to `true` on import to enable first-login Flow logic.
- **JIT (password verification)**: Don't bulk-export. When a user signs in, verify their password against the Okta Authentication API (`POST /api/v1/authn`), then create or link the user in Descope and issue a Descope session. The user must re-enter credentials but no upfront export is needed.
- **Session migration (JIT without re-login)**: The app sends the user's existing Okta session token to Descope; Descope validates it, provisions the user in Descope just-in-time, and issues a Descope token. The user only needs the app to update — no re-login. This is the highest-quality zero-disruption path. See [docs.descope.com/migrate/session-migration](https://docs.descope.com/migrate/session-migration).

**Password constraint (all paths):** Okta does not export password hashes. For full migration, plan for a reset campaign, a first-login "set new password" Flow step, or a full switch to passwordless.

**Dual-token validation (critical for phased rollouts):** During any gradual cutover, the backend will receive both Okta JWTs (from users not yet migrated) and Descope tokens. The backend must validate both — inspect the token issuer or `kid` to route to the correct validator. See `references/implementation-nuances.md` → Dual Token Validation.

**Passkeys and TOTP cannot be migrated** — Okta does not expose these seeds. Users who enrolled passkeys or TOTP in Okta must reprovision them in Descope after migration.

**Gaps to flag immediately** (don't ask — flag these proactively based on Step 0 answers)
- If they're using **Passkeys or TOTP authenticators**: **these cannot be migrated**. Okta does not expose passkey credentials or TOTP seeds. Users will need to reprovision both in Descope after cutover — this requires a user-facing prompt (add a re-enrollment step to the sign-in Flow for affected users). Flag this early; it directly affects the user experience at launch.
- If they're using **Okta Verify push notifications**: there is no direct equivalent in Descope. Recommend replacing with Email Magic Link, TOTP, or WebAuthn/Passkeys.
- If they're using **Smart Card authenticator**: contact Descope support before migrating.
- If they're using **Security Question authenticator**: no equivalent in Descope. Plan removal or replacement.
- If they're using **Okta Workflows** (separate from CIS Policies): flag as out-of-scope for this skill — Workflows require a separate evaluation.
- If they're using **Log Streams to Datadog**: Datadog is NOT a direct Okta Log Stream destination, and Descope has no native Datadog audit connector. Plan for a custom Audit Webhook.

**Console/Flow/Widget opportunities** (flag before codebase analysis, then ask):
- If the app embeds the **Okta Sign-In Widget** (`@okta/okta-signin-widget`): the migration is almost entirely Console-side. Embed the Descope Flow component (``) in the same location. No redirect required; the same low-code/no-code principle applies.
- If the app uses Okta's **hosted/redirect login** (`loginWithRedirect`, `@okta/oidc-middleware`, or any redirect-based OIDC flow): **default to the OIDC path** — set up a Federated App or Inbound App in Console and update the issuer/client-ID env vars. Do NOT recommend replacing the redirect flow with an embedded Descope component unless the user explicitly wants that. See `references/implementation-nuances.md` → OIDC compatibility path and the Node.js + @okta/oidc-middleware section (Option A).
- If the app has a custom SSO settings page: ask whether the SSO Setup Suite + Tenant Profile Widget replaces that code.
- If the app has a profile edit page or user management UI: ask whether a Descope Widget covers the use case.
- If the app has a separate MFA enrollment page: ask whether MFA should be integrated into the main sign-in Flow as a step or subflow (almost always cleaner in Descope).
- If any server-side code generates emails or runs logic during the auth journey: ask whether that logic can be a Flow Scriptlet or Connector instead.

Summarize any blockers and Console/Flow opportunities before proceeding to codebase analysis.

---

### Step 0.75: Fast-Track Assessment

Before running codebase analysis, determine whether the app qualifies for a minimal-code migration.

**Fast-track A — OIDC redirect swap (all three must be true):**
1. App uses **hosted/redirect login** (Decision 0 = redirect)
2. **Decision 1 resolved to Federated Apps** (no backend scope validation)
3. **No Token Inline Hooks** selected in the feature multiselect

**If all three are true:** this is a minimal-config migration. The work is ~80% Console setup:
- Create a Federated App in Console (Applications → Federated Apps → + Application); register the callback URL
- Configure the Descope Flow linked to the app (auth methods, branding) — this replaces the Okta hosted login page
- Update env vars: `OKTA_ISSUER` → `https://api.descope.com/DESCOPE_PROJECT_ID`; `OKTA_CLIENT_ID` → Project ID; `OKTA_CLIENT_SECRET` → a Descope Access Key
- If using `@okta/oidc-middleware`: replace with `ope

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [descope](https://github.com/descope)
- **Source:** [descope/skills](https://github.com/descope/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-descope-skills-okta-cis-to-descope
- Seller: https://agentstack.voostack.com/s/descope
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
