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.
Recommended libraries¶
- iOS: AppAuth-iOS
- Android: AppAuth-Android
- Flutter:
flutter_appauth - React Native:
react-native-app-auth
All four libraries accept a discovery URL — point them at https://id.littlexlittle.org/.well-known/openid-configuration and they'll auto-configure.