Repository navigation
home
Supabase authentication for Kotlin Multiplatform — native Google sign-in through the Android
Credential Manager, native Apple sign-in through ASAuthorization on iOS, anonymous sessions with
an id-preserving upgrade, and a web-OAuth fallback everywhere else.
The public API is entirely commonMain. No consumer writes a platform-conditional import to make sign-in work.
Set supabaseAuthVersion to the version shown by the Maven Central badge above —
that badge is read live from the registry and is always the latest published release.
repositories {
mavenCentral()
google() // see the note below — required only for cmp-supabase-auth-compose
}
val supabaseAuthVersion = "<see the Maven Central badge>"
dependencies {
implementation("io.github.mobilebytelabs:cmp-supabase-auth:$supabaseAuthVersion") // headless
implementation("io.github.mobilebytelabs:cmp-supabase-auth-compose:$supabaseAuthVersion") // Compose UI (optional)
}Why
google()?cmp-supabase-auth-composepulls in Compose Multiplatform, whose transitive AndroidX dependencies (androidx.savedstate,androidx.lifecycle-*) are published to Google's Maven repository and are not mirrored to Maven Central. Verified by resolving both modules against Central alone: the build fails on those transitive artifacts, not on this library's own.
cmp-supabase-authalone needs onlymavenCentral(). If you are not using the Compose bindings, you do not needgoogle()for this library at all.
val AppModule = module {
includes(
kmpSupabaseAuth(KmpSupabaseAuthConfig(projectRef = "…", googleWebClientId = "…")),
kmpSupabaseAuthComposeModule(),
)
}
KmpSupabaseLoginScreen(
viewModel = koinViewModel(),
client = koinInject(),
onSignedIn = { navigateHome() },
)Four apps in one workspace had each built their own Supabase sign-in. One of them worked. The
others were a provider interface wired to nothing, a REST client with the native token hardcoded
to "", and a Supabase client with no auth at all. A fifth shipped an Apple button on Android
that opened a browser it could never return from.
Auth is the worst thing to re-implement per app: a bug in it is a security bug, and a fix that only reaches the next project is close to worthless.
| Native sign-in | Credential Manager (Android) · ASAuthorization (iOS) · OAuth redirect elsewhere — the plugin picks per platform |
| Guest sessions |
signInAnonymously() with RLS from the first write; linkIdentity upgrades without changing the user id
|
| Layered DI | One includes(kmpSupabaseAuth(config)), or one line per rung across core/network → core/store → core/data
|
| Drop-in UI | Slot-based KmpSupabaseLoginScreen, brand-compliant provider buttons, a session-driven ViewModel |
| Testability |
FakeKmpSupabaseAuthRepository ships in the main artifact |
It never creates a Supabase client. It installs Auth and ComposeAuth onto the one your app
already has. A second client carries no session, so every RLS-gated call resolves no auth.uid()
— while compiling cleanly and passing static checks the whole way.
Signed-in comes from the session, never the button callback. On Android the native Google
onResult(Success) callback frequently never fires even though the session landed. Observed
on-device: the app sat on "Signing in…" while Supabase logged Authenticated.
The library owns the session; your app keeps owning the user. Profile data stays in your
store, untouched. KmpSupabaseAuthUser carries identity only.
| Android | iOS | Desktop | Web | macOS | |
|---|---|---|---|---|---|
| native | native | redirect | redirect | redirect | |
| Apple | redirect | native | redirect | redirect | redirect |
| Anonymous | ✅ | ✅ | ✅ | ✅ | ✅ |
macOS gets no native Apple sign-in — compose-auth publishes no macOS artifact. Measured, not an
oversight; see the target matrix.
- ComposeAuth — native sign-in composables
- ComposeAuthUI — provider buttons, form fields, validators
- supabase-kt — the GoTrue client
This library adds what those do not: DI, a provider-neutral domain surface, the session-truth ViewModel, the token bridge, and the Android OAuth callback receiver.
-
Getting started
-
Provider setup
-
Modules
-
Reference
-
Project