> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.id.me/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.id.me/_mcp/server.

# Android communities SDK

> Integrate the IDMe Android Communities SDK into your Android app to enable identity verification using Chrome Custom Tabs.

---

> **Prerequisites**
>
> Before integrating the SDK, ensure your development environment meets the following requirements:
>
> * Android minimum API Level: `26` (Android 8.0)
> * Android Studio: Ladybug or later
> * Kotlin version: `2.1+`
> * Chrome must be installed on the target device (required for Chrome Custom Tab)

# Adding the SDK to your project

Ensure `mavenCentral()` is listed in your project-level `settings.gradle.kts` (or `build.gradle`) repositories block:

**`Example`**

```kotlin Example
dependencyResolutionManagement {
    repositories {
        mavenCentral()
    }
}
```

Add the following to your app-level `build.gradle.kts`:

**`Example`**

```kotlin Example
dependencies {
    implementation("com.idmelabs.auth:android-auth-sample-code:1.0.8")
}
```

Sync your Gradle project.

# Required app integration steps

In your app's `AndroidManifest.xml`, register `IDmeRedirectActivity` with an intent-filter matching your redirect URI scheme. This Activity captures the OAuth callback from the Chrome Custom Tab after verification completes.

**`Example`**

```xml Example
<activity
    android:name="com.idme.auth.auth.IDmeRedirectActivity"
    android:exported="true"
    android:launchMode="singleTask"
    android:theme="@android:style/Theme.Translucent.NoTitleBar">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:scheme="yourapp"
            android:host="idme"
            android:path="/callback" />
    </intent-filter>
</activity>
```

Replace `yourapp` with your app's registered redirect scheme. The `redirectURI` you pass to `IDmeConfiguration` must match this exactly (e.g. `yourapp://idme/callback`).

Alternatively, use a manifest placeholder in your app-level `build.gradle.kts` to avoid hardcoding the scheme:

**`Example`**

```kotlin Example
android {
    defaultConfig {
        manifestPlaceholders["idmeRedirectScheme"] = "yourapp"
    }
}
```

# Initialization

Create an `IDmeConfiguration` with your client credentials and desired auth settings, then instantiate `IDmeAuth`:

**`Example`**

```kotlin Example
import com.idme.auth.IDmeAuth
import com.idme.auth.configuration.*

val config = IDmeConfiguration(
    clientId = "YOUR_CLIENT_ID",
    redirectURI = "yourapp://idme/callback",
    scopes = listOf(IDmeScope.MILITARY),
    environment = IDmeEnvironment.PRODUCTION,
    authMode = IDmeAuthMode.OAUTH_PKCE
)

val idme = IDmeAuth(config, applicationContext)
```

### Configuration reference

| Parameter          | Type                   | Default      | Description                                        |
| ------------------ | ---------------------- | ------------ | -------------------------------------------------- |
| `clientId`         | `String`               | —            | OAuth Client ID from IDMe                          |
| `redirectURI`      | `String`               | —            | Registered redirect URI — must match your manifest |
| `scopes`           | `List<IDmeScope>`      | —            | Community scopes to request                        |
| `environment`      | `IDmeEnvironment`      | `PRODUCTION` | `PRODUCTION` or `SANDBOX`                          |
| `authMode`         | `IDmeAuthMode`         | `OAUTH_PKCE` | `OAUTH_PKCE`, `OAUTH`, or `OIDC`                   |
| `verificationType` | `IDmeVerificationType` | `SINGLE`     | `SINGLE` or `GROUPS`                               |
| `clientSecret`     | `String?`              | `null`       | Required for `OAUTH` mode only                     |

### Auth modes

| Mode         | Description                                                              |
| ------------ | ------------------------------------------------------------------------ |
| `OAUTH_PKCE` | **Recommended.** OAuth 2.0 with PKCE. No client secret required.         |
| `OAUTH`      | Standard OAuth 2.0 Authorization Code. Requires `clientSecret`.          |
| `OIDC`       | OpenID Connect. Returns a signed ID token validated against IDMe's JWKS. |

### Available scopes

| Scope             | Community                                    |
| ----------------- | -------------------------------------------- |
| `MILITARY`        | Active duty, veterans, and military families |
| `FIRST_RESPONDER` | First responders                             |
| `NURSE`           | Nurses                                       |
| `TEACHER`         | Teachers and educators                       |
| `STUDENT`         | Students                                     |

# Common usage patterns

## Starting the verification flow

Call `login()` from a coroutine, passing the current `Activity`. This opens a Chrome Custom Tab for the user to verify their community membership. The tab dismisses automatically when verification completes.

**`Example`**

```kotlin Example
viewModelScope.launch {
    try {
        val credentials = idme.login(activity)
        // Verification complete — credentials contains access and refresh tokens
        println(credentials.accessToken)
        println(credentials.expiresAt)
    } catch (e: IDmeAuthError.UserCancelled) {
        // User dismissed the verification tab
    } catch (e: IDmeAuthError) {
        println("Verification failed: ${e.message}")
    }
}
```

## Retrieving community attributes (OAuth / PKCE)

**`Example`**

```kotlin Example
val attributes = idme.attributes()
for (attr in attributes.attributes) {
    println("${attr.handle}: ${attr.value}")
}
```

## Retrieving user info (OIDC)

**`Example`**

```kotlin Example
val userInfo = idme.userInfo()
println(userInfo.email)
println(userInfo.givenName)
```

## Token management

The SDK stores credentials in `EncryptedSharedPreferences` and handles token refresh automatically:

**`Example`**

```kotlin Example
// Get valid credentials, refreshing if they expire within 60 seconds
val creds = idme.credentials(minTTL = 60)

// Check expiry
if (creds.isExpired) {
    // Token has expired
}

if (creds.expiresWithin(300)) {
    // Token expires within 5 minutes
}
```

## Fetching available policies

Discover which verification policies your organization supports:

**`Example`**

```kotlin Example
val policies = idme.policies()
for (policy in policies.filter { it.active }) {
    println("${policy.name} — scope: ${policy.handle}")
}
```

## Logout

**`Example`**

```kotlin Example
idme.logout()
```

Clears all stored credentials and tokens from encrypted storage.

# Error handling

All errors are thrown as `IDmeAuthError`, a sealed class:

**`Example`**

```kotlin Example
try {
    val credentials = idme.login(activity)
} catch (e: IDmeAuthError.UserCancelled) {
    // User dismissed the Chrome Custom Tab
} catch (e: IDmeAuthError.TokenExchangeFailed) {
    println("Token exchange failed (${e.statusCode}): ${e.errorMessage}")
} catch (e: IDmeAuthError.StateMismatch) {
    // OAuth state parameter mismatch — possible CSRF attempt
} catch (e: IDmeAuthError.NotAuthenticated) {
    println("No stored credentials available")
} catch (e: IDmeAuthError) {
    println(e.message)
}
```