Abrova
☰ Docs menu · Android SDK

Android SDK

Abrova Auth for Android (ir.abrova:abrova-auth, Kotlin). Anonymous, Google (Credential Manager), Apple, e-mail and password, magic link and Telegram sign-in with coroutines; refresh token encrypted with an Android Keystore key; token providers for every Abrova SDK.

Android 0.1.1Android API 23+Last updated: 27 Oct 2026
Client-Safe

Uses the public API key only. Safe to ship in an app

Coroutines

Every call is a suspend function

Keystore

Refresh token encrypted with a key that never leaves the Android Keystore

Token Providers

Suspend, strict and blocking providers for the other Abrova SDKs

StateFlow

authState for Compose and coroutines, or a classic listener

Upgrade Guests

linkApple, linkGoogle, linkPassword keep the user id

Abrova Auth Android SDK v0.1.1.

This page describes ir.abrova:abrova-auth 0.1.1.

Requirements.

Android API 23 (Android 6.0) or higher. Kotlin coroutines.

Using an AI assistant? Give it this page with Copy page for AI, or all the docs as plain text from /docs/llms.txt. See AI assistants.

Installation#

The SDK comes from Abrova Center. First add the Abrova Maven repository in settings.gradle.kts:

settings.gradle.ktsKotlin
dependencyResolutionManagement {
  repositories {
      google()
      mavenCentral()
      maven { url = uri("https://center.abrova.ir/api/packages/abrova/maven") }
  }
}

Then add the dependency in your app's build.gradle.kts:

kotlin
dependencies {
    implementation("ir.abrova:abrova-auth:0.1.1")
}

In Abrova Console, turn on Abrova Auth for your project (Settings › Products) and the sign-in methods you want (Abrova Auth › Sign-in methods).

Initialization#

Configure the SDK once, in Application.onCreate, with your public API key (ab_live_...). A session saved by an earlier launch is restored.

kotlin
import ir.abrova.auth.AbrovaAuth

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        AbrovaAuth.shared.configure(this, "ab_live_your_api_key")
    }
}

All sign-in calls are suspend functions: call them from a coroutine (for example lifecycleScope.launch { ... }).

Sign in#

kotlin
val auth = AbrovaAuth.shared

val methods = auth.getMethods()
if (auth.currentUserId == null && methods.isEnabled("anonymous")) {
    auth.signInAnonymously()
}
Log.d("Auth", auth.currentUserId!!) // ru_...

Show only the buttons for methods where methods.isEnabled(...) is true: anonymous, apple, google, password, magicLink, telegram.

Use the user with other Abrova SDKs#

Coming soon. Abrova Sync, Chat, Push, Storage and A/B Testing are coming soon. The calls below show how they will take the Auth user; today, attach the user to Abrova Trace with AbrovaTrace.setUserId(auth.currentUserId).
kotlin
// Abrova Sync: its provider is called off the main thread
AbrovaSyncConfig.builder(apiKey).userTokenProvider(auth.blockingTokenProvider).build()

// Abrova Push
AbrovaPushConfig(apiKey = apiKey, tokenProvider = auth.tokenProvider)

// Abrova Chat: create the client after sign-in
AbrovaChatConfig(apiKey = apiKey, userId = auth.currentUserId!!, tokenProvider = auth.strictTokenProvider)
ProviderTypeWhen nobody is signed in
tokenProvidersuspend () -> String?Returns null
strictTokenProvidersuspend () -> StringThrows NOT_SIGNED_IN
blockingTokenProvider() -> String?Returns null. Blocks the calling thread: never call it on the main thread

All return a token that is renewed before it expires. After a sign-in or sign-out, call the other SDK's refresh method (for example sync.userTokens.refresh()). Abrova A/B Testing and more: Use with other Abrova products.

Sign-in methods#

Each method has its own page with the Console setup: Anonymous, Apple, Google, E-mail & password, Magic link, Telegram.

Sign in with Google

Use Credential Manager with your web client ID and a hashed nonce. Add androidx.credentials:credentials, androidx.credentials:credentials-play-services-auth and com.google.android.libraries.identity.googleid:googleid to your app:

kotlin
val rawNonce = AbrovaNonce.generate()
val option = GetGoogleIdOption.Builder()
    .setServerClientId(WEB_CLIENT_ID)
    .setFilterByAuthorizedAccounts(false)
    .setNonce(AbrovaNonce.sha256(rawNonce))
    .build()
val response = CredentialManager.create(context)
    .getCredential(context, GetCredentialRequest.Builder().addCredentialOption(option).build())
val idToken = GoogleIdTokenCredential.createFrom(response.credential.data).idToken

auth.signInWithGoogle(idToken, rawNonce)

Add the web client ID under Abrova Auth › Sign-in methods › Google.

Google sign-in needs a connection to Google, and on Android also Google Play services; some users in Iran have neither. Anonymous, e-mail and password, magic link and Telegram code work without Google, so offer at least one of them as well. See Sign in with Google.

Sign in with Apple

Run Apple's web sign-in with your Services ID and AbrovaNonce.sha256(rawNonce) as the nonce, then pass the id_token and code Apple returns:

kotlin
auth.signInWithApple(idToken, rawNonce, authorizationCode = code)

E-mail and password

kotlin
val result = auth.signUp(email, password, redirectUrl = "https://example.com/auth/verify")
// result.signedIn is false when the project requires a verified e-mail first.

auth.signIn(email, password)

auth.sendPasswordReset(email, redirectUrl = "https://example.com/auth/reset")
auth.resetPassword(token, newPassword) // ends every session; does not sign in
auth.verifyEmail(token)
auth.sendEmailVerification(redirectUrl = "https://example.com/auth/verify")

Magic link

kotlin
auth.sendMagicLink(email, redirectUrl = "myapp://auth/magic")
// In the activity the link opens:
AbrovaAuth.tokenFromLink(intent.dataString ?: "")?.let { auth.signInWithMagicLink(it) }

Telegram

kotlin
val code = auth.requestTelegramCode("+989121234567")
if (!code.sent) startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(code.botUrl)))
auth.verifyTelegramCode("+989121234567", "123456")

Upgrade an anonymous user#

Linking keeps the user id, so everything they created stays theirs:

kotlin
try {
    auth.linkGoogle(idToken, rawNonce)   // or linkApple(...), linkPassword(email, password)
} catch (e: AbrovaAuthException) {
    if (e.code == AbrovaAuthErrorCode.PROVIDER_ALREADY_LINKED) {
        // This Google account already belongs to another user.
    }
}

The current user#

kotlin
auth.currentUserId                 // null when signed out
auth.isSignedIn
val user = auth.me()               // AbrovaUser: id, isAnonymous, emailVerified, createdAt, providers
auth.currentUser                   // the profile last loaded by me()

// StateFlow of the user id
lifecycleScope.launch { auth.authState.collect { userId -> /* sign-in, sign-out, session end */ } }

// Or a listener
val registration = auth.addAuthStateListener { userId -> }
registration.remove()

val token = auth.getAccessToken()  // if you call your own API with it

Sign out and delete the account#

kotlin
auth.signOut()            // this device; never fails
auth.signOutEverywhere()  // every device
auth.deleteAccount()      // deletes the user, then signs out

See Security & data for what deletion removes.

Handle errors#

Every error is an AbrovaAuthException. Branch on code:

kotlin
try {
    auth.signIn(email, password)
} catch (e: AbrovaAuthException) {
    when (e.code) {
        AbrovaAuthErrorCode.INVALID_CREDENTIALS -> showError("Wrong e-mail or password")
        AbrovaAuthErrorCode.RATE_LIMITED -> showError("Try again in ${e.retryAfterSec ?: 60} s")
        AbrovaAuthErrorCode.NETWORK_ERROR -> showError("No connection")
        else -> showError("Sign-in failed")
    }
}

message is an English hint for developers. Besides the server's codes the SDK uses NETWORK_ERROR, NOT_SIGNED_IN and SDK_NOT_CONFIGURED (call configure first). A network error never signs the user out. All codes: Error codes.

Troubleshooting#

SDK_NOT_CONFIGURED

Call AbrovaAuth.shared.configure(context, apiKey) in Application.onCreate.

Google sign-in fails with INVALID_ID_TOKEN

Credential Manager issues the ID token to the web client ID you pass as serverClientId. Add that web client ID in the Console, and pass AbrovaNonce.sha256(rawNonce) as the nonce.

The app freezes when Sync asks for a token

blockingTokenProvider blocks its thread. Give it only to SDKs that call it off the main thread, and never call it yourself on the main thread.

Was this page helpful?
Report a problem