Overview Sign in with Suloro API Reference FAQ Open Developer Console

Sign in with Suloro for Android

Official guide for integrating the Suloro Android Auth SDK across Kotlin (ViewBinding & XML), Java (XML), and Jetpack Compose applications. Built on the secure repository dl.suloro.com/android with hardware-attested security.

1. Maven Repository & Dependency Setup

The Suloro Android SDK is hosted at the official Suloro repository https://dl.suloro.com/android. Add the Maven repository to your settings.gradle.kts or settings.gradle.

Step 1: Add Maven Repository in `settings.gradle.kts`

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        mavenCentral()
        // ✨ Official Suloro Maven Repository
        maven {
            url = uri("https://dl.suloro.com/android")
        }
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        mavenCentral()
        // ✨ Official Suloro Maven Repository
        maven { url 'https://dl.suloro.com/android' }
    }
}

Step 2: Add Dependency in `app/build.gradle.kts`

dependencies {
    // Official Suloro Auth SDK
    implementation("com.suloro.android:auth:1.1.3")

    // AndroidX Core & AppCompat
    implementation("androidx.core:core-ktx:1.12.0")
    implementation("androidx.appcompat:appcompat:1.6.1")
    implementation("androidx.activity:activity-ktx:1.8.2")
}
dependencies {
    // Official Suloro Auth SDK
    implementation 'com.suloro.android:auth:1.1.3'

    implementation 'androidx.core:core-ktx:1.12.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.activity:activity-ktx:1.8.2'
}

Click "Sync Now" in Android Studio to download the SDK.

2. SDK Initialization (`SuloroAuth.init`)

Initialize the SDK in your custom Application class or inside MainActivity.onCreate():

App.kt (Application Class)
package com.example.myapp

import android.app.Application
import com.suloro.auth.SuloroAuth
import com.suloro.auth.SuloroAuthConfig

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        // ✨ Suloro Configuration
        val config = SuloroAuthConfig(
            clientId = "YOUR_ANDROID_CLIENT_ID",
            // ⚡ Instant-Launch Preloader Option:
            // When true, SuloroAuth.init() eagerly pre-loads the login page in the background.
            // When the user taps "Sign in", the modal opens instantly with 0ms perceived delay!
            // Recommended if your app is not memory-heavy.
            loadInStart = true // default is false (on-demand loading)
        )

        SuloroAuth.init(config)
    }
}
Performance Tip: When to use `loadInStart = true`

When your app is standard / lightweight: Set loadInStart = true. The SDK creates an invisible background WebView during app initialization and pre-renders the Suloro authentication portal. When the user taps the login button, the preloaded view appears instantly, delivering a perceived 0ms startup time.

When your app is memory-heavy: Keep loadInStart = false (the default). The login WebView will only be instantiated on-demand when SuloroAuth.getInstance().signIn() is called, conserving system memory during app startup.

3. Kotlin (XML Layouts & ViewBinding)

To implement Sign in with Suloro in a traditional Kotlin Activity using XML layouts:

XML Layout (`res/layout/activity_login.xml`)

activity_login.xml
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="24dp">

    <Button
        android:id="@+id/btn_suloro_login"
        android:layout_width="match_parent"
        android:layout_height="52dp"
        android:text="Sign in with Suloro"
        android:backgroundTint="#2563EB"
        android:textColor="#FFFFFF"
        android:textAllCaps="false"
        android:textSize="16sp" />

</LinearLayout>

Kotlin Activity (`LoginActivity.kt`)

LoginActivity.kt
package com.example.myapp

import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.suloro.auth.SuloroAuth
import com.suloro.auth.SuloroAuthCallback
import com.suloro.auth.SuloroAuthError
import com.suloro.auth.SuloroUser

class LoginActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)

        findViewById<Button>(R.id.btn_suloro_login).setOnClickListener {
            startSuloroLogin()
        }
    }

    private fun startSuloroLogin() {
        SuloroAuth.getInstance().signIn(this, object : SuloroAuthCallback {
            override fun onSuccess(user: SuloroUser) {
                Log.d("SuloroAuth", "Login Success: ${user.name} (${user.email})")
                Toast.makeText(this@LoginActivity, "Welcome ${user.name}!", Toast.LENGTH_SHORT).show()
                // Navigate to Main Dashboard
            }

            override fun onError(error: SuloroAuthError) {
                Log.e("SuloroAuth", "Sign-in Failed [${error.code}]: ${error.message}")
                Toast.makeText(this@LoginActivity, error.message, Toast.LENGTH_LONG).show()
            }
        })
    }
}

4. Java & XML Implementation

For applications written in pure Java:

LoginActivity.java
package com.example.myapp;

import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.suloro.auth.SuloroAuth;
import com.suloro.auth.SuloroAuthCallback;
import com.suloro.auth.SuloroAuthError;
import com.suloro.auth.SuloroUser;

public class LoginActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        Button btnLogin = findViewById(R.id.btn_suloro_login);
        btnLogin.setOnClickListener(v -> startSuloroLogin());
    }

    private void startSuloroLogin() {
        SuloroAuth.getInstance().signIn(this, new SuloroAuthCallback() {
            @Override
            public void onSuccess(SuloroUser user) {
                Log.d("SuloroAuth", "Login Success: " + user.getName() + " (" + user.getEmail() + ")");
                Toast.makeText(LoginActivity.this, "Welcome " + user.getName(), Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onError(SuloroAuthError error) {
                Log.e("SuloroAuth", "Login error: " + error.getMessage());
                Toast.makeText(LoginActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }
}

5. Jetpack Compose UI Integration

If your Android app is built with Jetpack Compose, use rememberLauncherForActivityResult with SuloroAuthContract:

LoginScreen.kt (Jetpack Compose)
package com.example.myapp.ui

import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.suloro.auth.*

@Composable
fun LoginScreen(onLoginSuccess: (SuloroUser) -> Unit) {
    val context = LocalContext.current

    // Modern ActivityResult Launcher
    val suloroAuthLauncher = rememberLauncherForActivityResult(
        contract = SuloroAuthContract()
    ) { result ->
        when (result) {
            is SuloroAuthResult.Success -> {
                onLoginSuccess(result.user)
            }
            is SuloroAuthResult.Error -> {
                Toast.makeText(context, result.error.message, Toast.LENGTH_LONG).show()
            }
            is SuloroAuthResult.Cancelled -> {
                // Flow was dismissed by user
            }
        }
    }

    Box(
        modifier = Modifier.fillMaxSize().padding(24.dp),
        contentAlignment = Alignment.Center
    ) {
        Button(
            onClick = {
                suloroAuthLauncher.launch(
                    SuloroAuthConfig(clientId = "YOUR_ANDROID_CLIENT_ID")
                )
            },
            modifier = Modifier.fillMaxWidth().height(52.dp),
            shape = RoundedCornerShape(26.dp),
            colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF2563EB))
        ) {
            Text("Sign in with Suloro", color = Color.White)
        }
    }
}

6. Modern Activity Result Contract (`SuloroAuthContract`)

For type-safe Activity Result handling in standard activities:

SuloroAuthContract Implementation
class MainActivity : AppCompatActivity() {

    private val suloroAuthLauncher = registerForActivityResult(SuloroAuthContract()) { result ->
        when (result) {
            is SuloroAuthResult.Success -> {
                val user = result.user
                Log.d("SuloroAuth", "Welcome ${user.name} (${user.email}), Gender: ${user.gender}")
            }
            is SuloroAuthResult.Error -> {
                Log.e("SuloroAuth", "Error [${result.error.code}]: ${result.error.message}")
            }
            is SuloroAuthResult.Cancelled -> {
                Log.d("SuloroAuth", "User cancelled authentication flow.")
            }
        }
    }

    fun launchLogin() {
        val config = SuloroAuthConfig(
            clientId = "YOUR_ANDROID_CLIENT_ID"
        )
        suloroAuthLauncher.launch(config)
    }
}

7. Silent Session Check (`SuloroAuth.checkSession`)

Check whether the user is already authenticated without interrupting the user or opening any UI dialogs:

Silent Session Check
fun checkUserSession() {
    SuloroAuth.getInstance().checkSession(
        context = this,
        callback = object : SuloroSessionCallback {
            override fun onAuthenticated(user: SuloroUser) {
                Log.d("SuloroAuth", "Session active: ${user.email}")
                // Route to App Home Screen
            }

            override fun onUnauthenticated() {
                Log.d("SuloroAuth", "No active session, show Login Screen")
            }

            override fun onError(error: SuloroAuthError) {
                Log.e("SuloroAuth", "Session check error: ${error.message}")
            }
        },
        forceNetworkCheck = false // false = 0ms hardware Keystore cache (instant startup)
    )
}
Mode forceNetworkCheck Latency Description
Local Cache (Recommended) false ~0ms Evaluates encrypted on-device session credentials from AndroidKeyStore AES-GCM storage. Returns immediately without network round-trips.
Live Server Validation true ~200-400ms Dispatches headless check via SuloroSilentSessionChecker with Play Integrity token to accounts.suloro.com/signin?action=check_session to confirm real-time account suspension/revocation status.

8. Sign Out (`SuloroAuth.signOut`)

Sign Out
fun logoutUser() {
    SuloroAuth.getInstance().signOut(this) {
        Log.d("SuloroAuth", "Successfully signed out.")
        // Navigate back to Login Screen
    }
}

9. SHA-256 Certificate Fingerprints & Hardware Attestation

Suloro OAuth enforces hardware-level attestation and certificate fingerprint verification for Android applications:

1

Obtain Your App SHA-256 Fingerprint

Run the signing report task in Android Studio:

Gradle Terminal
./gradlew signingReport

Or extract it with keytool:

Terminal
keytool -list -v -keystore your_release.keystore -alias your_alias
2

Register Package Name & SHA-256 in Developer Console

In the Developer Console, add your Android Package Name (e.g. com.example.myapp) and paste the SHA-256 fingerprint.

3

Hardware-Attested Fail-Closed Security

When an Android app launches sign-in, the SDK acquires a hardware-backed attestation token and verifies it against the Suloro Attestation Engine. If an APK is resigned, modified, or run on an untrusted device without matching fingerprints, authentication fails closed immediately.

10. ProGuard / R8 Rules (`consumer-rules.pro`)

proguard-rules.pro
# Keep all public classes, methods & callbacks in Suloro Auth
-keep public class com.suloro.auth.** {
    public *;
}

# Keep Serializable & Data Classes (SuloroUser, SuloroAuthConfig, SuloroAuthError)
-keepclassmembers class com.suloro.auth.** implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
    !static !transient <fields>;
}

# Keep internal authentication activity
-keep class com.suloro.auth.SuloroAuthActivity { *; }

# Suppress harmless warnings
-dontwarn com.suloro.auth.**
-dontwarn javax.crypto.**
-dontwarn android.security.keystore.**

11. Android Error Codes & Troubleshooting

Error Code Description Fix
UNTRUSTED_CLIENT Invalid or unregistered Android Client ID. Confirm Android Client ID in Developer Console.
ATTESTATION_FAILED App certificate SHA-256 fingerprint does not match registered list. Register both Debug and Release SHA-256 fingerprints in Console.
CROSS_PLATFORM_MISMATCH A Web Client ID was initialized in the Android SDK. Use the Android application Client ID.
USER_CANCELLED User dismissed the authentication sheet via back navigation. No action needed; allow user to retry.