Skip to content

Repository files navigation

KMPAuth — Kotlin Multiplatform Authentication Library

Build Kotlin Maven Central

badge-android badge-ios badge-desktop badge-web

Simple and easy-to-use authentication for Compose Multiplatform apps on Android, iOS, Desktop (JVM) and Web (JS + wasm). Sign in with Google, Apple, Facebook, GitHub, Microsoft, email/password, magic links, phone number or anonymously — backed by Firebase or Supabase (or your own backend), with every API callable from commonMain on every target.

SampleApp

What's supported where

Every sign-in method is served by a backend (or by your own server, when the method just hands you a token). So two questions: which backend runs on your platforms, and which methods that backend serves.

Backend Android iOS Desktop (JVM) Web (JS) Web (wasm)
Firebase ✅ (REST) ✅ (REST²)
Supabase

("your server" below = no backend needed — the state hands you the provider's token to verify yourself.)

Sign-in method Works with Android iOS Desktop (JVM) Web (JS) Web (wasm)
Google your server · Firebase · Supabase
Apple Firebase · Supabase ✅ native ✅⁴ ✅⁴
Apple (native token, no backend) your server
Facebook (native SDK login) your server · Firebase · Supabase¹
GitHub / Microsoft / Facebook-web / any OAuth Firebase · Supabase ✅⁴ ✅⁴
Email (password / reset / magic link) Firebase · Supabase
Phone number Firebase · Supabase ✅³ ✅³ ✅³
Anonymous Firebase · Supabase

¹ Supabase accepts Facebook Limited Login (OIDC) tokens only. Meta's SDK exists only on Android/iOS — on other platforms use the browser-OAuth row (rememberOAuthState("facebook.com") with Firebase, or OAuthWebFlow("facebook.com") with Supabase). ² Firebase on wasm runs on the REST engine (no Firebase SDK there): email, anonymous, id-token exchange, email link, password reset, reauthentication — not browser web flows or phone. ³ Beyond Android/iOS only with Supabase (SMS OTP); Firebase phone auth needs the mobile SDKs. ⁴ Only with Supabase (KMPAuth.signIn(AuthCredential.OAuthWebFlow("github.com"))): Desktop works out of the box, Android/iOS need Supabase's deep-link setup, and on web the flow is a full-page redirect — the session is restored after reload.

Everything compiles and is callable from commonMain on all targets — a feature unavailable on the current platform reports a failed Result with the reason instead of not compiling or silently doing nothing.

Installation (short version)

commonMain.dependencies {
    // Identity providers - native SDK sign-in, no backend required:
    implementation("io.github.mirzemehdi:kmpauth-google:<version>")   // Google sign-in
    implementation("io.github.mirzemehdi:kmpauth-apple:<version>")    // if needed: native Sign in with Apple (iOS)
    implementation("io.github.mirzemehdi:kmpauth-facebook:<version>") // if needed: Facebook login (Android/iOS)

    implementation("io.github.mirzemehdi:kmpauth-uihelper:<version>") // if needed: branded sign-in buttons

    // Session backend - pick one (or both):
    implementation("io.github.mirzemehdi:kmpauth-firebase:<version>") // Firebase backend
    implementation("io.github.mirzemehdi:kmpauth-supabase:<version>") // if needed: Supabase backend
}

iOS apps add the native SDKs via Swift Package Manager — see Getting started.

Pick your setup

1. No backend — you verify the token yourself (Google · Facebook · Apple)

Only the provider modules (kmpauth-google, kmpauth-facebook, kmpauth-apple). The rememberXxxSignInState states hand you the provider's credential and stop there — send it to your own server:

KMPAuth.initialize {
    google(serverId = WebClientId)
}

val googleSignIn = rememberGoogleSignInState(onResult = { result ->
    result.onSuccess { googleUser ->
        api.login(googleUser.idToken) // verify server-side
    }.onFailure { error -> /* cancelled, misconfigured, ... */ }
})
GoogleSignInButton { googleSignIn.launch() }

// same shape for Facebook and native Apple:
val facebookSignIn = rememberFacebookSignInState(onResult = { result: Result<FacebookUser> -> })
val appleSignIn = rememberAppleSignInState(onResult = { result: Result<AppleUser> -> })

2. Firebase (guide)

Add kmpauth-firebase — the backend registers itself, and on Android/iOS there is zero configuration (the SDK reads google-services.json / GoogleService-Info.plist). The rememberXxxAuthState states exchange the credential for a Firebase session; account operations live on KMPAuth:

KMPAuth.initialize {
    google(serverId = WebClientId)
    // Desktop/Web only - Android/iOS use the bundled config files:
    firebase(apiKey = "...", projectId = "...", applicationId = "...")
}

val onResult: (Result<KMPAuthUser>) -> Unit = { result -> /* ... */ }

val googleSignIn = rememberGoogleAuthState(onResult = onResult)
GoogleSignInButton { googleSignIn.launch() }

val appleSignIn = rememberAppleAuthState(onResult = onResult)       // native on iOS, web flow elsewhere
val facebookSignIn = rememberFacebookAuthState(onResult = onResult) // kmpauth-facebook, Android/iOS
val githubSignIn = rememberGithubAuthState(onResult = onResult)     // browser OAuth web flow
val microsoftSignIn = rememberMicrosoftAuthState(onResult = onResult)
val emailSignIn = rememberEmailAuthState(email, password, onResult = onResult)
val phoneSignIn = rememberPhoneAuthState(phoneNumber, onResult = onResult)
val guestSignIn = rememberAnonymousAuthState(onResult = onResult)

KMPAuth.currentUser()
KMPAuth.signOut()
KMPAuth.sendPasswordResetEmail(email)
KMPAuth.reauthenticate(AuthCredential.EmailPassword(email, password))

3. Supabase (guide)

Add kmpauth-supabase (plus a Ktor client engine per platform — see the guide) — no Firebase anywhere, works on every target including wasm. Same states, same KMPAuth operations; only the registration differs:

KMPAuth.initialize {
    google(serverId = WebClientId)
    supabase(url = projectUrl, apiKey = publishableKey)
}

val onResult: (Result<KMPAuthUser>) -> Unit = { result -> /* ... */ }

val googleSignIn = rememberGoogleAuthState(onResult = onResult)     // id-token grant
val facebookSignIn = rememberFacebookAuthState(onResult = onResult) // kmpauth-facebook, Limited Login (OIDC), Android/iOS
val emailSignIn = rememberEmailAuthState(email, password, onResult = onResult)
val phoneSignIn = rememberPhoneAuthState(phoneNumber, onResult = onResult) // SMS OTP, every target
val guestSignIn = rememberAnonymousAuthState(onResult = onResult)

// Same composables as with Firebase - the backend behind them differs:
val appleSignIn = rememberAppleAuthState(onResult = onResult)       // native on iOS, browser flow elsewhere
val githubSignIn = rememberGithubAuthState(onResult = onResult)     // browser OAuth: Desktop OOTB, mobile via deep links
val microsoftSignIn = rememberMicrosoftAuthState(onResult = onResult)
// ...or any GoTrue provider: rememberOAuthState(provider = "gitlab") /
// KMPAuth.signIn(AuthCredential.OAuthWebFlow("gitlab"))

KMPAuth.sendPasswordResetEmail(email)
KMPAuth.signOut()

Need Firebase and Supabase side by side? Register both in initialize { } (the first — Firebase — stays the default) and scope subtrees with ProvideKMPAuthBackend("supabase") { ... }Custom & multiple backends.

4. UI helper buttons (guide)

Add kmpauth-uihelper for pre-styled buttons following each brand's guidelines — they're plain composables, so they wire to any state from the setups above (and any clickable of your own works instead):

GoogleSignInButton(modifier = Modifier.fillMaxWidth()) { googleSignIn.launch() }
GoogleSignInButtonIconOnly(onClick = { googleSignIn.launch() })

AppleSignInButton(modifier = Modifier.fillMaxWidth()) { appleSignIn.launch() }
AppleSignInButtonIconOnly(onClick = { appleSignIn.launch() })

FacebookSignInButton(modifier = Modifier.fillMaxWidth()) { facebookSignIn.launch() }
FacebookSignInButtonIconOnly(onClick = { facebookSignIn.launch() })

Documentation

Start here — read only what you need:

Guide What's in it
Getting started Dependencies, iOS SPM setup, requirements, KMPAuth.initialize, first sign-in
Core concepts The two state layers, KMPAuthUser, the KMPAuth object, account linking, reauthentication

Identity providers (bring their own SDK/flow, work with any backend or none):

Guide Platforms
Google Android · iOS · Desktop · JS · wasm
Apple Android · iOS (native) · Desktop — or iOS-only without any backend
Facebook Android · iOS

Backends & backend-served sign-in (these flows exist only through Firebase/Supabase):

Guide What's in it
Firebase Auto-registration, Android/iOS zero-config, Desktop (REST + browser flows), web notes
Supabase Setup, Ktor engines, what maps to Supabase (works on wasm)
GitHub / Microsoft / any OAuth Firebase (Android · iOS · Desktop) or Supabase (every target, see guide)
Email — password, reset, magic link Served by Firebase or Supabase
Phone number Firebase (Android · iOS) or Supabase (every target)
Anonymous (guest) Served by Firebase or Supabase
Custom & multiple backends AuthProviderBackend, LocalKMPAuthBackend scoping

Also: UI helper buttons · Full API reference · Sample app covering every feature

Migrating from 2.x

Follow the step-by-step MIGRATION.md — most 2.x code keeps compiling (the *UiContainer composables and GoogleAuthProvider.create still work, deprecated). All notable changes live in CHANGELOG.md.


Where else this is used

I'm also building KAppMaker AI — an always-on cloud machine that runs Claude Code unattended and builds Compose Multiplatform apps overnight, driven from Telegram. See a full run replayed →

Releases

Used by

Contributors

Languages