//HAAPI Android UI.Widget Documentation
HAAPI Android UI.Widget Documentation
[androidJvm]
An Android library with classes and layout definitions that are used to perform an Haapi Flow
authorization with Curity Identity ServerHypermedia Authentication API (HAAPI) from Android devices.
The library allows a client to implement an authorization flow via HAAPI by using a set of prebuilt UI screens that represent the different responses/steps that may be involved in the API-driven flow.
Requirements
- The
HAAPI UI.Widget
framework works on Android 8.0+ (API level 26+). - Usage of
HAAPI UI.Widget
requires that your application theme’s parent be any of the framework bundledTheme.Haapi.Ui.Widget.BaseTheme
,Theme.MaterialComponents
or a descendant.
We highly recommend you keep HAAPI UI.Widget
up-to-date.
⚠️ The HAAPI UI.Widget
is not tested on Jetpack Compose
.
Getting started
Setting up HAAPI UI.Widget
To install the SDK, add identityserver.haapi.android.ui.widget
to the dependencies block of your app/build.gradle
file:
apply plugin: 'com.android.application'
android { ... }
dependencies {
implementation("se.curity.identityserver:identityserver.haapi.android.ui.widget:4.1.0")
...
}
Pairing the application with the client on the Curity Identity Server
Get the package name of your application and the API signature of your application.
To get the API signature of your application, run this command in the terminal at the project level:
./gradlew SigningReport
It should produce this result:
> Task :app:signingReport
Variant: debug
Config: debug
...
SHA-256: AC:8A:65:9D:EC:3B:E1:FD:FC:A0:28:87:FA:AB:E0:E0:A5:04:BE:15:7A:2C:05:CB:86:47:FE:9B:E5:7B:D4:1F
Valid until: Wednesday, 7 June 2051
...
Update the client that is the Oauth client with the HAAPI capability using the Android attestation on your Curity Identity Server by adding the following information:
Package Name ->com.example.myhaapiui
(ℹ️ This is an example. Use your own package name.)
Signature Digest ->AC:8A:65:9D:EC:3B:E1:FD:FC:A0:28:87:FA:AB:E0:E0:A5:04:BE:15:7A:2C:05:CB:86:47:FE:9B:E5:7B:D4:1F
(ℹ️ This is an example. Use your own API signature.)
Setting up Digital Asset Links
Associate your app and domain by configuring the Digital Asset Link association in your app Manifest.xml
file by adding an entry like below.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="my.app.package">
...
<application
...
android:name="TestApplication">
<meta-data android:name="asset_statements" android:resource="@string/asset_statements"/>
...
</application>
</manifest>
Next, it is necessary to define the string resource entry referenced in the manifest like the following.
<resources>
<string name="app_name">My App</string>
<!-- Digital Asset Links app association -->
<string name="asset_statements" translatable="false">[{\"include\": \"https://10.0.2.2:8443/.well-known/assetlinks.json\"}]</string>
</resources>
WebAuthn and Passkeys
When the app needs to trigger a WebAuthn Authorization interaction flow, it can do so by either delegating responsibility on the OS by opening a browser or by using an integrated native flow inside the app. The default behaviour has changed and now uses the native integrated WebAuthn support. The configuration has been removed and now the use of the browser is relegated to an alternate fallback action in case the native support fails.
Native WebAuthn support is currently experimental. Use with caution. Provide any relevant feedback about its usage and also if/when finding bugs to help us improve the user and developer experience.
Native WebAuthn support is provided by:
- Google Play Services Fido2 API.
- Credential Manager: A Jetpack credentials API. Supports built-in Platform authenticators (Android 7+ devices) as well as Cross-platform external hardware Security Keys authenticators.
⚠️ Cross-platform Security-Keys with user verification are currently not supported.
Native WebAuthn support for Android is available in Curity Identity Server starting from version 8.7.0.
To use passkeys on Android, you need to meet certain requirements. Passkeys are supported on devices running Android 9 (Pie) or later. Here are the key requirements and details:
- Android Version: Your device must be running Android 9 (Pie) or a newer version.
- Biometric Authentication: You need a biometric sensor, such as a fingerprint or facial recognition, or a PIN, swipe pattern, or password to authenticate and create a passkey.
- Google Account: You must be signed in to a Google Account on your device.
- Credential Manager: Passkeys are managed through the Credential Manager Jetpack library, which handles different credential types including passkeys, passwords, and identity federation.
- Google gms Fido2: Passkeys are managed through the Fido2ApiClient which handles passkeys
- Google Password Manager: Passkeys can be stored in the Google Password Manager, which synchronizes them between devices signed into the same Google account. This allows you to use passkeys across multiple devices.
- Third-party Password Managers: Starting with Android 14, users can opt to store their passkeys in a compatible third-party password manager.
- Website and App Support: The website or app you want to access must support passkey login.
- Nearby Device Authentication: For cross-device login, your phone must be near the device you're logging into, and you must approve the sign-in on your phone.
- PIN or Biometric Authentication: When creating or using a passkey, you'll need to authenticate using a PIN, swipe pattern, or biometric sensor.
Discoverable Credentials support for Android is available in Curity Identity Server starting from version 9.3.0.
Integration
Integrating with the IdsvrHaapi UI framework
to run a Haapi Flow requires minimal code and setup to get your application up and running. This is by design and intended to provide a low code out-of-the-box experience that enables client applications to take advantage of the security features provided by a HyperMedia Authentication API
. Configuring the framework is achieved by implementing the HaapiUIWidgetApplication
which provides the setup that drives the UI behaviour and whose main configuration property is WidgetConfiguration
. For more advanced use cases, some degree of UI customization is also available and can be applied by making use of Theming capabilities from the Android styles and themes.
Start the HAAPI flow
When launching the HaapiFlowActivity
, the HAAPI flow starts, then is driven by the API and finally returns an OauthModel.Token
which contains an OAuth Access Token. The OauthModel.Token
has to be stored and managed in your application.
OAuth Token lifecycle management
Oauth.Token
models follow the specification for OAuth 2.0
tokens, which means their lifecycle can be managed to refresh their validity or revoke and make them invalid/unusable. Haapi UI framework provides a set of APIs that make it possible to manage the lifecycle of held tokens.
DCR configuration for Android devices that do not support Key Attestation
The HAAPI UI.Widget
security features require that Android devices support hardware-backed Key Attestation. Unfortunately, the Android system suffers from ecosystem fragmentation due to the many existing brands/manufacturers, and as such, many of them don't support the security requirements. For those devices, users will not be able to start the HAAPI flow unless the WidgetConfiguration
has a DCR configuration in place. In this case, devices that do not have valid Key Attestation support can automatically fallback to the DCR configuration and continue using Haapi in a secure way.
To configure it, please perform the following steps:
- In your Curity Identity Server, create and configure a client that supports one of the following authentication methods:
-
- Secret
- Mutual TLS
- Signed JWT
- In your Curity Identity Server, create and configure a
DCR template client ID
, and add the client that was created in point 1 to the Dynamic Client Registration section. - In your Curity Identify Server, find (or configure) the DCR client registration endpoint (
oauth-dev-dynamic-client-registration
) and take note as it will be required in the next point. - In your application, update your
WidgetConfiguration
by setting the Client Authentication method and the DCR configuration as the example demonstrates below:
class ClientApplication : Application(), HaapiUIWidgetApplication {
private val baseUri = URI.create("https://10.0.2.2:8443")
override val widgetConfiguration: WidgetConfiguration
get() = WidgetConfiguration.Builder(
clientId = "my-client-id", // It is the client id that is used and was updated above.
baseUri = baseUri,
tokenEndpointUri = baseUri.resolve("/token-endpoint"),
authorizationEndpointUri = baseUri.resolve("/authorization-endpoint"),
appRedirect = "app://haapi"
)
.setClientAuthenticationMethod(
WidgetConfiguration.ClientAuthenticationMethod.Secret("my-secret")
)
.setDcr(
WidgetConfiguration.Dcr(
templateClientId = "dcr-template-client-haapi-android",
clientRegistrationEndpointUri = baseUri.resolve("/oauth-registration"),
context = this
)
)
.build()
}
Configuring HTTPCookie management
To establish and maintain a potentially long-lived session between client and server, HttpURLConnection includes an extensible cookie manager. For more information on setting up cookie management for HttpUrlConnection
please refer to Android API docs. The HAAPI UI.Widget
framework does not handle this automatically as it should be setup at the application level as per use case requirement. To do so, only a couple of lines of code are required to enable the cookie management behaviour like demonstrated below.
// override default behaviour to accept all cookies
CookieHandler.setDefault(CookieManager(null, CookiePolicy.ACCEPT_ALL))
// keep default behaviour to accept only cookies from original server
val cookieManager = CookieManager()
CookieHandler.setDefault(cookieManager)
Guide
Additional features
References
HaapiLogger
When using the HAAPI UI.Widget
it is possible to get information about what is happening during the Haapi Flow
by analyzing the framework logs. This kind of information is intended to help assess issues and troubleshoot the framework behavior and to allow the client developer to gather and provide the necessary data when support is needed. This logging mechanism is built on top of the System Logging in the Android Runtime, more specifically making use of android.util.Log
.
Additional note
If more control over transport/serialization or custom behavior is needed, the HAAPI Android Driver and HAAPI Android SDK can be used as they define lower-level building blocks to issue HAAPI requests.