Skip to main content

API Reference

📚 API Reference​

Reference for the public SDK API and the backend REST contract the SDK expects.

🔒 The gkas_solution produced by buildSolution() is an opaque token. Its contents and format are intentionally not documented. Your app forwards it to your backend, and your backend forwards it unchanged to checkaccessxe. You never read, build or parse it.


Public API (io.guardiankey.gkas)​

GuardianKeyGkas​

The entry point. Construct it with the factory so the platform identity provider, collectors and HTTP engine are wired in.

class GuardianKeyGkas {
companion object {
fun create(config: GkasSdkConfig, platform: PlatformContext): GuardianKeyGkas
}

suspend fun fetchConfig(): GkasConfig
suspend fun buildSolution(config: GkasConfig, fieldValue: String): String // opaque gkas_solution
suspend fun login(request: LoginRequest): LoginResult
}
MethodDescription
fetchConfig()GET /config. Returns GkasConfig (salt, once, time, url, policy).
buildSolution(config, fieldValue)Collects signals and resolves identity, returns the gkas_solution (opaque Base64 string). fieldValue is the username for this attempt.
login(request)POST /login. Returns a normalized LoginResult.

Configuration & models​

data class GkasSdkConfig(
val backendBaseUrl: String, // REST backend, no trailing slash
val httpTimeoutMs: Long = 8000,
val debug: Boolean = false,
)

@Serializable
data class GkasConfig(
val url: String,
val salt: String,
val once: String, // one-time nonce
val time: String,
val policy: GkasPolicy = GkasPolicy(),
)

@Serializable
data class GkasPolicy(
val tiers: List<String> = listOf("software", "uuid"), // identity cascade
val user_verification: String = "preferred",
)

data class LoginRequest(
val username: String,
val password: String,
val gkasSolution: String, // result of buildSolution() — opaque, forward as-is
val config: GkasConfig, // same GkasConfig returned by fetchConfig()
)

sealed interface LoginResult {
data class Allowed(val raw: String) : LoginResult
data class Blocked(val reason: String?, val raw: String) : LoginResult
data class Error(val message: String) : LoginResult
}

GkasConfig is returned by fetchConfig() and passed straight back into buildSolution() and LoginRequest — you don't construct it yourself. The policy.tiers field is what drives the identity behavior (biometric prompt vs. silent).

PlatformContext​

Platform‑specific bag of dependencies (expect/actual):

  • Android: PlatformContext(context: Context, activityProvider: () -> FragmentActivity? = { null }). The activityProvider is used by the biometric tier to host the BiometricPrompt.
  • iOS: PlatformContext() — empty (stubs).

GkasTouchTracker (Android)​

object the host app feeds raw touch events into:

GkasTouchTracker.feed(event: MotionEvent)   // call from Activity.dispatchTouchEvent

It records only behavioral characteristics of the touches — never the typed content.


Backend contract​

The SDK talks only to your backend. Your backend holds the GuardianKey credentials and calls checkaccessxe server‑side. Two endpoints are required (plus an optional health check).

GET /config​

Generates and persists a one‑time once, and returns the challenge inputs + policy:

{
"url": "https://your-backend.example.com/api/login",
"salt": "demo_salt",
"once": "<nonce>",
"time": "<unix ts>",
"policy": { "tiers": ["biometric","software","uuid"], "user_verification": "preferred" }
}

policy.tiers drives which identity the SDK uses (biometric / software‑only / uuid).

POST /login​

Request body (sent by the SDK):

{
"username": "alice",
"password": "secret",
"gkas_solution": "<opaque token>",
"url": "...", "salt": "...", "once": "...", "time": "..."
}

The backend should:

  1. Validate the once (exists, not expired, not reused) and consume it.
  2. Decide the attempt flag — attempt = "0" when the password is correct, "1" otherwise.
  3. Call checkaccessxe($username, "", $url, $salt, $once, $time, $gkas_solution, $attempt), forwarding the gkas_solution unchanged.
  4. Return a normalized decision:
{
"decision": "ALLOW" | "BLOCK",
"attempt": "0",
"gk_raw": { /* raw checkaccessxe response */ }
}

The SDK maps decision to LoginResult: ALLOW → Allowed, BLOCK → Blocked (carrying an optional reason), anything else / network failure → Error.

GET /health (optional)​

{ "status": "ok" } — smoke test.

The backend forwards gkas_solution to checkaccessxe unchanged via frontend_data, so no change to the reference guardiankey.class.php is needed.