Configuration (UI Layer)#
The UI Layer’s configuration object — HaapiUIKitConfiguration on iOS, WidgetConfiguration on Android — carries every parameter the framework needs to connect to the Curity Identity Server, render the flow, and (when configured) bind tokens, fall back to Dynamic Client Registration, or collect risk-assessment context. Build it once at application startup and inject it through HaapiUIKitApplication (iOS) or HaapiUIWidgetApplication (Android).
For presentation knobs (modal vs stack, polling interval, selector style), see Presentation Options . For starting the flow itself, see Flow Lifecycle .
Minimal Configuration#
The five required parameters are the same on both platforms: client ID, base URL, token endpoint, authorization endpoint, and the app redirect URI. Everything else is optional.
Build HaapiUIKitConfiguration once in AppDelegate.application(_:didFinishLaunchingWithOptions:) and use it to construct HaapiUIKitApplication:
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var haapiUIKitConfiguration = HaapiUIKitConfigurationBuilder(
clientId: Constants.clientId,
baseUrl: Constants.baseURL,
tokenEndpointUrl: Constants.tokenEndpointURL,
authorizationEndpointUrl: Constants.authorizationEndpointURL,
appRedirect: Constants.appRedirectURIString
).build()
var haapiUIKitApplication: HaapiUIKitApplication!
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
haapiUIKitApplication = HaapiUIKitApplicationBuilder(
haapiUIKitConfiguration: haapiUIKitConfiguration
).build()
return true
}
}clientId — the OAuth client ID configured on the Curity Identity Server with the haapi capability.
baseUrl — the base URL of the Curity Identity Server (the runtime endpoint base, typically the issuer URL).
tokenEndpointUrl — the OAuth token endpoint, typically <baseUrl>/oauth/v2/oauth-token.
authorizationEndpointUrl — the OAuth authorization endpoint, typically <baseUrl>/oauth/v2/oauth-authorize.
appRedirect — the app redirect URI registered on the OAuth client (custom scheme or universal link).
For SwiftUI apps, build the configuration in AppDelegate the same way and hook it with @UIApplicationDelegateAdaptor.
Implement HaapiUIWidgetApplication on your Application subclass and expose widgetConfiguration from it:
class ClientApplication : Application(), HaapiUIWidgetApplication {
private val baseUri = URI.create("https://idsvr.example.com")
override val widgetConfiguration: WidgetConfiguration
get() = WidgetConfiguration.Builder(
clientId = "my-client-id",
baseUri = baseUri,
tokenEndpointUri = baseUri.resolve("/oauth/v2/oauth-token"),
authorizationEndpointUri = baseUri.resolve("/oauth/v2/oauth-authorize"),
appRedirect = "app://haapi"
).build()
}clientId — the OAuth client ID configured on the Curity Identity Server with the haapi capability.
baseUri — java.net.URI for the Curity Identity Server runtime base.
tokenEndpointUri — the OAuth token endpoint.
authorizationEndpointUri — the OAuth authorization endpoint.
appRedirect — the app redirect URI registered on the OAuth client.
Register ClientApplication in AndroidManifest.xml via android:name=".ClientApplication" and also register HaapiFlowActivity:
<application android:name=".ClientApplication" ...>
<activity android:name="se.curity.identityserver.haapi.android.ui.widget.HaapiFlowActivity" />
<!-- ... -->
</application> Security Configuration#
The four security knobs — DCR fallback, Token Binding, Client Authentication, Risk Assessment — are wired on the UI-Layer builder using the same parameter types as at the SDK Layer. The SDK-Layer pages carry the per-parameter depth; the UI-Layer call sites are:
| Knob | iOS builder call | Android builder call | Parameter depth |
|---|---|---|---|
| DCR fallback | setDCRConfiguration(configuration:) | setDcr(...) | DCR |
| Token Binding | setTokenBoundConfiguration(configuration:) | setTokenBoundConfiguration(...) | Token Binding |
| Client Authentication | setClientAuthenticationMethod(method:) | setClientAuthenticationMethod(...) | Client Authentication |
| Risk Assessment | setRiskAssessmentConfiguration(_:) | setContext(...) ¹ | Risk Assessment |
¹ On Android, risk assessment is wired by passing the application Context rather than a dedicated configuration object — setContext(applicationContext) is the wiring call. The framework then reads OS name, OS version, device model, and package name from that Context internally and forwards them on every HAAPI request. iOS exposes the same four fields as explicit parameters on RiskAssessmentConfiguration because UIDevice is main-actor-isolated; see Risk Assessment for the field-by-field detail on both platforms.
Example — configuring DCR fallback + a Secret client authentication method on the UI-Layer builder (chain these onto the foundational builder shown above):
// ... required parameters from the Minimal Configuration block above
.setClientAuthenticationMethod(
method: ClientAuthenticationMethodSecret("foo")
)
.setDCRConfiguration(
configuration: DCRConfiguration(
templateClientId: "dcr-template-client-haapi-ios",
clientRegistrationEndpointUrl: URL(
string: "/oauth/oauth-registration",
relativeTo: baseURL
)
)
)
.build() // ... required parameters from the Minimal Configuration block above
.setClientAuthenticationMethod(
WidgetConfiguration.ClientAuthenticationMethod.Secret("my-secret")
)
.setDcr(
WidgetConfiguration.Dcr(
templateClientId = "dcr-template-client-haapi-android",
clientRegistrationEndpointUri = baseUri.resolve("/oauth/oauth-registration"),
context = this
)
)
.build() The UI Layer composes the SDK Layer’s security wiring, but server-side prerequisites must already be in place before the client-side call has any effect:
setDCRConfiguration/setDcr— without a configured template HAAPI client on the Curity Identity Server that references the main client viaauthenticate-client-by, the framework’s first registration call returns 401 or 404 and the flow fails before the user sees a screen.setTokenBoundConfiguration— when the server hasissue-token-bound-authorization-code=truebut the client passesUnboundedTokenConfiguration(or omits the call), the token-exchange step returnsinvalid_dpop_proof. The mismatch is silent until the user has already authenticated; see the matrix in Token Binding .setRiskAssessmentConfiguration/setContext— without a configured risk-assessment integration at the Curity profile level, the device-context fields are forwarded but never consumed, and the auth step that depends on the risk score either runs without a score or fails with a flow-level error.
Configure both sides together; the SDK-Layer pages linked in the table above carry the server-side prerequisites for each knob.
How to implement this: Flow Lifecycle · Presentation Options · DCR · Token Binding · Client Authentication