Flutter SDK Quick Start
The official Flutter SDK for Optare ID provides OAuth 2.0 authentication with PKCE, secure token storage, and user management for iOS and Android apps.
Installation
Add to your pubspec.yaml:
dependencies:
optareid_flutter: ^0.1.3Run:
flutter pub getPlatform Configuration
iOS Setup
Add URL scheme to ios/Runner/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>Android Setup
Add intent filter to android/app/src/main/AndroidManifest.xml:
<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="myapp" android:host="callback"/>
</intent-filter>
</activity>Initialize SDK
import 'package:optareid_flutter/optareid_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await OptareAuth.init(
clientId: 'your-client-id',
redirectUri: 'myapp://callback',
);
runApp(const MyApp());
}Basic Usage
Login
ElevatedButton(
onPressed: () => OptareAuth.login(),
child: const Text('Sign in with Optare'),
)Check Authentication
Widget build(BuildContext context) {
if (OptareAuth.isAuthenticated) {
return HomeScreen(user: OptareAuth.currentUser);
}
return LoginScreen();
}Get User Profile
final user = await OptareAuth.getUser();
print('Welcome, ${user?.name}');
print('Email: ${user?.email}');
print('Organization: ${user?.organizationId}');Check Licenses
if (OptareAuth.hasLicense('premium-plan')) {
// Show premium features
}
if (OptareAuth.hasEntitlement('export-data')) {
// Enable export button
}Get Organizations
final orgs = await OptareAuth.getOrganizations();
for (final org in orgs) {
print('${org.name} - Role: ${org.role}');
}Get Licenses (Server-Side Validation)
final licenses = await OptareAuth.getLicenses();
for (final license in licenses) {
if (license.isValid && license.hasFeature('premium')) {
// User has premium access
}
}Update Profile
final updated = await OptareAuth.updateProfile(
name: 'New Name',
avatarUrl: 'https://example.com/avatar.jpg',
);Logout
await OptareAuth.logout();
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (_) => LoginScreen()));Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
clientId | String | Required | OAuth client ID from Optare console |
redirectUri | String | Required | Deep link callback URI |
issuer | String | https://id.optare.one | Optare ID server URL |
scopes | List<String> | ['openid', 'email', 'profile'] | OAuth scopes |
storage | TokenStorage | SecureTokenStorage() | Token storage adapter |
User Object
class OptareUser {
String id; // Unique user ID
String? email; // Email address
String? name; // Display name
String? picture; // Profile picture URL
String? organizationId; // Organization ID
List<String> licenses; // Product licenses
List<String> entitlements; // Feature entitlements
List<String> roles; // User roles
}Error Handling
try {
await OptareAuth.login();
} on OptareAuthException catch (e) {
showSnackBar('Authentication failed: ${e.message}');
} on OptareNetworkException catch (e) {
showSnackBar('Network error: ${e.message}');
}Complete Example
import 'package:flutter/material.dart';
import 'package:optareid_flutter/optareid_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await OptareAuth.init(
clientId: 'your-client-id',
redirectUri: 'myapp://callback',
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
home: OptareAuth.isAuthenticated
? const HomeScreen()
: const LoginScreen(),
);
}
}
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () => OptareAuth.login(),
child: const Text('Sign in with Optare'),
),
),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
final user = OptareAuth.currentUser;
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
IconButton(
icon: const Icon(Icons.logout),
onPressed: () async {
await OptareAuth.logout();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const LoginScreen()),
);
},
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (user?.picture != null)
CircleAvatar(
backgroundImage: NetworkImage(user!.picture!),
radius: 50,
),
const SizedBox(height: 16),
Text('Welcome, ${user?.name ?? 'User'}!'),
Text(user?.email ?? ''),
],
),
),
);
}
}Troubleshooting
Android Build Error (Pre-v0.1.3)
If you see incorrect androidPackage: one.optare.optareid_flutter, upgrade to v0.1.3:
flutter pub upgrade optareid_flutterDeep Links Not Working
Ensure your redirect URI scheme matches:
pubspec.yaml→redirectUriparameterandroid/app/src/main/AndroidManifest.xml→android:schemeios/Runner/Info.plist→CFBundleURLSchemes- Optare Dashboard → OAuth Client redirect URIs
Next Steps
- Token Verification - Verify tokens on your backend
- Custom Claims - Use organization and license data
- API Reference (opens in a new tab) - Full API documentation on pub.dev