跳到正文

sdk/android

适用于 Android 的 Kotlin SDK,使用 Chrome Custom Tabs、PKCE S256 授权码流程和 Keystore 支持的 EncryptedSharedPreferences token 存储。

状态

包状态为 已实现 · 本地已验证。JVM 单元测试(24 个通过)覆盖 PKCE 生成、OAuth state 和内存存储。EncryptedSharedPreferences(Keystore AES-256-GCM)、Chrome Custom Tabs 和 App Links 行为需要真实 Android 设备或模拟器验证。IdP 往返验证待人工核实。本页面记录已实现的行为,不代表生产就绪声明。

要求

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

安装

在应用模块的 build.gradle.kts 中添加依赖:

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

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

清单配置

注册带 intent-filter 的 callback Activity。生产环境推荐使用 App Links(带 autoVerify 的 HTTPS scheme)而非自定义 scheme:

<!-- 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>

快速开始

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

方式 签名
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)

错误类型

所有 SDK 错误均为 sealed class XidException 的子类型:

子类 触发
NotConfigured configure() 未被调用
UserCancelled 用户在未完成时关闭了 Custom Tabs
StateMismatch OAuth state 不匹配——可能存在 CSRF
TokenExchangeFailed Token 端点返回了错误
TokenRefreshFailed refresh token 已过期或被吊销
NoSession 在已登出状态下调用会话方法

安全

  • 公共客户端——不存储或传输客户端密钥。
  • 仅 PKCE S256。服务器拒绝 plain challenge 方式。
  • 由 Android Keystore(AES-256-GCM)支持的 EncryptedSharedPreferences 保护静态 token 存储。
  • 每次请求生成随机 OAuth state;在重定向时验证以防 CSRF。

已知限制

  • 基于 JWKS 的 ID token 验签已实现并完成本地单元测试。Android 设备或模拟器和真实 IdP 验证前仍不具备 L4 支持。
  • 没有机制检测用户在未完成授权时关闭 Custom Tabs。
  • 仅支持单账户——存储层使用固定密钥。
导航

输入内容以搜索...

使用方向键导航按 Enter 键选择按 Escape 键关闭