Kotlin (Android) - Integrations - Idura Verify Documentation
  1. Integrations
  2. Kotlin (Android)

Idura provides an Android SDK, which is hosted at https://github.com/criipto/idura-verify-android.

The Idura Verify Android SDK allows your users to authenticate with a host of European eID providers. It allows your application to act as a public client, meaning it does not use a client secret, but instead employs PKCE to ensure that a malicious actor cannot intercept the authorization code.

In addition to the basic OIDC flow, the SDK also supports app switching for the Danish MitID app.

This project is built using Kotlin, and targets Android API Level 29 and up. It builds on top of the AppAuth library, which is maintained by the OpenID foundation. It has been tested on Android versions 10 through 16, using Chrome (both Auth Tab and Custom Tab), Samsung Internet, Brave, and Microsoft Edge browsers.

If the end-user has one of the browsers above installed, the SDK will use that, even if it is not the default browser. If not, the SDK will fall back to the default browser. The SDK can work with other browsers (such as Opera and Firefox). However, the end user will need to manually press "Open in app" after being redirected to the redirect URL.

Installation

Add the following to your build.gradle.kts file:

implementation("eu.idura:verify:1.0.0")

Usage

If you prefer a more interactive approach, there is an example project which your can run and play around with.

Initialization

The SDK needs to be configured with two pieces of information:

  • Your Idura domain.
  • Your Idura client ID.

The SDK assumes that:

  • You will be using your Idura domain to host your redirect URLs (both custom (vanity) domains, and *.idura.id domains can be used).
  • Your redirect URL will be https://[YOUR IDURA DOMAIN]/android/callback.
  • Your app switch URL will be https://[YOUR IDURA DOMAIN]/android/callback/appswitch.

You should register these as callback URLs in the Idura dashboard. To override these values, see the Customization section.

The domain needs to be configured at compile time, since it is used to set up intent filters for your redirect and app switch URLs. You do so by using manifest placeholders

The domain must also be passed when initializing the SDK class. In order to prevent drift between the value stored in your build.gradle.kts file and your code, we recommend adding your domain and client ID as build config fields:

android {
  buildFeatures {
    buildConfig = true
  }

  val iduraClientId = "urn:my:application:identifier:XXXX"
  val iduraDomain = "this-is-an-example.idura.id"

  defaultConfig {
    manifestPlaceholders["iduraDomain"] = iduraDomain
  }
  buildTypes {
    all {
      buildConfigField("String", "IDURA_CLIENT_ID", "\"$iduraClientId\"")
      buildConfigField("String", "IDURA_DOMAIN", "\"$iduraDomain\"")
    }
  }
}

You can then instantiate the SDK like this:

val iduraVerify =
  IduraVerify(
    BuildConfig.IDURA_CLIENT_ID,
    BuildConfig.IDURA_DOMAIN,
    activity = activity,
  )

On top of the client ID and domain, you must also specify an activity. This should be the activity that hosts your login UI. The SDK uses this activity to start the intents, which opens the browser, and shows the login UI to the user. The SDK must be initialized at the same time as the containing activity. That means you should probably do something like this:

class LoginActivity : ComponentActivity() {
  val iduraVerify = IduraVerify(
    BuildConfig.IDURA_CLIENT_ID,
    BuildConfig.IDURA_DOMAIN,
    activity = this,
  )
}

A word about redirect URLs

In order for redirect URLs to work, your app needs to prove that it is authorized to capture the URL. This is done by using App Links. When you use your Idura domain, Idura manages this for you, as long as you configure your package name and the fingerprint of your signing key in the Idura dashboard.

During development, you can get the fingerprint of your local signing key by running ./gradlew signingReport. To get the signing key to use for release, see the Android documentation.

When the SDK is initialized, it will verify that your app is configured to capture the app links. If your app is not correctly configured, you will see a warning like so:

IduraVerify   eu.idura.verifyexample  W   App link is not correctly configured for https://android-sdk.idura.id/my/custom/callback

Logging in

val jwt = iduraVerify.login(DanishMitID.substantial())
println(jwt.subject)

The SDK provides builder classes for some of the eIDs supported by Idura Verify. You should use these when possible, since they provide helper methods for the scopes and login hints supported by the specific eID provider. For example, Danish MitID supports SSN prefilling, which you can access using the prefillSsn method:

val jwt = iduraVerify.login(
  DanishMitID.substantial().prefillSsn("123456-7890").withMessage("Hello there!"),
)

The returned JWT class has properties for some common claims such as subject and identityscheme. For other claims, use the getClaimsAsString, getClaimAsMap etc. functions. For example, if you requested the address scope, you can access the address like so:

val streetAddress = jwt.getClaimAsMap("address")?.get("street_address") as? String

Customization

Using a custom callback domain

In this context, a custom domain means a domain not hosted by Idura. If you have registered a custom (vanity) domain in the Idura dashboard, and pointed it towards idura.id, you do not need to do anything else.

If you want to use another domain, you need to host an assetslinks.json file on the domain, as described in the Android documentation.

Using custom callback URLs

If you want to use different callback and app switch URLs you need to:

  1. Pass these when initializing the SDK:
IduraVerify(
  BuildConfig.IDURA_CLIENT_ID,
  BuildConfig.IDURA_DOMAIN,
  activity = activity,
  redirectUri = "https://${BuildConfig.IDURA_DOMAIN}/my/custom/callback".toUri(),
  appSwitchUri = "https://${BuildConfig.IDURA_DOMAIN}/my/custom/appswitch".toUri(),
)
  1. Update your manifest to capture the new URLs:
<application>
  ...
  <activity
    android:name="eu.idura.verify.RedirectUriReceiverActivity"
    android:exported="true"
    tools:node="replace">
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />

      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />

      <data android:scheme="https" />
      <data android:host="${iduraDomain}" />
      <data android:path="/my/custom/callback" />
    </intent-filter>
  </activity>

  <activity
    android:name="eu.idura.verify.AppSwitchActivity"
    android:exported="true"
    tools:node="replace">
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />

      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />

      <data android:scheme="https" />
      <data android:host="${iduraDomain}" />
      <data android:path="/my/custom/appswitch" />
    </intent-filter>
  </activity>
</application>