Skip to content

Mobile SDKs (preview)

Preview

Native iOS/Android SDKs are scheduled for a future release. The flow below — system browser + PKCE — works today and is the recommended pattern.

Native LXL SDKs (spec, in development)

The native SDK packages are spec-locked and live in their own repos. The public surface is stable; the network-bound method bodies throw notImplemented until v0.2.

Platform Package Repo
iOS (Swift Package, iOS 15+) LXLId littlexlittle/id-mobile-ios
Android (AAR, minSdk 24) org.littlexlittle:id littlexlittle/id-mobile-android

Until those publish, use the AppAuth-based recipe below — it works against the same discovery document and produces interoperable tokens.

iOS (Swift) — using ASWebAuthenticationSession

```swift import AuthenticationServices

let verifier = PKCE.generateVerifier() let challenge = PKCE.codeChallenge(for: verifier)

var components = URLComponents(string: "https://id.littlexlittle.org/oidc/authorize")! components.queryItems = [ URLQueryItem(name: "response_type", value: "code"), URLQueryItem(name: "client_id", value: clientId), URLQueryItem(name: "redirect_uri", value: "com.yourorg.app://oauth/callback"), URLQueryItem(name: "scope", value: "openid profile email lxl.access"), URLQueryItem(name: "state", value: state), URLQueryItem(name: "nonce", value: nonce), URLQueryItem(name: "code_challenge", value: challenge), URLQueryItem(name: "code_challenge_method", value: "S256"), ]

let session = ASWebAuthenticationSession( url: components.url!, callbackURLScheme: "com.yourorg.app" ) { callbackURL, error in guard let url = callbackURL, let code = URLComponents(url: url, resolvingAgainstBaseURL: false)? .queryItems?.first(where: { $0.name == "code" })?.value else { return } exchangeCode(code, verifier: verifier) } session.prefersEphemeralWebBrowserSession = false session.presentationContextProvider = self session.start() ```

Android (Kotlin) — using Custom Tabs + AppAuth pattern

```kotlin val verifier = generateCodeVerifier() val challenge = generateCodeChallenge(verifier)

val authUri = Uri.parse("https://id.littlexlittle.org/oidc/authorize").buildUpon() .appendQueryParameter("response_type", "code") .appendQueryParameter("client_id", clientId) .appendQueryParameter("redirect_uri", "com.yourorg.app://oauth/callback") .appendQueryParameter("scope", "openid profile email lxl.access") .appendQueryParameter("state", state) .appendQueryParameter("nonce", nonce) .appendQueryParameter("code_challenge", challenge) .appendQueryParameter("code_challenge_method", "S256") .build()

CustomTabsIntent.Builder().build().launchUrl(this, authUri) ```

Handle the com.yourorg.app://oauth/callback deep link in your AndroidManifest.xml and exchange the code for tokens against /oidc/token.

Redirect URI conventions

Platform Scheme
iOS / Android Reverse-DNS app scheme: com.yourorg.app://oauth/callback
Universal Links / App Links https://yoursite.org/oauth/callback (preferred — phishing-resistant)
Desktop (loopback) http://127.0.0.1:RANDOM_PORT/cb (RFC 8252)

Register all redirect URIs you'll use in the developer portal.

All four libraries accept a discovery URL — point them at https://id.littlexlittle.org/.well-known/openid-configuration and they'll auto-configure.