← ClaudeAtlas

android-auth-securitylisted

Authentication and app security patterns for Android/KMP - login/logout flows, session ownership, token refresh, secure local storage, guarded navigation, and secret handling. Use this skill whenever adding sign-in, session restore, token refresh, protected APIs, logout, or handling secrets and user credentials. Trigger on phrases like "login", "signup", "token refresh", "session", "logout", "auth guard", "secure storage", "biometric", or "secret management".
lenorebreakneck630/claude-zero-to-hero-android-KMP · ★ 1 · API & Backend · score 64
Install: claude install-skill lenorebreakneck630/claude-zero-to-hero-android-KMP
# Android / KMP Authentication and Security ## Core Principles - Authentication state is a first-class domain concern. - Store only the minimum secret data required. - Treat tokens and credentials differently from general preferences. - UI decides what to render from a session state model; it does not inspect tokens directly. - Logging must never expose passwords, tokens, refresh responses, or personally sensitive payloads. --- ## Recommended Module Ownership ```text :core:domain -> shared `SessionState`, auth error types if used broadly :core:data or :core:auth -> token storage abstraction, session persistence :feature:auth:domain -> auth contracts and models :feature:auth:data -> API/data source implementations :feature:auth:presentation-> login screen, registration screen, auth ViewModels ``` Create a dedicated `:core:auth` module when auth grows beyond a few classes. --- ## Session Model Expose a typed session model instead of raw token checks: ```kotlin sealed interface SessionState { data object Unknown : SessionState data object LoggedOut : SessionState data class LoggedIn(val userId: String) : SessionState } ``` The app root observes `SessionState` and decides whether to show the auth flow or the main flow. --- ## Auth Contracts Keep contracts in domain: ```kotlin interface AuthRepository { fun observeSession(): Flow<SessionState> suspend fun login(email: String, password: String): EmptyResult<AuthError>