How to Integrate Risk Assessment#

You want to integrate with a risk-scoring authentication service (BankID is the canonical case) that needs device-context fields — OS name, OS version, device model, application identifier — on every HAAPI request. The SDK collects these fields once at startup and attaches them to outgoing requests; the Curity Identity Server forwards them to the assessment service during flow steps that need them.

For the concept and security trade-offs, see Risk Assessment . For per-field detail and platform asymmetry, see Risk Assessment (SDK Layer) . This page is the end-to-end task walkthrough.

Prerequisites#

Risk assessment is server-driven — the client merely supplies device context. Before configuring the client:

  1. the Curity Identity Server version 9.7.0 or later. Earlier versions do not support the risk-assessment forwarding protocol.
  2. A configured risk-assessment integration at the Curity profile level. BankID’s risk-assessment functionality, or another vendor’s equivalent. The integration carries the upstream risk-service URL, threshold settings, and auth-step bindings.
  3. An authentication flow that includes a risk-assessment step. Risk assessment fires only at specific points in the flow (typically before high-value steps); flows without those steps do not invoke it even when the client-side fields are configured.

Refer to the BankID Relying Party Guidelines for version 6 for the upstream service requirements and acceptance criteria.

Step-by-Step#

1. Decide where to construct the configuration#

  • iOSRiskAssessmentConfiguration accesses UIDevice properties, which are main-actor-isolated. Build it in AppDelegate.application(_:didFinishLaunchingWithOptions:) (UIKit) or the App’s init (SwiftUI), not from a background thread.
  • Android — pass applicationContext from Application.onCreate. The framework reads OS name, version, device model, and package name from that Context internally.

2. Wire it onto your builder#

SDK Layer#

let riskAssessmentConfiguration = RiskAssessmentConfiguration(
    operatingSystemName: UIDevice.current.systemName,
    operatingSystemVersion: UIDevice.current.systemVersion,
    deviceModelName: UIDevice.current.deviceModelName,
    applicatonIdentifier: Bundle.main.bundleIdentifier!
)

let haapiConfiguration = HaapiConfiguration(
    // ...other configuration
    riskAssessmentConfiguration: riskAssessmentConfiguration
)

UI Layer#

let riskAssessmentConfiguration = try! RiskAssessmentConfiguration()

let configurationBuilder = HaapiUIKitConfigurationBuilder(/* ... */)
    .setRiskAssessmentConfiguration(riskAssessmentConfiguration)

Note the SDK-Layer parameter is misspelled in the framework (applicatonIdentifier, missing the second i in “application”); type it verbatim or the code won’t compile. The UI Layer’s parameterless RiskAssessmentConfiguration() reads the same four fields from UIDevice and Bundle.main internally.

3. (Android) Confirm android:allowBackup="true" in your manifest#

allowBackup defaults to true on modern Android — leave it alone if you haven’t explicitly set it to false. Some risk-assessment integrations rely on persisted device context surviving backup-and-restore for continuity.

<application
    android:name=".ClientApplication"
    android:allowBackup="true"
    ...>

Verify It Works#

  • Run a HAAPI flow that includes a risk-assessment step (typically a high-value authentication like BankID).
  • Inspect the request payloads at the proxy / server log — the four fields (OS name, OS version, device model, application identifier) should be present.
  • Trigger the high-risk scenarios your service detects (unfamiliar device, geo anomaly) and confirm the assessment service returns the expected risk score.

Pitfalls#

  • Don’t configure if you don’t use a risk service. Risk assessment adds device-context lookups at startup and per-request payload overhead. Most apps don’t need it. Skip it unless your flow includes a risk-assessment step.
  • iOS main-actor isolation. RiskAssessmentConfiguration must be built on the main thread because it touches UIDevice. Constructing it from a background queue results in a runtime crash on Swift 6 actors.
  • iOS parameter typo is permanent. applicatonIdentifier (missing one i) is preserved for binary compatibility. Type it verbatim. A future major release may correct it.
  • Android allowBackup=false breaks continuity. Apps that opted out of backup-and-restore (often for security reasons) lose persisted risk-assessment context across factory resets and device migrations. Some integrations cope; others don’t. Test the end-to-end backup-and-restore path before disabling allowBackup.
  • Server-side prerequisite missing. Without a configured risk-assessment integration on the CIS profile, the device-context fields are forwarded but never consumed — flows run without a risk score, or fail with a flow-level error when the auth step expects one.

Was this helpful?