> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chappiesdk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Keychain Credential Storage Configuration in Chappie

> Configure Keychain service names, account slots, access groups, and accessibility levels for secure credential storage in single and multi-account apps.

Chappie stores OAuth credentials in the iOS or macOS Keychain automatically after sign-in and restores them on the next launch — your app never needs to manage token storage manually. You control where and how those credentials live through the Keychain-related fields in `ChappieConfiguration`.

## Default settings

| Field                   | Default value                 |
| ----------------------- | ----------------------------- |
| `keychainService`       | `"com.chappie.sdk"`           |
| `keychainAccount`       | `"default"`                   |
| `keychainAccessGroup`   | `nil`                         |
| `keychainAccessibility` | `.whenUnlockedThisDeviceOnly` |

Out of the box, credentials are stored under a single generic-password Keychain item with the most restrictive accessibility level: readable only while the device is unlocked, never migrated to another device, and excluded from iCloud Keychain sync and device backups.

## Keychain accessibility options

`ChappieKeychainAccessibility` maps directly to Security framework `kSecAttrAccessible` constants:

<ParamField path="whenUnlockedThisDeviceOnly" type="ChappieKeychainAccessibility">
  **Default and recommended.** The Keychain item is readable only while the device is unlocked. It never leaves the device — not through iCloud Keychain, backups, or migration. Use this for all foreground-only apps.
</ParamField>

<ParamField path="afterFirstUnlockThisDeviceOnly" type="ChappieKeychainAccessibility">
  The Keychain item is readable after the user unlocks the device at least once after a reboot. Background processes (VoIP, background fetch, push-triggered extensions) can read credentials without requiring the screen to be unlocked. This setting still prevents the item from leaving the device.
</ParamField>

<Warning>
  Enable `.afterFirstUnlockThisDeviceOnly` only when your app genuinely needs to read credentials from a background extension or background task. This accessibility level makes the credential readable by any process running in the background under your app's entitlements. Keep the default `.whenUnlockedThisDeviceOnly` for all foreground-only apps.
</Warning>

## Setting a custom Keychain service

Override the default service identifier to namespace your credentials separately from the SDK default:

```swift theme={null}
let config = ChappieConfiguration(
    keychainService: "com.myapp.chappie",
    keychainAccount: "default"
)

let authSession = Chappie.authSession(configuration: config)
let client = Chappie.client(configuration: config)
```

Using your own reverse-DNS service name avoids any accidental overlap with other apps that use the SDK at its defaults.

## Shared Keychain with app groups or extensions

To share credentials between your main app and an extension (Share Extension, Widget, Notification Service Extension), set `keychainAccessGroup` to your app group's shared Keychain identifier. Your app target must have the Keychain Sharing entitlement and list that access group:

```swift theme={null}
let config = ChappieConfiguration(
    keychainAccount: currentUser.id,
    keychainAccessGroup: "TEAMID.com.example.shared"
)

let authSession = Chappie.authSession(configuration: config)
let client = Chappie.client(configuration: config)
```

Replace `TEAMID` with your ten-character Apple Developer Team ID and `com.example.shared` with the group identifier configured in your entitlement file.

## Multi-account apps

For apps that support multiple signed-in accounts simultaneously, use a distinct `keychainAccount` value per user. Each value creates a separate Keychain item under the same service, so accounts do not interfere with one another:

```swift theme={null}
// User A
let configA = ChappieConfiguration(keychainAccount: userA.id)
let sessionA = Chappie.authSession(configuration: configA)
let clientA  = Chappie.client(configuration: configA)

// User B
let configB = ChappieConfiguration(keychainAccount: userB.id)
let sessionB = Chappie.authSession(configuration: configB)
let clientB  = Chappie.client(configuration: configB)
```

Use a stable, non-PII identifier like a UUID or opaque server-assigned user ID for the account slot name.

<Note>
  Raw access tokens, refresh tokens, and OAuth internals are never surfaced through Chappie's public API. `ChappieAuthSession` exposes an auth state enum and `ChappieAccountInfo` (email, user ID, account ID, plan) — never the underlying bearer token. This prevents accidental token logging or transmission through app code.
</Note>
