Skip to content

fix(swiftui-mfa): Journey OIDC config, SDK 2.0, and MFA auto-registration (SDKS-5029)#113

Open
george-bafaloukas-forgerock wants to merge 4 commits into
mainfrom
fix/sdks-5029-journey-config-oidc
Open

fix(swiftui-mfa): Journey OIDC config, SDK 2.0, and MFA auto-registration (SDKS-5029)#113
george-bafaloukas-forgerock wants to merge 4 commits into
mainfrom
fix/sdks-5029-journey-config-oidc

Conversation

@george-bafaloukas-forgerock
Copy link
Copy Markdown
Contributor

@george-bafaloukas-forgerock george-bafaloukas-forgerock commented May 15, 2026

Summary

Fixes four issues reported in SDKS-5029 in the swiftui-mfa sample app.

  • Journey configuration: Replace the 3-field stub in JourneyManager.swift with a full Journey.createJourney block including PingJourney.OidcModule.config (clientId, redirectUri, discoveryEndpoint, scopes), scoped to PingAM / AIC only
  • import PingOidc: Added to JourneyManager.swift; PingOidc wired into the Xcode project as a linked framework
  • Journey tree name: LoginViewModel.startLogin() annotated with a TODO comment explaining where to find the tree name in AM Admin and that it is case-sensitive
  • MFA auto-registration: When Journey returns a HiddenValueCallback with an MFA registration URI, the credential is now registered automatically. A MfaRegistrationView shows a spinner while registration is in progress and a success state with a Continue button when done — the raw URI is never shown to the user
  • SDK upgrade: ping-ios-sdk pinned to 2.0.0 (was develop branch); pingone-signals-sdk-ios bumped to 5.4.0
  • README: Rewritten setup section with a full AM/AIC config example, clarification that AppConfiguration.swift is optional, and a step for setting the Journey tree name

Test plan

  • Build succeeds on iOS Simulator (verified: iPhone 17 Pro, iOS 26.4)
  • Journey login with username/password callbacks renders correctly
  • On a node containing a HiddenValueCallback with valueId == "mfaDeviceRegistration", the spinner appears automatically and registration completes without user input
  • Continue button is disabled during registration and enabled after
  • Normal callback nodes (NameCallback, PasswordCallback) still render as before

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added MFA registration progress UI with visual feedback during credential registration, including a loading state and success confirmation.
  • Documentation

    • Updated setup and configuration guidance for MFA registration workflows.

Review Change Stack

…DKS-5029)

- Add PingOidc to project dependencies (build file, frameworks phase, package product)
- Replace 3-field Journey stub with full Journey.createJourney block including
  PingJourney.OidcModule.config (clientId, redirectUri, discoveryEndpoint, scopes)
- Add commented-out PingOne block so sample covers both AM/AIC and PingOne environments
- Annotate every placeholder with TODO comments explaining what to fill in
- Add import PingOidc to JourneyManager.swift
- Add TODO comment on Journey tree name in LoginViewModel.startLogin()
- Update README: full config examples for both AM/AIC and PingOne, clarify
  AppConfiguration.swift is optional, fix FailureNode.cause non-optional usage,
  note journey name is case-sensitive
- Package.resolved: pin ping-ios-sdk to 2.0.0 (was develop branch), bump
  pingone-signals-sdk-ios to 5.4.0

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Remove the commented-out PingOne standalone configuration block from
JourneyManager.swift and all corresponding PingOne references from the
README — this sample targets PingAM / AIC exclusively.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…KS-5029)

When the Journey returns a HiddenValueCallback with an MFA registration URI,
register the credential automatically instead of exposing it in the UI.

- JourneyManager: add isMfaRegistering published flag, set true/false around
  the credential registration call in detectAndHandleMfaRegistration
- LoginViewModel: forward isMfaRegistering from JourneyManager; add
  isMfaRegistrationNode computed property to detect the registration node
- LoginScreen: branch on isMfaRegistrationNode before the normal callback list;
  show MfaRegistrationView (spinner while registering, success + Continue when done)
- Add MfaRegistrationView component: ProgressView during registration,
  checkmark shield on success, Continue button enabled only after completion

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 15, 2026

Warning

Rate limit exceeded

@george-bafaloukas-forgerock has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 48 minutes and 18 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 696cecf2-baf9-4b99-b829-fea5cb27319e

📥 Commits

Reviewing files that changed from the base of the PR and between 3df13d3 and 4a4245f.

📒 Files selected for processing (4)
  • iOS/swiftui-mfa/MfaSample/MfaSample/Core/Managers/JourneyManager.swift
  • iOS/swiftui-mfa/MfaSample/MfaSample/ViewModels/LoginViewModel.swift
  • iOS/swiftui-mfa/MfaSample/MfaSample/Views/Screens/LoginScreen.swift
  • iOS/swiftui-mfa/README.md
📝 Walkthrough

Walkthrough

This PR integrates MFA credential registration support into the iOS SwiftUI sample by adding the PingOidc dependency, configuring Journey with explicit OIDC settings, tracking registration state through the view model, rendering a dedicated registration UI, and updating documentation.

Changes

MFA Registration End-to-End Implementation

Layer / File(s) Summary
PingOidc Dependency Integration
iOS/swiftui-mfa/MfaSample/MfaSample.xcodeproj/project.pbxproj, iOS/swiftui-mfa/MfaSample/MfaSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
PingOidc product added to Xcode target build configuration, included in Frameworks build phase, and packageProductDependencies; SwiftPM pin for ping-ios-sdk updated to latest revision while maintaining 2.0.0 version.
JourneyManager: OIDC Configuration and MFA Registration Handling
iOS/swiftui-mfa/MfaSample/MfaSample/Core/Managers/JourneyManager.swift
PingOidc imported; @Published isMfaRegistering flag added for tracking registration state. Journey initialization replaced with PingAM/PingOne AIC template including serverUrl, realm, cookie, and OidcModule configuration (clientId, redirectUri, discoveryEndpoint, scopes). MFA registration detection now toggles isMfaRegistering around credential registration call and returns after first matching HiddenValueCallback.
LoginViewModel: MFA Registration State Exposure
iOS/swiftui-mfa/MfaSample/MfaSample/ViewModels/LoginViewModel.swift
@Published isMfaRegistering property added and subscribed to JourneyManager's state. Computed property isMfaRegistrationNode detects MFA device registration HiddenValueCallback in current node. Comments added to document Journey tree name configuration.
LoginScreen: MFA Registration UI Component
iOS/swiftui-mfa/MfaSample/MfaSample/Views/Screens/LoginScreen.swift
Conditional branch added to render MfaRegistrationView when isMfaRegistrationNode is true. New MfaRegistrationView component switches between registering spinner state and success state, includes wired Continue button disabled while registering.
README: Journey Configuration and MFA Registration Guidance
iOS/swiftui-mfa/README.md
Dependencies section updated to specify Ping iOS SDK 2.0.0+ modules including PingOidc. Prerequisites and installation steps expanded with explicit PingAM/AIC server configuration, OATH/Push module setup, Journey registration node configuration, and OIDC client settings. Code examples updated to show Journey.createJourney template with TODO placeholders and revised callback/error handling. Troubleshooting expanded to include OIDC parameter verification.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant LoginScreen
  participant LoginViewModel
  participant JourneyManager
  participant PingOidc
  User->>LoginScreen: Interacts with login flow
  LoginViewModel->>JourneyManager: detectAndHandleMfaRegistration()
  JourneyManager->>JourneyManager: isMfaRegistering = true
  JourneyManager->>PingOidc: registerMfaCredential()
  PingOidc-->>JourneyManager: registration callback processed
  JourneyManager->>JourneyManager: isMfaRegistering = false
  JourneyManager-->>LoginViewModel: publish isMfaRegistering state
  LoginViewModel-->>LoginScreen: update isMfaRegistrationNode
  LoginScreen->>LoginScreen: render MfaRegistrationView
  User->>LoginScreen: taps Continue button
  LoginScreen->>LoginViewModel: submitNode()
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • ForgeRock/sdk-sample-apps#105: Updates MfaSample.xcodeproj to require ping-ios-sdk 2.0.0, directly related to the PingOidc dependency wiring in this PR.

Suggested reviewers

  • spetrov
  • rodrigoareis

Poem

🐰 A registration flow takes shape,
PingOidc now joins the escape,
State flows down through views so bright,
MFA's registered—all feels right! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: Journey OIDC config, SDK 2.0 upgrade, and MFA auto-registration. It is concise, specific, and clearly conveys the primary focus of the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sdks-5029-journey-config-oidc

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
iOS/swiftui-mfa/README.md (1)

236-251: ⚡ Quick win

Consider documenting URL scheme registration for the OAuth2 redirect URI.

The installation instructions include configuring the redirectUri (e.g., "com.example.mfasample://oauth2redirect"), but don't explicitly mention that developers must register the corresponding URL scheme (com.example.mfasample) in Info.plist under CFBundleURLTypes.

Without this registration, the OAuth2 redirect will fail at runtime. Consider adding a note or step reminding developers to register their custom URL scheme.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@iOS/swiftui-mfa/README.md` around lines 236 - 251, Add a short note in the
README near the redirectUri configuration (the block that calls
Journey.createJourney and sets oidcConfig.redirectUri in JourneyManager.swift)
instructing developers to register the redirect URI's URL scheme (the scheme
part of oidcConfig.redirectUri, e.g., "com.example.mfasample") in the app's
Info.plist under CFBundleURLTypes/CFBundleURLSchemes so the OAuth2 redirect will
be handled by the app at runtime.
iOS/swiftui-mfa/MfaSample/MfaSample/ViewModels/LoginViewModel.swift (1)

33-39: ⚡ Quick win

Consider centralizing MFA registration node detection logic.

The detection logic for MFA registration nodes is duplicated between LoginViewModel.isMfaRegistrationNode (lines 35-37) and JourneyManager.detectAndHandleMfaRegistration (lines 131-133). Both check for HiddenValueCallback with valueId == "mfaDeviceRegistration" and a non-empty value.

If the detection criteria change in the future, both locations must be updated in sync. Consider either:

  1. Exposing a helper method from JourneyManager to check if a node is an MFA registration node
  2. Adding a comment linking both implementations to maintain awareness of the coupling
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@iOS/swiftui-mfa/MfaSample/MfaSample/ViewModels/LoginViewModel.swift` around
lines 33 - 39, Duplicate MFA-registration detection exists in
LoginViewModel.isMfaRegistrationNode and
JourneyManager.detectAndHandleMfaRegistration: both look for a
HiddenValueCallback with valueId == "mfaDeviceRegistration" and non-empty value;
centralize by moving that check into a single helper (e.g.,
JourneyManager.isMfaRegistrationNode(node: Node) or a static helper on
JourneyManager) and update LoginViewModel.isMfaRegistrationNode to call that
helper (inspect currentNode as ContinueNode and pass it), then remove the
duplicated logic from detectAndHandleMfaRegistration or call the same helper
there so both locations reference the single implementation (referenced symbols:
isMfaRegistrationNode, currentNode, ContinueNode, HiddenValueCallback,
JourneyManager.detectAndHandleMfaRegistration).
iOS/swiftui-mfa/MfaSample/MfaSample/Core/Managers/JourneyManager.swift (1)

127-140: ⚡ Quick win

Consider surfacing registration failures to the user.

Currently, if registerMfaCredential encounters an error (e.g., invalid URI, SDK failure), the error is logged but isMfaRegistering is still set to false, causing the UI to display a success state. Users won't know registration failed until they attempt to authenticate with MFA on a subsequent login.

Consider adding an error state that:

  • Exposes registration failures via a published property
  • Shows an error message in MfaRegistrationView
  • Allows retry or informing the user to contact support
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@iOS/swiftui-mfa/MfaSample/MfaSample/Core/Managers/JourneyManager.swift`
around lines 127 - 140, detectAndHandleMfaRegistration currently sets
isMfaRegistering true then calls registerMfaCredential and unsets
isMfaRegistering but does not expose errors to the UI; change it to catch
failures from registerMfaCredential and surface them via a new `@Published`
property (e.g., mfaRegistrationError: String? or isMfaRegistrationFailed: Bool
plus mfaRegistrationErrorMessage) on JourneyManager, ensure isMfaRegistering is
cleared in a finally/defer-like block, set the error property when
registerMfaCredential throws or returns failure, and update MfaRegistrationView
to observe this published property to show the error and offer a retry action
that calls detectAndHandleMfaRegistration/registerMfaCredential again.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@iOS/swiftui-mfa/MfaSample/MfaSample/Core/Managers/JourneyManager.swift`:
- Around line 127-140: detectAndHandleMfaRegistration currently sets
isMfaRegistering true then calls registerMfaCredential and unsets
isMfaRegistering but does not expose errors to the UI; change it to catch
failures from registerMfaCredential and surface them via a new `@Published`
property (e.g., mfaRegistrationError: String? or isMfaRegistrationFailed: Bool
plus mfaRegistrationErrorMessage) on JourneyManager, ensure isMfaRegistering is
cleared in a finally/defer-like block, set the error property when
registerMfaCredential throws or returns failure, and update MfaRegistrationView
to observe this published property to show the error and offer a retry action
that calls detectAndHandleMfaRegistration/registerMfaCredential again.

In `@iOS/swiftui-mfa/MfaSample/MfaSample/ViewModels/LoginViewModel.swift`:
- Around line 33-39: Duplicate MFA-registration detection exists in
LoginViewModel.isMfaRegistrationNode and
JourneyManager.detectAndHandleMfaRegistration: both look for a
HiddenValueCallback with valueId == "mfaDeviceRegistration" and non-empty value;
centralize by moving that check into a single helper (e.g.,
JourneyManager.isMfaRegistrationNode(node: Node) or a static helper on
JourneyManager) and update LoginViewModel.isMfaRegistrationNode to call that
helper (inspect currentNode as ContinueNode and pass it), then remove the
duplicated logic from detectAndHandleMfaRegistration or call the same helper
there so both locations reference the single implementation (referenced symbols:
isMfaRegistrationNode, currentNode, ContinueNode, HiddenValueCallback,
JourneyManager.detectAndHandleMfaRegistration).

In `@iOS/swiftui-mfa/README.md`:
- Around line 236-251: Add a short note in the README near the redirectUri
configuration (the block that calls Journey.createJourney and sets
oidcConfig.redirectUri in JourneyManager.swift) instructing developers to
register the redirect URI's URL scheme (the scheme part of
oidcConfig.redirectUri, e.g., "com.example.mfasample") in the app's Info.plist
under CFBundleURLTypes/CFBundleURLSchemes so the OAuth2 redirect will be handled
by the app at runtime.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a309c585-24c1-40ed-b896-2db888593a07

📥 Commits

Reviewing files that changed from the base of the PR and between 8206f33 and 3df13d3.

📒 Files selected for processing (6)
  • iOS/swiftui-mfa/MfaSample/MfaSample.xcodeproj/project.pbxproj
  • iOS/swiftui-mfa/MfaSample/MfaSample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
  • iOS/swiftui-mfa/MfaSample/MfaSample/Core/Managers/JourneyManager.swift
  • iOS/swiftui-mfa/MfaSample/MfaSample/ViewModels/LoginViewModel.swift
  • iOS/swiftui-mfa/MfaSample/MfaSample/Views/Screens/LoginScreen.swift
  • iOS/swiftui-mfa/README.md

- Centralize MFA registration node detection: move the HiddenValueCallback
  check into JourneyManager.nodeIsMfaRegistration (static helper);
  LoginViewModel.isMfaRegistrationNode delegates to it, eliminating duplication
- Surface registration failures: registerMfaCredential now throws; errors are
  caught in detectAndHandleMfaRegistration and published via mfaRegistrationError;
  use defer to guarantee isMfaRegistering is always cleared
- MfaRegistrationView: accept errorMessage param, show error state with
  exclamationmark.shield icon, and relabel button to "Retry" on failure
- README: add URL scheme registration note next to the redirectUri config step

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant