API Reference
📚 API Reference​
Reference for the public SDK API and the backend REST contract the SDK expects.
🔒 The
gkas_solutionproduced bybuildSolution()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 tocheckaccessxe. 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
}
| Method | Description |
|---|---|
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 }). TheactivityProvideris used by the biometric tier to host theBiometricPrompt. - 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:
- Validate the
once(exists, not expired, not reused) and consume it. - Decide the attempt flag —
attempt = "0"when the password is correct,"1"otherwise. - Call
checkaccessxe($username, "", $url, $salt, $once, $time, $gkas_solution, $attempt), forwarding thegkas_solutionunchanged. - 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_solutiontocheckaccessxeunchanged viafrontend_data, so no change to the referenceguardiankey.class.phpis needed.