---
title: "sdk/flutter"
description: "Dart / Flutter SDK for iOS, Android, and desktop using flutter_web_auth_2, PKCE S256 authorization code flow, and flutter_secure_storage token persistence."
locale: "en"
---

> Documentation Index
> Fetch the relevant documentation index at: https://vonvon.id/sdks/llms.txt
> Use this file to discover all available pages before exploring further.

# sdk/flutter

## Status

Package status is **Implemented and verified locally**. The Dart and Flutter unit-test suite passes and covers PKCE, nonce and ID token verification, guest capability, session expiry, and storage contracts. Platform-channel paths and a real IdP round-trip still require a device or simulator. This page documents implemented behavior; it is not a production-readiness claim.

Registry status: UNPUBLISHED. Install this SDK only from the repository source checkout; do not use an external package registry.

## Installation

Add to pubspec.yaml and run flutter pub get:

```yaml
# pubspec.yaml
dependencies:
  vonvon:
git:
  url: https://github.com/StringKe/vonvon
  path: sdk/flutter
  ref: main
```

## Platform setup

Register the callback URI scheme on each platform.

```xml
<!-- Android: AndroidManifest.xml (main Activity) -->
<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="com.example.myapp" android:host="auth" />
</intent-filter>

<!-- iOS: Info.plist -->
<key>CFBundleURLTypes</key>
<array>
  <dict>
<key>CFBundleURLSchemes</key>
<array><string>com.example.myapp</string></array>
  </dict>
</array>
```

## Quick start

```dart
import 'package:vonvon/vonvon.dart';

final client = VonvonClient();

// 1. Initialize (fetches OIDC discovery). offline_access is rejected until DPoP is implemented.
await client.configure(
  const VonvonOptions(
issuer: 'https://vonvon.id',
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'com.example.myapp://auth/callback',
scopes: ['openid', 'profile', 'email'],
  ),
);

// 2. Sign in (opens system browser, PKCE S256)
final session = await client.signIn();
print(session.user.email);

// 3. Get the current unexpired access token. Expiry requires reauthorization.
final token = await client.getAccessToken();

// 4. Get the current unexpired session.
final current = await client.getSession();

// 5. Clear secure storage and optionally open end_session. No revoke request is sent.
await client.signOut();
```

## Core API

| Method | Description |
| --- | --- |
| `configure(VonvonOptions, {storageAdapter?})` | Initialize SDK and fetch OIDC discovery. Must be called before all other methods. |
| `signIn({}additionalParameters?, audience?})` | Open system browser with PKCE S256 authorization URL; exchange code and return VonvonSession. |
| `handleRedirect(String url)` | Process App Link or custom scheme callback. Called internally by signIn; invoke manually for cross-process redirect recovery. |
| `getSession()` | Return the current unexpired VonvonSession, or null after clearing expired local state. |
| `getAccessToken({}bool forceRefresh})` | Return the current unexpired access token. forceRefresh: true clears the session and requires reauthorization. |
| `signOut({}bool openLogoutUrl})` | Clear secure storage and optionally open end\_session\_endpoint in the system browser; no revoke request is sent. |
| `setTokenStorage(TokenStorageAdapter)` | Replace the default SecureStorageAdapter (flutter\_secure\_storage) with a custom implementation. |

## Dependencies

| Package | Version | Purpose |
| --- | --- | --- |
| `flutter_web_auth_2` | ^4.0.0 | System browser authorization session and callback receipt |
| `flutter_secure_storage` | ^9.2.4 | Platform secure storage (Keychain / Keystore / DPAPI) |
| `crypto` | ^3.0.3 | SHA-256 for PKCE S256 challenge computation |
| `http` | ^1.2.2 | HTTP client for discovery and token endpoints |

## Security

- Public client — no client secret stored or transmitted.
- PKCE S256 only. No implicit flow or password grant.
- OAuth state generated per request; validated in handleRedirect to prevent CSRF.
- New sessions store access and ID tokens in platform secure storage. The refreshToken compatibility field remains null, and offline\_access is rejected until DPoP is implemented.

## Known limitations

- JWKS-backed ES256 ID token verification, nonce validation, and persisted state-keyed PKCE are implemented and locally tested. Real device and IdP validation are still required before L4 support.
- offline\_access is rejected until the SDK implements DPoP sender binding; access-token expiry requires reauthorization.

Source: https://vonvon.id/sdks/flutter/index.mdx
