Saltar al contenido

sdk/android

SDK Kotlin para Android que usa Chrome Custom Tabs, flujo de código de autorización PKCE S256 y almacenamiento de tokens EncryptedSharedPreferences respaldado por Keystore.

Ver como Markdown

Estado

El estado del paquete es Implementado · verificado localmente. Las pruebas unitarias JVM (24 pasadas) cubren la generación PKCE, el estado OAuth y el almacenamiento en memoria. El comportamiento de EncryptedSharedPreferences (Keystore AES-256-GCM), Chrome Custom Tabs y App Links requiere un dispositivo Android real o emulador. La prueba de ida y vuelta real contra un IdP está pendiente de verificación manual. Esta página documenta el comportamiento implementado; no es una declaración de disponibilidad para producción.

Requisitos

  • Android API 26+ (Android 8.0)
  • Kotlin 1.9+ y AndroidX

Instalación

Añade la dependencia al build.gradle.kts del módulo de tu app:

dependencies {
    implementation("dev.xid:xid-android:0.1.0-alpha")
}

// Local development: add to settings.gradle.kts
includeBuild("../sdk/android")

Configuración del manifiesto

Registra una Activity de callback con un intent-filter. Se recomiendan los App Links (esquema HTTPS con autoVerify) sobre los esquemas personalizados:

<!-- AndroidManifest.xml -->
<activity android:name=".AuthCallbackActivity" android:exported="true">
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="https"
              android:host="yourapp.example.com"
              android:pathPrefix="/auth/callback" />
    </intent-filter>
</activity>

Inicio rápido

import dev.xid.sdk.Xid
import dev.xid.sdk.model.XidConfig

// 1. Initialize in Application.onCreate
Xid.configure(
    context = this,
    config = XidConfig(
        issuer = "https://xid.dev",
        clientId = "your_client_id",
        redirectUri = "https://yourapp.example.com/auth/callback",
        scopes = listOf("openid", "profile", "email", "offline_access"),
    )
)

// 2. Sign in (opens Chrome Custom Tabs)
lifecycleScope.launch { Xid.signIn(requireContext()) }

// 3. Handle redirect in AuthCallbackActivity
val session = Xid.handleRedirect(intent.data.toString())

// 4. Get current session (auto-refreshes near expiry)
val session = Xid.getSession()

// 5. Get access token
val token = Xid.getAccessToken()

// 6. Sign out
Xid.signOut(context = this, openEndSession = true)

API principal

Método Firma
configure fun configure(context: Context, config: XidConfig)
signIn suspend fun signIn(context: Context, options: SignInOptions? = null)
handleRedirect suspend fun handleRedirect(url: String): XidSession
getSession suspend fun getSession(): XidSession?
getAccessToken suspend fun getAccessToken(options: GetAccessTokenOptions? = null): String
signOut suspend fun signOut(context: Context? = null, openEndSession: Boolean = false)
setTokenStorage fun setTokenStorage(adapter: TokenStorageAdapter)

Tipos de error

Todos los errores del SDK son subtipos de la clase sellada XidException:

Subclase Disparador
NotConfigured configure() no fue llamado
UserCancelled El usuario cerró Custom Tabs sin completar el flujo
StateMismatch Desfase en el estado OAuth: posible CSRF
TokenExchangeFailed El endpoint de tokens devolvió un error
TokenRefreshFailed Refresh token expirado o revocado
NoSession Método de sesión llamado sin sesión iniciada

Seguridad

  • Cliente público: no se almacena ni transmite ningún secreto de cliente.
  • Solo PKCE S256. El servidor rechaza el método plain de challenge.
  • EncryptedSharedPreferences respaldado por Android Keystore (AES-256-GCM) protege el almacén de tokens en reposo.
  • Estado OAuth aleatorio generado por solicitud; validado en la redirección para prevenir CSRF.

Limitaciones conocidas

  • La verificación de ID token basada en JWKS está implementada y probada localmente. Las pruebas con dispositivo o emulador Android e IdP real siguen siendo necesarias para L4.
  • No hay mecanismo para detectar cuándo el usuario cierra Custom Tabs sin completar la autorización.
  • Solo una cuenta: la capa de almacenamiento usa claves fijas.
Navegación

Escribe para buscar...

Usa las flechas para navegarPulsa Intro para seleccionarPulsa Escape para cerrar