Repository navigation
getting started
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.
The Compose module brings the headless one transitively (api), so a UI app can take just it.
val authConfig = KmpSupabaseAuthConfig(
projectRef = "your-project-ref",
googleWebClientId = BuildKonfig.GOOGLE_OAUTH_WEB_CLIENT_ID,
redirectUrl = "myapp://login-callback",
)Use the Google Cloud Web client id — not the Android or iOS one. Both GoTrue and the Android Credential Manager verify against the Web id, and supplying the Android id fails at runtime with an opaque provider error. See Google Sign-In.
Leaving a provider id blank is safe: the library skips that native flow and falls back to the
OAuth redirect. Only a blank or placeholder projectRef is fatal — without it there is no client
to install onto.
The library never calls createSupabaseClient. It installs onto the client your app already
has — in a kmp-project-template fork, the one your Supabase training layer codegens into
core/network.
// core/network/di/ProjectNetworkModule.kt — owner:fork, survives template sync
single<SupabaseExtrasProvider> {
SupabaseExtrasProvider { id ->
when (id) {
authConfig.projectRef -> {
{
kmpSupabaseAuthExtras(authConfig)(this) // Auth
kmpSupabaseComposeAuthExtras(authConfig)(this) // ComposeAuth (native sign-in)
}
}
else -> { {} }
}
}
}?> Two blocks because compose-auth is a Compose artifact. Keeping it out of the headless module
is what lets cmp-supabase-auth reach 17 targets instead of 7 — see Target matrix.
One line:
includes(kmpSupabaseAuth(authConfig))…or one per layer, if you prefer each rung where it belongs:
includes(kmpSupabaseAuthNetwork(authConfig)) // core/network
includes(kmpSupabaseAuthStore()) // core/store
includes(kmpSupabaseAuthRepository()) // core/data
includes(kmpSupabaseAuthComposeModule()) // featurekmpSupabaseAuth(config) is defined as the first three, and a test asserts the binding sets are
identical — the two forms cannot drift apart.
On kmp-project-template, the client comes from a factory rather than a direct binding, so pass the lookup:
includes(
kmpSupabaseAuth(authConfig) {
get<SupabaseClientFactory>().requireClientFor(authConfig.projectRef).client
},
)This is the step that silently breaks RLS if skipped. The library exposes the JWT; the template's
existing AuthHeaderBridge does the rest:
single<AuthTokenSource> {
val repository = get<KmpSupabaseAuthRepository>()
AuthTokenSource { _ -> repository.accessTokenFlow }
}KmpSupabaseLoginScreen(
viewModel = koinViewModel(),
client = koinInject(),
header = { YourLogo() },
onSignedIn = { navigateHome() },
)Or compose your own from the parts:
val google = rememberKmpSupabaseGoogleSignIn(client, onError = viewModel::onSignInFailed)
KmpSupabaseGoogleSignInButton(onClick = { viewModel.onSignInStarted(); google.launch() })
KmpSupabaseContinueAsGuestButton(onClick = viewModel::continueAsGuest)!> Never treat the provider callback as success. On Android NativeSignInResult.Success
frequently never fires even though the session landed. Observe KmpSupabaseAuthRepository.isSignedIn
instead — KmpSupabaseAuthViewModel already does.
viewModel.continueAsGuest() // anonymous session, RLS applies immediately
rememberKmpSupabaseGoogleSignIn(client, linkIdentity = true) // upgrade, KEEPING the user idlinkIdentity preserves the id, so no guest data has to be migrated. It works on the same
install; a guest signing in on a second device gets a different id.
- Google Sign-In setup · Sign in with Apple setup
- Architecture — why it is shaped this way
-
Getting started
-
Provider setup
-
Modules
-
Reference
-
Project