React Native Representations#

The Curity HAAPI React Native SDK delivers every HAAPI response as a fully-typed TypeScript value — host apps never deal with raw JSON. This page covers the HaapiResponse discriminated union: the step types you switch on, the action shapes you submit, and the form-field models you render.

The same model hierarchy exists on iOS and Android — see iOS Representations and Android Representations for the per-platform shape. Each platform exposes the same 14 step types, action shapes, and problem variants through its own type system: Swift uses an enum (HaapiResult) with protocol-conforming representation types, Kotlin uses a sealed HaapiResponse with HaapiRepresentation interface and ProblemRepresentation siblings, and React Native uses a TypeScript discriminated union. This page is the React Native narrative reference.

Equivalent type names by platform#

A quick map for cross-platform readers. The names differ but the model is the same.

ConceptReact NativeiOS (Swift)Android (Kotlin)
Top-level response wrapperHaapiResponse (discriminated on responseCategory)HaapiResult (.representation / .problem / .error)HaapiResponse (sealed; HaapiRepresentation / ProblemRepresentation / ClientOperationStep siblings)
Step-shaped representationHaapiRepresentation (discriminated on stepType)HaapiRepresentation (protocol; per-step structs conform)HaapiRepresentation (interface; per-step classes implement)
Problem-shaped representationProblemRepresentation (discriminated on problemKind)Problem (protocol; InvalidInputProblem, AuthorizationProblem conform)ProblemRepresentation (sealed; subclasses)
Step variants (14)AuthenticatorSelectorStep, InteractiveFormStep, PollingStep, …Same names, Swift-idiomSame names, Kotlin-idiom
Action variantsFormAction, SelectorAction, ClientOperationActionSame names, Swift-idiomSame names + ClientOperationStep siblings
Form-field variantsTextFormField, PasswordFormField, SelectFormField, …Same names, Swift-idiomFormField.Text, FormField.Password, … (nested)

For the per-platform narrative, see iOS Representations or Android Representations . For the full type signatures, follow the autodoc links from the reference pages: iOS Reference (DocC for IdsvrHaapiSdk), Android Reference (KDoc for identityserver.haapi.android.sdk).

The rest of this page is the React Native narrative — discriminated-union shape, switching patterns, rendering helpers.

SDK-thrown errors are separate. Network failures, attestation failures, and bridge invariants reject the Promise with a typed HaapiError instead of resolving with a HaapiResponse. Catch them with try/catch + isHaapiError(e). See Error Handling .

Response Hierarchy#

Every call to start(), submitForm(), or followLink() returns a HaapiResponse. It is a discriminated union on responseCategory:

VariantWhen it surfacesKey field
HaapiRepresentationResponse (responseCategory: 'representation')The flow continues with another steprepresentation: HaapiRepresentation
HaapiProblemResponse (responseCategory: 'problem')The server rejected the request (RFC 7807)problem: ProblemRepresentation

Branch on responseCategory first; then narrow further on representation.stepType or problem.problemKind.

Step Types#

HaapiRepresentation is a discriminated union on stepType with 14 variants. The StepType enum exposes each value:

Common fields#

Every step shares these base fields:

FieldTypeDescription
stepTypeStepTypeDiscriminator (14 values)
typeRepresentationTypeHAAPI representation type (8 values)
metadataMetadata?Template area and view name
actionsAction[]Available actions for this step
linksLink[]Navigation links (e.g., “forgot password”)
messagesUserMessage[]User-facing messages to display

The 14 step types#

Grouped by purpose:

GroupStep typeExtra fields
InteractiveAuthenticatorSelectortitle, authenticators[]
InteractiveFormproperties?
UserConsent
Flow controlRedirectionredirectAction
PollingmainAction, cancelAction?, pollingProperties
ContinueSame
OAuthOAuthAuthorizationResponseoauthProperties (carries code)
Client operationExternalBrowserClientOperation
BankIdClientOperationactivationLink?
EncapClientOperation
WebAuthnRegistrationClientOperation
WebAuthnAuthenticationClientOperation
GenericClientOperation
FallbackGenericRepresentationproperties?

Switching on stepType#

import { StepType, ActionType } from 'identityserver.haapi.reactnative.sdk'

switch (response.representation.stepType) {
    case StepType.AuthenticatorSelector:
        // Narrows to AuthenticatorSelectorStep
        for (const auth of response.representation.authenticators) {
            // auth.title.literal, auth.type, auth.action (a FormAction)
        }
        break

    case StepType.InteractiveForm:
        // Narrows to InteractiveFormStep
        const formAction = response.representation.actions.find(
            (a) => a.actionType === ActionType.Form
        )
        // Render formAction.model.fields as a React form
        break

    case StepType.Polling:
        // Narrows to PollingStep
        // Submit response.representation.mainAction to poll;
        // submit cancelAction to abort.
        break

    case StepType.OAuthAuthorizationResponse:
        // Flow complete — extract code and exchange for tokens.
        const code = response.representation.oauthProperties.code
        break

    // …other step types
}

Actions#

Actions represent operations the user can perform. Discriminated on actionType:

VariantactionTypeCarriesWhen to use
FormActionFormmodel: FormActionModelThe most common action — render fields, submit values
SelectorActionSelectoroptions: Action[]Server provides a choice (e.g., device selector); each option is itself an Action
ClientOperationActionClientOperationmodel: ClientOperationActionModelExternal handling required (BankID, WebAuthn, browser launch)

Every action also carries:

FieldTypeDescription
kindActionKindSemantic meaning: Login, Cancel, Redirect, Poll, etc. (17 values)
titleMessage?Display title for buttons / labels

FormAction#

Submitting a form is the SDK’s primary write operation:

const formAction = action as FormAction
const submitValues: Record<string, unknown> = {
    [formAction.model.fields[0].name]: 'user@example.com',
    [formAction.model.fields[1].name]: 'secret',
}
const next = await accessor.haapiManager.submitForm(formAction, submitValues)

submitForm’s parameters accept any JSON-serialisable value (string, number, boolean, null, nested objects, arrays) — matching the native iOS and Android signatures. For GET form actions, the native side still requires string-only values. See HAAPI Flow for the full parameter-type semantics across platforms.

The FormActionModel carries:

FieldTypeDescription
fieldsFormField[]Form fields to render
methodstringHTTP method (e.g., "POST")
hrefstringTarget URI
actionTitleMessage?Submit button text

ClientOperationAction#

Six sub-types, each with its own model fields, discriminated on clientOperationType: ExternalBrowser, BankId, Encap, WebAuthnRegistration, WebAuthnAuthentication, Generic. Each model includes continueActions and errorActions arrays for post-operation flow.

Form Fields#

Fields are a discriminated union on fieldType with 7 variants.

Common fields#

FieldTypeDescription
fieldTypeFormFieldTypeDiscriminator (7 values)
namestringParameter key for submission
valuestring?Current / default value
labelMessage?Display label
placeholderMessage?Placeholder text
isRequiredbooleanWhether the field is required

Rendering guide#

fieldTypeReact Native elementNotes
HiddennoneInclude value in submit params automatically — don’t render
Text<TextInput>Inspect kind for keyboard type (email, tel, etc.)
Username<TextInput>autoCapitalize="none"
Password<TextInput>secureTextEntry={true}
SelectPicker or buttonsRender options[] as choices
Checkbox<Switch>Respect readOnly flag
ContextnoneHidden context data (e.g., WebAuthn challenge) — don’t render

A helper to collect visible (non-hidden, non-context) fields when rendering a form:

import { ActionType, FormFieldType } from 'identityserver.haapi.reactnative.sdk'
import type { FormField, HaapiRepresentation } from 'identityserver.haapi.reactnative.sdk'

function collectVisibleFields(step: HaapiRepresentation): FormField[] {
    const fields: FormField[] = []
    for (const action of step.actions) {
        if (action.actionType === ActionType.Form) {
            for (const field of action.model.fields) {
                if (
                    field.fieldType !== FormFieldType.Hidden &&
                    field.fieldType !== FormFieldType.Context
                ) {
                    fields.push(field)
                }
            }
        }
    }
    return fields
}

Problems#

Problem responses follow RFC 7807, discriminated on problemKind:

VariantproblemKindExtra fields
Problembase(base only)
InvalidInputProbleminvalidInputinvalidFields[] (each: name, reason?, detail: Message), errorDescription?
AuthorizationProblemauthorizationerror, errorDescription?

InvalidInputProblem.invalidFields[] is the right hook for showing field-level validation errors inline in your React form.

Token Responses#

fetchAccessToken, refreshAccessToken, and the revoke methods all return a TokenResponse (a successful Promise resolution — not an error). Discriminated on responseType:

VariantresponseTypeFields
SuccessfulTokenResponsesuccessaccessToken, tokenType?, scope?, expiresIn, refreshToken?, idToken?
ErrorTokenResponseerrorerror, errorDescription?, errorUri?

See OAuthTokenManager for the full lifecycle, and Error Handling for the difference between RFC-6749 OAuth errors (values) and SDK-thrown errors (Promise rejections).

Each Link carries:

FieldTypeDescription
hrefstringTarget URI
relstringRelationship type (e.g., forgot-password)
titleMessage?Display text

Render link sets alongside the main form — typically rendered as secondary buttons or text links. Submit a link via accessor.haapiManager.followLink(link) to navigate.

Was this helpful?