Quickstart — iOS#
This walkthrough gets a HAAPI-authenticated login working in a fresh iOS app in roughly 15 minutes. It uses the UI Layer (IdsvrHaapiUIKit) because prebuilt screens are the fastest path to a working flow. If your app needs custom screens, start at the layer chooser instead.
Before You Start#
You’ll need:
- Xcode 15+ and an iOS 14+ deployment target.
- A Curity Identity Server with a HAAPI-capable OAuth client configured. The
clientId, base URL, token endpoint, authorization endpoint, and redirect URI for that client. - An iOS device or simulator. If attestation isn’t available on the target device, configure DCR fallback (covered in step 6).
Step 1 — Install the Framework#
The iOS UIKit ships as its own artifact, IdsvrHaapiUIKit. The Driver and SDK are pulled in as transitive dependencies — no separate declarations needed.
dependencies: [
.package(url: "https://github.com/curityio/ios-idsvr-haapi-sdk-dist")
]
// ... and in your target's dependencies:
.product(name: "IdsvrHaapiUIKit", package: "ios-idsvr-haapi-sdk-dist") pod 'IdsvrHaapiUIKit' In your Swift files, import IdsvrHaapiUIKit.
Step 2 — Build the Configuration#
Declare the configuration as an AppDelegate property (so it’s built once at instantiation) and build the HaapiUIKitApplication in application(_:didFinishLaunchingWithOptions:):
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var haapiUIKitConfiguration = HaapiUIKitConfigurationBuilder(
clientId: "my-haapi-client",
baseUrl: URL(string: "https://idsvr.example.com")!,
tokenEndpointUrl: URL(string: "https://idsvr.example.com/oauth/v2/oauth-token")!,
authorizationEndpointUrl: URL(string: "https://idsvr.example.com/oauth/v2/oauth-authorize")!,
appRedirect: "app://haapi"
).build()
var haapiUIKitApplication: HaapiUIKitApplication!
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
haapiUIKitApplication = HaapiUIKitApplicationBuilder(
haapiUIKitConfiguration: haapiUIKitConfiguration
).build()
return true
}
}
This is the same pattern documented in Configuration — your final code should match.
Step 3 — Conform to HaapiFlowResult#
Pick the view controller that will trigger authentication and make it conform to HaapiFlowResult:
class LoginViewController: UIViewController, HaapiFlowResult {
func didReceiveOAuthTokenModel(_ tokenModel: OAuthTokenModel) {
// Persist tokens (Keychain) and navigate to authenticated state.
// REMOVE THIS print BEFORE SHIPPING — it leaks the access token to logs.
print("Got token: \(tokenModel.accessToken)")
}
func didReceiveError(_ error: Error) {
// Show user-facing error
print("Flow error: \(error)")
}
}
Step 4 — Start the Flow#
Trigger the flow on user action — typically a “Sign In” button:
@IBAction func signInTapped(_ sender: UIButton) {
do {
try HaapiFlow.start(
from: self,
haapiUIKitApplication: UIApplication.shared.haapiUIKitApplication,
haapiDeepLinkManageable: HaapiDeepLinkManager.shared
)
} catch {
// Configuration error — flow couldn't start
}
}
extension UIApplication {
var haapiUIKitApplication: HaapiUIKitApplication {
guard let appDelegate = delegate as? AppDelegate else {
fatalError("AppDelegate not configured")
}
return appDelegate.haapiUIKitApplication
}
}
Step 5 — Wire Up Deep Links#
In Info.plist, register your redirect URI scheme (app in the example above) under URL Types. Then in AppDelegate:
func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
return HaapiDeepLinkManager.shared.handle(url: url)
}
This lets the framework receive the redirect after an external-browser leg of the flow.
Step 6 — DCR Fallback for Untrusted Devices (Optional)#
When the device doesn’t support hardware-backed key attestation, or when the server rejects the attestation result (older OS versions, certain device states, distribution-channel mismatches), configure DCR fallback in step 2:
let config = HaapiUIKitConfigurationBuilder(
clientId: "my-haapi-client",
baseUrl: URL(string: "https://idsvr.example.com")!,
tokenEndpointUrl: URL(string: "https://idsvr.example.com/oauth/v2/oauth-token")!,
authorizationEndpointUrl: URL(string: "https://idsvr.example.com/oauth/v2/oauth-authorize")!,
appRedirect: "app://haapi"
)
.setClientAuthenticationMethod(method: ClientAuthenticationMethodSecret("dev-secret"))
.setDCRConfiguration(configuration: DCRConfiguration(
templateClientId: "dcr-template-client-haapi-ios",
clientRegistrationEndpointUrl: URL(string: "https://idsvr.example.com/oauth/oauth-registration")!
))
.build()
The server must have a matching template client configured — see DCR for the server-side prerequisites.
Run It#
Build and run. Tap your sign-in button; the framework presents the login screen, walks the user through the authentication flow, and delivers the access token to didReceiveOAuthTokenModel(_:).
Next: Theming to brand the prebuilt screens · Presentation Options to tune modal vs stack and polling cadence · iOS UIKit for the full topic list