Android Representations#
The Curity HAAPI Android SDK delivers every HAAPI response as a typed Kotlin value. HaapiResponse is the sealed root returned by HaapiManager.start, submitForm, and followLink; concrete subtypes — HaapiRepresentation for step-shaped responses and ProblemRepresentation for RFC 7807 errors — tell you what the server is asking the client to do.
The same model hierarchy exists on iOS and React Native — see iOS Representations and React Native Representations for the per-platform shape. This page is the Android narrative reference.
SDK-thrown errors are separate. Network failures, attestation failures, and other framework errors arrive through the coroutine’s Throwable channel (or as failed Result values), not as a HaapiResponse variant. Catch them with try/catch and cast to HaapiError for the typed hierarchy. See Error Handling .
Response Hierarchy#
HaapiResponse is a sealed Kotlin interface with two sealed children:
| Sibling | When it surfaces | Implemented by |
|---|---|---|
HaapiRepresentation | The flow continues with another step | 14 concrete step classes (8 HaapiRepresentations + 6 ClientOperationStep siblings) |
ProblemRepresentation | The server rejected the request (RFC 7807) | Problem, InvalidInputProblem, AuthorizationProblem |
Branch with a when expression on the response, then narrow on the concrete step or problem class.
Step Types#
HaapiRepresentation is the sealed interface for renderable steps. A parallel ClientOperationStep sealed interface captures steps that delegate to an external operation (BankID, WebAuthn, external browser, …).
Common fields#
Every step exposes these base fields:
| Field | Type | Description |
|---|---|---|
type | RepresentationType | HAAPI representation type (8 values) |
metadata | Metadata? | Template area and view name |
actions | List<Action> | Available actions for this step |
links | List<Link> | Navigation links (e.g., “forgot password”) |
messages | List<UserMessage> | User-facing messages to display |
properties | Properties? | Step-specific properties |
The 14 step types#
Grouped by purpose:
| Group | Concrete class | Extra fields |
|---|---|---|
| Interactive | AuthenticatorSelectorStep | title: Message, authenticators: List<AuthenticatorOption> |
InteractiveFormStep | (form actions inside actions) | |
UserConsentStep | — | |
| Flow control | RedirectionStep | redirectAction: Action |
PollingStep | mainAction, cancelAction?, properties: PollingProperties | |
ContinueSameStep | — | |
| OAuth | OAuthAuthorizationResponseStep | properties: OAuthAuthorizationResponseProperties (carries code) |
Client operation (implement ClientOperationStep) | ExternalBrowserClientOperationStep | — |
BankIdClientOperationStep | activationLink? | |
EncapClientOperationStep | — | |
WebAuthnRegistrationClientOperationStep | — | |
WebAuthnAuthenticationClientOperationStep | — | |
GenericClientOperationStep | — | |
| Fallback | GenericRepresentationStep | properties? |
Branching on the result#
import se.curity.identityserver.haapi.android.sdk.models.*
import se.curity.identityserver.haapi.android.sdk.models.actions.*
val response: HaapiResponse = haapiManager.start()
when (response) {
is HaapiRepresentation -> handleRepresentation(response)
is ProblemRepresentation -> handleProblem(response)
}
private fun handleRepresentation(representation: HaapiRepresentation) {
when (representation) {
is AuthenticatorSelectorStep -> {
// representation.title.literal, representation.authenticators
// Each AuthenticatorOption carries an Action.Form for selection.
}
is InteractiveFormStep -> {
// representation.actions contains form actions;
// render their fields as a Compose / View form.
}
is PollingStep -> {
// representation.properties.status, representation.mainAction, representation.cancelAction
}
is OAuthAuthorizationResponseStep -> {
// Flow complete — extract the authorization code.
val code = representation.properties.code
}
is ClientOperationStep -> {
// Delegate to the platform (BankID, WebAuthn, external browser, …)
}
else -> {
// GenericRepresentationStep, ContinueSameStep, UserConsentStep, RedirectionStep.
}
}
}
Actions#
Actions represent operations the user can perform. They live under the sealed Action class:
| Subclass | Carries | When to use |
|---|---|---|
Action.Form | model: FormActionModel | The most common action — render fields, submit values |
Action.Selector | model: SelectorActionModel (nested options as List<Action>) | Server provides a choice (e.g., device selector); each option is itself an Action |
Action.ClientOperation | model: ClientOperationActionModel | External handling required (BankID, WebAuthn, browser launch) |
Every action also carries:
| Field | Type | Description |
|---|---|---|
kind | ActionKind | Semantic meaning: Login, Cancel, Redirect, Poll, etc. (17 values) |
title | Message? | Display title for buttons / labels |
Action.Form#
Submitting a form is the SDK’s primary write operation:
val formAction: Action.Form = …
val parameters: Map<String, Any> = mapOf(
formAction.model.fields[0].name to "user@example.com",
formAction.model.fields[1].name to "secret"
)
val next = haapiManager.submitForm(formAction, parameters)
submitForm’s parameters accept any JSON-serialisable value (String, Number, Boolean, nested maps, lists) for non-GET methods; GET form actions require Map<String, String>. See HAAPI Flow for the full parameter-type semantics across platforms.
The FormActionModel carries:
| Field | Type | Description |
|---|---|---|
fields | List<FormField> | Form fields to render |
method | String | HTTP method (e.g., "POST") |
href | String | Target URI |
actionTitle | Message? | Submit button text |
Action.ClientOperation#
Six sub-types of ClientOperationActionModel, each with its own fields: ExternalBrowser, BankId, Encap, WebAuthnRegistration, WebAuthnAuthentication, Generic. Each model includes continueActions and errorActions lists for post-operation flow.
Form Fields#
FormField is a sealed Kotlin class with 7 subclasses:
Common fields#
| Field | Type | Description |
|---|---|---|
name | String | Parameter key for submission |
value | String? | Current / default value |
label | Message? | Display label |
placeholder | Message? | Placeholder text |
isRequired | Boolean | Whether the field is required |
Rendering guide#
FormField subclass | Compose / View element | Notes |
|---|---|---|
FormField.Hidden | none | Include value in submit params automatically — don’t render |
FormField.Text | TextField / EditText | Inspect kind for keyboard type (Email, Tel, Number, Url, Color) |
FormField.Username | TextField / EditText | Disable autocapitalisation |
FormField.Password | TextField / EditText | visualTransformation = PasswordVisualTransformation() |
FormField.Select | DropdownMenu / Spinner | Render options as choices |
FormField.Checkbox | Switch / Checkbox | Respect readonly flag |
FormField.Context | none | Hidden context data (e.g., WebAuthn challenge) — don’t render |
Problems#
Problem responses follow RFC 7807. Android exposes them as concrete ProblemRepresentation subclasses:
| Class | type (ProblemType) | Extra fields |
|---|---|---|
Problem | base value | (base only) |
InvalidInputProblem | InvalidInputProblem | invalidFields: List<InvalidField> (each: name, reason?, detail: Message), errorDescription? |
AuthorizationProblem | ErrorAuthorizationResponseProblem | error, errorDescription?, iss? |
InvalidInputProblem.invalidFields is the right hook for showing field-level validation errors inline in your form.
Token Responses#
OAuthTokenManager.fetchAccessToken, refreshAccessToken, and revokeRefreshToken return a TokenResponse sealed interface. Branch its variants:
| Variant | Fields |
|---|---|
SuccessfulTokenResponse | accessToken, tokenType?, scope?, expiresIn, refreshToken?, idToken? |
ErrorTokenResponse | error, errorDescription?, errorUri? |
SDK-thrown errors (network, attestation, framework) come back through the coroutine’s exception channel, not as a TokenResponse variant. See OAuthTokenManager for the full lifecycle, and Error Handling for the difference between RFC-6749 OAuth errors (values) and framework errors.
Links#
Each Link carries:
| Field | Type | Description |
|---|---|---|
href | String | Target URI |
rel | String | Relationship type (e.g., forgot-password) |
title | Message? | Display text |
Render link sets alongside the main form — typically as secondary buttons or text links. Submit a link via haapiManager.followLink(link) to navigate.
Related: HAAPI Flow · OAuthTokenManager · Error Handling · Android SDK · Android Reference (KDoc for the full type signatures)