/images/resources/code-examples/code-examples-kotlin-haapi.jpg

Kotlin Android App using HAAPI

On this page

This tutorial summarizes the behavior of a Kotlin app that implements OAuth 2.0 and OpenID Connect using the Hypermedia Authentication API (HAAPI). The flow is API-driven and enables a pure native login user experience, after which the app receives a correct access token with which to call APIs.

Overview

The code example provides a basic Android implementation that runs a HAAPI authentication flow. The app uses the HAAPI UI SDK to handle the authentication flow with a low-code solution. The app initially presents a view to start the authentication process.

Initial View

The authentication workflow then runs as a series of fast API requests that return JSON responses. The SDK processes each API response to perform various actions including rendering of forms. The following screenshot shows the login experience with native passkeys:

Passkeys Login

Once authentication completes, the app presents its Authenticated View, to simulate a mobile app that works with access tokens to call APIs. The app can then easily perform other OAuth operations such as refreshing tokens and ending the authenticated session.

Authenticated View

Quick Start

First, clone the GitHub repository at the top of this page and open it in an up-to-date version of Android Studio. The repository includes a Docker deployment of the Curity Identity Server, to provide backend Hypermedia Authentication API endpoints. See the README file for instructions on how to run the deployment. The deployed system includes an Admin UI which you can connect to with the following details.

PropertyValue
URLhttps://localhost:6749/admin
Useradmin
PasswordPassword1

The quick start enables you to run a HAAPI flow with a test account and either of the following login methods:

  • The HTML form authenticator, with a pre-shipped username of demouser and a password of Password1.
  • The passkeys authenticator, with the pre-shipped user account named demouser.

Application Configuration

The code example uses the following client settings, including the haapi and code capabilities. For further details on HAAPI specific settings refer to the Android HAAPI Client Setup tutorial. Include the issue-token-bound-authorization-code setting if using version 9.0 or later of the Curity Identity Server.

xml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
<config xmlns="http://tail-f.com/ns/config/1.0">
<profiles xmlns="https://curity.se/ns/conf/base">
<profile>
<id>token-service</id>
<type xmlns:as="https://curity.se/ns/conf/profile/oauth">as:oauth-service</type>
<settings>
<authorization-server xmlns="https://curity.se/ns/conf/profile/oauth">
<client-store>
<config-backed>
<client>
<id>haapi-android-client</id>
<client-name>Haapi Android Client</client-name>
<no-authentication>true</no-authentication>
<redirect-uris>app://haapi</redirect-uris>
<proof-key>
<require-proof-key>false</require-proof-key>
</proof-key>
<refresh-token-ttl>3600</refresh-token-ttl>
<scope>address</scope>
<scope>email</scope>
<scope>openid</scope>
<scope>phone</scope>
<scope>profile</scope>
<capabilities>
<code>
</code>
<haapi>
<issue-token-bound-authorization-code>true</issue-token-bound-authorization-code>
</haapi>
</capabilities>
<validate-port-on-loopback-interfaces>true</validate-port-on-loopback-interfaces>
<attestation>
<disable-attestation-validation>true</disable-attestation-validation>
<android>
<package-name>io.curity.haapidemo</package-name>
<signature-digest>Z2DKEZO2XWFWQnApoRCzhqhIxzODe7BUsArj4Up9oKQ=</signature-digest>
<signature-digest>QqGGZJ4Kzv75J1MyPtG2WA59Z1ezNIshN1o1Ayh7qU4=</signature-digest>
<android-policy>android-dev-policy</android-policy>
</android>
</attestation>
</client>
</config-backed>
</client-store>
</authorization-server>
</settings>
</profile>
</profiles>
</config>

The demo app uses configuration settings from its Configuration object. When running the quick start, the configuration gets updated with working values. To run against a different instance of the Curity Identity Server, update the configuration details to match those of the deployed system.

kotlin
1234567891011
fun newInstance(): Configuration =
Configuration(
clientId = "haapi-android-client",
baseURLString = "https://10.0.2.2:8443",
tokenEndpointPath = "/oauth/v2/oauth-token",
authorizationEndpointPath = "/oauth/v2/oauth-authorize",
userInfoEndpointPath = "/oauth/v2/oauth-userinfo",
redirectURI = "haapi://callback",
scope = listOf("openid", "profile"),
useSSL = true
)

HAAPI UI SDK Integration

To understand how the app integrates the HAAPI UI SDK, see the Android integration guide. In the application code, study the following main integration points:

  1. The app/build.gradle file references the HAAPI UI SDK as a dependency.
  2. The DemoApplication object implements an SDK interface to configure the app.
  3. The AndroidManifest.xml file declares the SDK's HAAPIFlowActivity that presents the login user interface.
  4. The MainActivity is the unauthenticated view, which triggers a HAAPI login and receives a token response.
  5. The AuthenticatedActivity then runs and works with OAuth tokens.

After a HAAPI flow authenticates the user, the mobile client adds access tokens to the HTTP Authorization header when it calls APIs. When the access token expires, the refreshAccessToken method of the HaapiFlowViewModel class is used to get a new set of tokens. Have a look at the TokensViewModel and TokensFragment cobjects to see how to obtain the view model and use it to refresh tokens.

To implement logout, the app discards its tokens and moves back to the MainActivity, to return to an unauthenticated state. Have a look at the TokensViewModel and TokensFragment objects to understand the details.

Application Customization

The UI SDK allows you to customize the look and feel of login screens. Have a look at the res/values/styles.xml and res/values/colors.xml files to see the techniques used in the demo app to change the default theme. Note that the custom theme is applied to the HAAPIFlowActivity in the AndroidManifest.xml file.

The app also makes some more complex modifications that the Advanced Login Customization tutorial explains. The app makes minor changes to its HTML login screen, to replace the Login title with a header banner and to remove the Forgot Username link. The app also completely replaces the authentication selection screen, to show the passkeys option first, and to represent each authenticator as descriptive text followed by a themed button.

Custom HTML Form Login
Custom Authentication Selector

Non-Compliant Devices

The HAAPI SDK uses hardware-backed attestation features to perform secure client authentication. Some older Android devices may not support the recommended method for client attestation. In these cases use a fallback method of proving the client identity before authentication. Have a look at the Implementing HAAPI Fallback tutorial to learn more.

Model SDK Code Example

HAAPI SDKs

This section is only relevant if you are using the older model SDK and want to run the model SDK code example. All new HAAPI secured mobile apps should instead integrate the UI SDK.

The UI SDK is implemented using the lower level Android Model SDK, which uses raw API responses. The Android HAAPI Model SDK Code Example demonstrates an alternative approach, where the model SDK is used directly, but considerably more plumbing code is needed.

To deploy working HAAPI backend endpoints, follow the README instructions and then run the app from Android Studio. First, locate the OAuth configuration settings in the Configuration.kt module and update them if required.

kotlin
12345678910111213
Configuration(
name = name,
clientId = "haapi-android-client",
baseURLString = "https://10.0.2.2:8443",
tokenEndpointURI = "https://10.0.2.2:8443/oauth/v2/oauth-token",
authorizationEndpointURI = "https://10.0.2.2:8443/oauth/v2/oauth-authorize",
userInfoEndpointURI = "https://10.0.2.2:8443/oauth/v2/oauth-userinfo",
metaDataBaseURLString = "https://10.0.2.2:8443/oauth/v2/oauth-anonymous",
redirectURI = "app://haapi",
followRedirect = true,
isSSLTrustVerificationEnabled = false,
selectedScopes = listOf("openid", "profile")
)

Study the code example's main classes to understand the logic. The DemoApplication object creates a HaapiAccessor factory class, which instantiates a HaapiManager. A FlowActivity provides the user interface for login screens. A HaapiFlowViewModel starts the flow and processes each API response until authentication completes. The following snippet shows the start and end of the authentication flow.

kotlin
123456789101112131415
private fun startHaapi() {
executeHaapi {
haapiAccessor.haapiManager.start()
}
}
private fun processHaapiResult(haapiResult: HaapiResult) {
if (haapiResult is OAuthAuthorizationResponseStep) {
fetchAccessToken(latestResponse)
}
...
}

Conclusion

The Hypermedia Authentication API provides a number of benefits to mobile apps, in terms of hardened security and login usability.

  • Users of the app get a pure native login user experience.
  • You can customize login screens without depending on a central identity team.
  • There is hardened security to prevent impersonation threats and to protect refresh tokens.
  • The Curity Identity Server and the HAAPI UI SDK deal with the security, to enable low code integration.
Newsletter

Join our Newsletter

Get the latest on identity management, API Security and authentication straight to your inbox.

Newsletter

Start Free Trial

Try the Curity Identity Server for Free. Get up and running in 10 minutes.

Start Free Trial

Was this helpful?