Skip to content
Migrated from Okta ...
 
Notifications
Clear all

Migrated from Okta to Azure AD for 3000 users - what broke and what didn't

7 Posts
7 Users
0 Reactions
15 Views
(@dianar)
Honorable Member
Joined: 2 months ago
Posts: 487
Topic starter   [#25268]

Just finished a 6-month migration for a 3k-user org. Objective was cost consolidation and tighter integration with existing MS stack. High-level takeaways below.

**What broke:**
* Custom SAML apps with non-standard claims. Azure AD's claim mapping is less flexible. Had to renegotiate with 3 vendors.
* Our JIT access workflows tied to Okta Groups API. Azure AD's Graph API rate limits caused queue backlogs.
* Break-glass procedures reliant on Okta's "Always Allow" MFA rule. Azure AD Conditional Access equivalent (named locations) required re-architecting network zones.

**What held:**
* Standard OIDC/SAML integrations (like Google Workspace, Salesforce) were straightforward.
* MFA rollout actually improved. Azure MFA's number matching reduced push fatigue.
* Basic user lifecycle (on/off-boarding) via HR-driven provisioning worked with minimal adjustment.

Biggest surprise was the monitoring gap. Azure AD sign-in logs lack the granularity of Okta's system log for some automated playbooks. Now building custom queries in Sentinel.

Biggest win was ditching the per-app MFA cost.

What specific pain points did others hit with SCIM or Conditional Access policies?


Five nines? Prove it.


   
Quote
(@infra_architect_rebel)
Honorable Member
Joined: 5 months ago
Posts: 544
 

Principal infra architect for ~2k user finance shop, running hybrid AD, Entra ID, and a bunch of IAM-glued SaaS.

* **Real Pricing:** Okta's visible $4-8/user/mo becomes $18+/user/mo once you add MFA, Lifecycle, and Advanced SSO modules. Entra ID "included" with M365 E5 is a trap - expect 20-30% more engineering time on Azure AD Connect health monitoring, Conditional Access tuning, and Sentinel log parsing.
* **Flexibility Deficit:** Azure AD's claim transformation is a brick wall. Okta handles complex SAML assertions in the UI. With Azure AD, you're writing custom claim mapping policies in PowerShell for anything non-standard, and it often just fails. We scripted around it, but it's a break.
* **API Hard Limit:** The Okta Groups API throttles at 600 requests per minute per org. Azure AD Graph/MS Graph has a 200,000 per 20-second *tenant* limit, but per-app and per-principal limits are brutal. Our JIT system hit 429s during peak syncs (10-15k user updates). Required a queue redesign with exponential backoff.
* **Break-Glass Reality:** Okta's "Always Allow" MFA bypass is a clean emergency rule. Entra's equivalent requires defining trusted *named locations* (IPs). If your break-glass is a cloud-based VPN or doesn't have a static IP, you're rebuilding the procedure. We had to stand up a dedicated, static IP jump host.

If you're >80% Microsoft on desktop (Intune/Windows), Office, and Teams, go Entra ID. You'll eat the integration pain but win on bundled cost. If you have a heterogenous app portfolio with finicky SAML requirements or heavy API-driven automation, Okta saves net engineering hours. Tell me your ratio of custom SAML apps to standard OIDC, and your yearly headcount growth projection.


Simplicity is the ultimate sophistication


   
ReplyQuote
(@consulting_contractor_mike)
Honorable Member
Joined: 6 months ago
Posts: 393
 

Your point about the "included" cost being an engineering trap is spot on. I've seen teams budget for licenses but completely overlook the operational lift of maintaining hybrid sync health and Conditional Access policies that don't break legacy auth. The hidden cost isn't just time, it's risk exposure during incidents when you're debugging sync latency.

On the API limits, the per-principal throttling is the real killer. That 200k tenant limit looks great on paper, but when a single service principal hitting a 429 can stall your entire JIT workflow, you're forced into a far more complex, distributed queue design than Okta ever demanded. We ended up implementing a sidecar pattern just to manage token rotation and retry logic across multiple app registrations.

The break-glass comparison is stark. Entra's named location requirement forces a network-centric emergency model, which is a step backwards. It assumes your crisis is predictable and location-bound. What about a scenario where your entire network egress is compromised? You're now redefining "trusted" IPs under duress. Okta's rule-based bypass, while also a risk, at least abstracted that away.


Mike


   
ReplyQuote
(@crm_hopper)
Honorable Member
Joined: 7 months ago
Posts: 472
 

Your point on Sentinel is where the real tax shows up. Okta's system log is ugly but you can just use it. Azure's sign-in logs are a fragmented mess, so you're forced into KQL and Sentinel, which is a whole other skillset and license cost just to see what's broken.

The Conditional Access pain starts when you have contractors or non-M365 users. Named locations are fine until you need to exempt a VPN range that overlaps with a coffee shop IP block someone's using. Then you're back to building custom logic anyway.

Biggest SCIM headache for us was the attribute mapping. If your HR system sends a department code as "DeptCode" but Azure expects "department", you're writing custom expressions, not just dragging a line in a UI. It works, but it's fragile.


CRM is a necessary evil


   
ReplyQuote
(@dannyz)
Estimable Member
Joined: 3 months ago
Posts: 171
 

Thanks for sharing this. The mention of SCIM mapping is really timely for me. We're planning a similar move next quarter.

Could you say a bit more about those custom expressions? Like, was it mostly for weird formatting of usernames, or was it something more complex like nested attributes? I'm nervous about breaking our current Jira provisioning flow.

Also, the Sentinel monitoring gap is something I hadn't considered at all. That's a bit scary.



   
ReplyQuote
(@davidn)
Reputable Member
Joined: 2 months ago
Posts: 305
 

Your point about SCIM mapping being a tripwire is something we ran into as well. For us, the main issue was custom expressions to handle multi-valued attributes in our HR feed. Okta's UI let you map "Department" to "department" and call it a day. In Azure AD, when our HR system sent an array like ["Sales", "Support"] for a shared role, the default mapping just took the first value. We had to write a custom expression to concatenate them with a delimiter, which then broke downstream apps expecting a single string.

The monitoring gap you mentioned is real, but we found a workaround before committing to Sentinel. Azure AD's built-in workbook for provisioning errors gave us enough visibility to debug the worst of the SCIM failures. It's not as good as a proper log, but it might save you some license cost in the short term.

On Conditional Access, did the shift to named locations force you to re-categorize all your network zones, or were you able to keep most of your existing IP-based rules?


Measure twice, buy once.


   
ReplyQuote
(@ci_cd_junkie)
Honorable Member
Joined: 7 months ago
Posts: 476
 

That bit about renegotiating with vendors for custom SAML claims hits hard. We had the same thing - one vendor's app expected a specific claim format for authorization that Azure AD just wouldn't produce out of the box. Ended up writing a custom claims mapping policy, but it felt like a hack.

Your point on the monitoring gap is the real hidden cost. Okta's System Log is noisy but searchable. In Azure AD, trying to recreate a simple "failed provisioning events" dashboard for our service desk took a week of KQL. It's functional now, but the operational burden shifted from the IAM team to the platform engineering team, which nobody budgeted for.

The Conditional Access one is interesting. We found "named locations" far too rigid for dynamic break-glass. Had to build a separate PIM-activated security group that triggers a Logic App to temporarily modify the CA policy. It's convoluted, but it works. How did you handle the network zone re-architecting? Did you go down the trusted IPs path or something else?


pipeline all the things


   
ReplyQuote