The latest source code of the Keyri Android SDK can be found here: https://github.com/Keyri-Co/keyri-android-whitelabel-sdk/releases

System Requirements

  • Android API level 23 or higher
  • AndroidX compatibility
  • Kotlin coroutines compatibility

Note: Your app does not have to be written in Kotlin to integrate this SDK, but it must be able to depend on Kotlin functionality.


  • Add the JitPack repository to your root build.gradle file:
  • Add SDK dependency to your build.gradle file and sync project:

To handle Android App Links (e.g., for QR login straight from the user's built-in camera app) you need to define the following intent-filter block in your AndroidManifest.xml:


This will handle all links with the following scheme: https://{yourCompany}.onekey.to?sessionId={sessionId}

Note: Keyri will create your https://{yourCompany}.onekey.to page automatically once you configure it in the dashboard

In the activity where the processing of links is declared, you need to add handlers in the onNewIntent() and onCreate() methods:


Note: Keyri will set up the required /.well-known/assetlinks.json JSON at your https://{yourSubdomain}.onekey.to page as required by Android App Links handling. Details on this mechanism are described here: https://developer.android.com/training/app-links/verify-site-associations

Option 2 - In-App Scanner

Use AuthWithScannerActivity built-in functionality to delegate authentication to SDK. You can use ActivityResult API or onActivityResult. Create Intent for AuthWithScannerActivity and pass App Key with AuthWithScannerActivity.APP_KEY, optional public user ID with AuthWithScannerActivity.PUBLIC_USER_ID and payload with AuthWithScannerActivity.PAYLOAD :


Or define custom scanner UI/UX. You can use Firebase ML Kit, ZXing, your own scanner, or any other equivalent. All you need to do is convert to URI, and then you're free to process the response the same way we did above (notice the process(uri) function is exactly the same in both cases)


Interacting with the API

The following methods are available to interact with the Keyri SDK API, which can be used to craft your own custom flows and leverage the SDK in different ways:

  • suspend fun initializeQrSession(appKey: String, sessionId: String, payload: String, publicUserId: String?): Result<Session> - call it after obtaining the sessionId from QR code or deep link. Returns Session object with Risk attributes (needed to show confirmation screen) or Exception
  • suspend fun initializeDefaultScreen(fm: FragmentManager, session: Session): Boolean - to show Confirmation with default UI. Returns Boolean result. Also you can implement your custom Confirmation Screen, just inherit from BaseConfirmationDialog.kt
  • suspend fun Session.confirm(): Result - call this function if user confirmed the dialog. Returns Boolean authentication result
  • suspend fun Session.deny(): Result<Boolean> - call if the user denied the dialog. Returns Boolean authentication result
  • fun generateAssociationKey(publicUserId: String): String - creates a persistent ECDSA keypair for the given public user ID (example: email address) and return public key
  • fun getUserSignature(publicUserId: String?, customSignedData: String?): String - returns an ECDSA signature of the timestamp and optional customSignedData with the publicUserId's privateKey (or, if not provided, anonymous privateKey), customSignedData can be anything
  • fun listAssociationKey(): List<String> - returns a list of names (publicUserIds) of "association keys" (public keys)
  • fun getAssociationKey(publicUserId: String): String - returns Base64 public key for the specified publicUserId

Payload can be anything (session token or a stringified JSON containing multiple items. Can include things like publicUserId, timestamp, customSignedData and ECDSA signature)

Session Object

The session object is returned on successful initializeQrSession calls, and is used to handle presenting the situation to the end user and getting their confirmation to complete authentication. Below are some of the key properties and methods that can be triggered. If you are utilizing the built-in views, you are only responsible for calling the confirm/deny methods above

  • IPAddressMobile/Widget - The IP Address of both mobile device and web browser
  • RiskAnalytics - if applicable
    • RiskStatus - clear, warn or deny
    • RiskFlagString - if RiskStatus is warn or deny, this string alerts the user to what is triggering the risk situation
    • GeoData - Location data for both mobile and widget
      • Mobile
        • city
        • country_code
      • Browser
        • city
        • country_code
  • Session.confirm() and Session.deny() - see descriptions in Interacting with the API.


We care deeply about the quality of our product and rigorously test every piece of functionality we offer. That said, every integration is different. Every app on the App Store has a different permutation of build settings, compiler flags, processor requirements, compatibility issues etc and it's impossible for us to cover all of those bases, so we strongly recommend thorough testing of your integration before shipping to production. Please feel free to file a bug or issue if you notice anything that seems wrong or strange on GitHub 🙂

Updated 09 Jun 2022
Did this page help?