API reference
The public surface of
io.thunderid:android, as documented in its reference pages.SignInThe `SignIn` composable renders a full app-native sign-in form. It drives the Flow Execution API loop automatically: initiating the flow, presenting the server-defined inputs and actions on each step, and completing when the user is authenticated. `SignIn` requires `ThunderIDProvider` in its ancestor composable hierarchy.
applicationIdrequiredStringThe Application ID from your ThunderID application settings. Identifies which sign-in flow to execute.
modifieroptionalModifierCompose modifier applied to the form container.
onCompleteoptional(() -> Unit)?Called when authentication completes successfully.
onErroroptional((String) -> Unit)?Called with an error message when a flow step fails.
import dev.thunderid.compose.components.presentation.auth.SignIn@Composablefun AuthView(applicationId: String) {SignIn(applicationId = applicationId,modifier = Modifier.fillMaxWidth().padding(16.dp))}
SignInButtonThe `SignInButton` composable renders a pre-styled button that calls an `onClick` lambda when tapped. It does not initiate the sign-in flow itself. Your `onClick` handler opens the sign-in UI (e.g., showing a `SignIn` form or launching the redirect URL). `SignInButton` requires `ThunderIDProvider` in its ancestor composable hierarchy.
onClickrequired() -> UnitCalled when the button is tapped.
modifieroptionalModifierCompose modifier.
import dev.thunderid.compose.components.actions.SignInButton@Composablefun LandingView() {var showSignIn by remember { mutableStateOf(false) }SignInButton(onClick = { showSignIn = true })if (showSignIn) {SignIn(applicationId = "<your-application-id>")}}
SignOutButtonThe `SignOutButton` composable renders a pre-styled button that calls `ThunderIDClient.signOut()`, then calls `ThunderIDState.refresh()` to update the reactive auth state. It disables itself automatically while the sign-out operation is in progress. `SignOutButton` requires `ThunderIDProvider` in its ancestor composable hierarchy.
modifieroptionalModifierCompose modifier applied to the button.
onSignOutCompleteoptional(() -> Unit)?Called after sign-out completes and `ThunderIDState` has been refreshed.
import dev.thunderid.compose.components.actions.SignOutButton@Composablefun HomeView() {Column {Text("You are signed in.")SignOutButton()}}
SignUpThe `SignUp` composable renders a full app-native registration form. It drives the Flow Execution API loop automatically: initiating the registration flow, presenting the server-defined inputs and actions on each step, and completing when the user is registered and authenticated. `SignUp` requires `ThunderIDProvider` in its ancestor composable hierarchy.
modifieroptionalModifierCompose modifier applied to the form container.
onCompleteoptional(() -> Unit)?Called when registration completes successfully.
onErroroptional((String) -> Unit)?Called with an error message when a flow step fails.
import dev.thunderid.compose.components.presentation.auth.SignUp@Composablefun RegisterView() {SignUp(modifier = Modifier.fillMaxWidth().padding(16.dp))}
SignedInThe `SignedIn` composable conditionally renders its content only when the user is authenticated. It reads the current sign-in state from `LocalThunderID` and displays protected UI for signed-in users, while rendering optional fallback content (or nothing) when the user is not authenticated. `SignedIn` requires `ThunderIDProvider` in its ancestor composable hierarchy.
fallbackoptional(@Composable () -> Unit)?The composable to render when the user is not authenticated. Defaults to nothing.
contentrequired@Composable () -> UnitThe composable to render when the user is authenticated.
import dev.thunderid.compose.components.guards.SignedIn@Composablefun ContentView() {SignedIn {Text("You are signed in.")}}
SignedOutThe `SignedOut` composable conditionally renders its content only when the user is **not** authenticated. It is the counterpart to `SignedIn`. `SignedOut` requires `ThunderIDProvider` in its ancestor composable hierarchy.
fallbackoptional(@Composable () -> Unit)?The composable to render when the user is authenticated. Defaults to nothing.
contentrequired@Composable () -> UnitThe composable to render when the user is not authenticated.
import dev.thunderid.compose.components.guards.SignedOut@Composablefun ContentView() {SignedOut {Text("Please sign in to continue.")}}
UserProfileThe `UserProfile` composable renders an editable profile form. It loads the user's current profile from `/scim2/Me` when it first composes, presents editable fields for `displayName` and `phoneNumbers`, and saves changes via `ThunderIDClient.updateUserProfile`. `UserProfile` requires `ThunderIDProvider` in its ancestor composable hierarchy.
modifieroptionalModifierCompose modifier applied to the form container.
onSavedoptional(() -> Unit)?Called after a successful profile save.
onErroroptional(() -> Unit)?Called when a load or save operation fails.
import dev.thunderid.compose.components.presentation.user.UserProfile@OptIn(ExperimentalMaterial3Api::class)@Composablefun ProfileSheet(onDismiss: () -> Unit) {ModalBottomSheet(onDismissRequest = onDismiss) {UserProfile(modifier = Modifier.fillMaxWidth().padding(24.dp),onSaved = onDismiss)}}
ChangeCredentialThe `ChangeCredential` composable renders a form that lets a signed-in user set a new value for one of their own credentials. It collects only a new value and its confirmation, checks it against the applicable rules, and posts the change via `ThunderIDClient.updateUserCredentials`. It reads the rules it needs from the user type schema (`GET /users/me/meta`), fetched once and shared with any other mounted component that needs it (for example `UserProfile`), so multiple components cost one request rather than one each. The default label and messages are built from the credential attribute's own `displayName` in that schema, so they always match whatever an admin named it there. By default it manages the `password` credential. To manage a different one, for example a PIN declared on the user type schema, set `attribute = 'pin'`; render the composable once per credential to let a user manage more than one. `ChangeCredential` requires `ThunderIDProvider` in its ancestor composable hierarchy. `ChangeCredential` collects only a new value and its confirmation, not the account's existing value. The self-service credential write path does not verify the current value today, so asking for one would only teach the user a false sense of security.
modifieroptionalModifierCompose modifier applied to the form container.
attributeoptionalStringThe credential attribute this instance manages, any attribute the user type schema declares `credential: true` for. Defaults to `"password"`.
onSuccessoptional(() -> Unit)?Called after the credential has been changed successfully.
import dev.thunderid.compose.components.presentation.user.ChangeCredential@Composablefun SecuritySection() {Column {Text("Security")ChangeCredential()}}
Configuration`ThunderIDConfig` is the configuration data class passed to `ThunderIDClient.initialize(config, storage)` and to the `ThunderIDProvider` composable.
baseUrlString**Required.** Your ThunderID instance URL. Must use HTTPS (e.g., `https://localhost:8090`).
clientIdString?The Client ID from your ThunderID application. Required for redirect-based authentication and token operations.
scopesListOAuth 2.0 scopes to request. Include `"profile"` and `"email"` to receive user identity claims.
afterSignInUrlString?The redirect URI to return to after sign-in. Must match an **Allowed Redirect URI** registered in the console.
afterSignOutUrlString?The redirect URI to return to after sign-out. Must match an **Allowed Post-Logout Redirect URI** in the console.
signInUrlString?Override the sign-in URL. Defaults to the ThunderID hosted sign-in page.
signUpUrlString?Override the sign-up URL.
clientSecretString?Client secret for confidential clients. Do not include this in a shipped Android app.
signInOptionsMapAdditional query parameters appended to the authorization URL on sign-in.
signOutOptionsMapAdditional parameters sent with the sign-out request.
signUpOptionsMapAdditional parameters sent with the sign-up request.
applicationIdString?The Application ID used for app-native (embedded) sign-in flows via the Flow Execution API.
organizationHandleString?The organization handle for multi-tenant deployments.
tokenValidationTokenValidationConfigControls ID token validation behavior.
storageStorageAdapter?Custom token storage backend. Defaults to `EncryptedStorageAdapter`.
instanceIdInt?Identifies the SDK instance when running multiple instances in one process.
import dev.thunderid.android.ThunderIDConfigval config = ThunderIDConfig(baseUrl = "https://localhost:8090",clientId = "<your-client-id>",scopes = listOf("openid", "profile", "email"),afterSignInUrl = "dev.thunderid.app://callback",afterSignOutUrl = "dev.thunderid.app://logout",applicationId = "<your-application-id>")
ThunderIDClient`ThunderIDClient` is the core authentication client in the `dev.thunderid:android` library. It manages the full authentication lifecycle: initialization, sign-in (both app-native and redirect-based), session, token management, and user profile operations. When you use the `dev.thunderid:compose` library, a `ThunderIDClient` instance is created and managed automatically. You can access it via `LocalThunderID.current.client` from any composable.
import dev.thunderid.android.ThunderIDClientimport dev.thunderid.android.ThunderIDConfigval client = ThunderIDClient()client.initialize(config = ThunderIDConfig(baseUrl = "https://localhost:8090",clientId = "<your-client-id>",scopes = listOf("openid", "profile", "email"),afterSignInUrl = "dev.thunderid.app://callback",afterSignOutUrl = "dev.thunderid.app://logout"))
ThunderIDState`ThunderIDState` is the reactive authentication state class provided by the `dev.thunderid:compose` library. It holds the current user, loading state, and initialization status, and exposes the underlying `ThunderIDClient` for direct API calls. `ThunderIDState` is provided via `LocalThunderID`, a `CompositionLocal` injected by `ThunderIDProvider`. Any composable in the hierarchy can read it using `LocalThunderID.current`.
import androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport dev.thunderid.android.ThunderIDConfigimport dev.thunderid.compose.ThunderIDProviderclass MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {ThunderIDProvider(config = ThunderIDConfig(baseUrl = "https://localhost:8090",clientId = "<your-client-id>",afterSignInUrl = "dev.thunderid.app://callback",afterSignOutUrl = "dev.thunderid.app://logout")) {AppContent()}}}}