frica_id_flutter 1.1.0
frica_id_flutter: ^1.1.0 copied to clipboard
Official Flutter SDK for Sign in with Frica ID. OAuth 2.1 PKCE authorization, user management, and seamless authentication for iOS, Android, and Web.
frica_id_flutter #
The official Flutter SDK for Sign in with Frica ID. Implements OAuth 2.1 with PKCE, user authentication, session token refresh, and ready-to-use Flutter UI widgets.
Features #
- 🔐 OAuth 2.1 PKCE by Default: Secure authorization flow (RFC 7636). Client secrets are never embedded in mobile code.
- 📱 Cross-Platform: Supports iOS, Android, and Web with deep link redirect callbacks.
- 🎨 Official Branded Widgets: Pre-styled
FricaSignInButtonwith AMOLED pure black (#000000) and Frica Gold (#FFCC00). - 🔄 Token Lifecycle: Built-in token exchange, automatic refresh token rotation, and in-memory or secure storage.
Installation #
Add frica_id_flutter to your pubspec.yaml:
dependencies:
frica_id_flutter: ^1.0.7
Then run:
flutter pub get
Platform Setup #
1. Android Configuration #
Open android/app/src/main/AndroidManifest.xml and add an <intent-filter> inside your <activity android:name=".MainActivity"> to capture the redirect URI callback:
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:exported="true">
<!-- Deep linking callback for Frica ID -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Scheme and host should match your Frica ID Developer Console redirect URI -->
<data android:scheme="myapp" android:host="oauth-callback" />
</intent-filter>
</activity>
2. iOS Configuration #
Open ios/Runner/Info.plist and register your custom URL scheme:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Quickstart #
Step 1: Initialize the FricaClient #
import 'package:flutter/material.dart';
import 'package:frica_id_flutter/frica_id_flutter.dart';
final fricaClient = FricaClient(
config: const FricaConfig(
clientId: 'fcli_my_mobile_app', // From https://frica.id/dashboard/developer
redirectUri: 'myapp://oauth-callback',
defaultScope: 'openid profile email phone',
),
);
Step 2: Add the FricaSignInButton #
import 'package:flutter/material.dart';
import 'package:frica_id_flutter/frica_id_flutter.dart';
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Dark AMOLED Theme (Default)
FricaSignInButton(
client: fricaClient,
theme: FricaButtonTheme.dark,
size: FricaButtonSize.large,
onError: (err) => print('Login error: $err'),
),
const SizedBox(height: 12),
// Gold Theme
FricaSignInButton(
client: fricaClient,
theme: FricaButtonTheme.gold,
size: FricaButtonSize.medium,
),
],
),
),
);
}
}
Step 3: Handle the Deep Link Callback #
Using standard Flutter app_links or uni_links:
import 'package:app_links/app_links.dart';
void listenToAuthCallbacks(FricaClient client) {
final appLinks = AppLinks();
appLinks.uriLinkStream.listen((uri) async {
if (uri.scheme == 'myapp' && uri.host == 'oauth-callback') {
try {
final tokens = await client.handleRedirectUri(uri);
final user = await client.getUserInfo();
print('Authenticated as ${user.name} (${user.email})');
} catch (e) {
print('Failed to complete login: $e');
}
}
});
}
API Reference #
FricaClient Methods #
| Method | Returns | Description |
|---|---|---|
signIn() |
Future<bool> |
Opens the Frica ID authorization page in system browser |
handleRedirectUri(Uri uri) |
Future<FricaTokenResponse> |
Exchanges authorization code for access and refresh tokens |
getUserInfo() |
Future<FricaUserInfo> |
Retrieves the authenticated user profile |
getValidAccessToken() |
Future<String?> |
Returns a valid access token, auto-refreshing if expired |
refreshToken() |
Future<FricaTokenResponse> |
Refreshes the session using the refresh token |
signOut() |
Future<void> |
Revokes tokens and clears session storage |
isAuthenticated() |
Future<bool> |
Checks if an active session exists |
launchKycVerification(String url) |
Future<bool> |
Launches the hosted KYC verification portal in system browser |
createKycSession(...) |
Future<FricaKycSession> |
Initiates a hosted developer KYC verification session |
getKycVerification(String id) |
Future<FricaKycVerification> |
Retrieves KYC verification result and verified claims |
instantKycCheck(...) |
Future<FricaInstantCheckResult> |
Runs instant identity check against official registries (BVN, NIN) |
getDeveloperWallet(...) |
Future<FricaWallet> |
Queries developer organization token wallet and remaining KYC checks |
topupDeveloperWallet(...) |
Future<Map<String, dynamic>> |
Tops up organization tokens via Card, Mobile Money, Crypto, or Sandbox |
getUserWallet(...) |
Future<FricaWallet> |
Retrieves user sovereign token wallet |
topupUserWallet(...) |
Future<Map<String, dynamic>> |
Tops up user tokens with bonus token support |
payServiceWithTokens(...) |
Future<Map<String, dynamic>> |
Pays for subscription upgrades (Pro, Pro+, Business) with tokens |
verifyDigitalPassport(String id) |
Future<FricaPassportVerificationResult> |
Verifies public authenticity of digital passport QR codes |
KYC & Identity Verification #
Frica ID supports tiered KYC identity verification (TIER_1, TIER_2, TIER_3) across African identity authorities.
Requesting KYC Claims #
Configure defaultScope or request kyc.status and kyc.identity during sign-in:
final fricaClient = FricaClient(
config: FricaConfig(
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'myapp://oauth-callback',
defaultScope: 'openid profile email kyc.status kyc.identity',
),
);
final user = await fricaClient.getUserInfo();
print('KYC Status: ${user.kycStatus}'); // 'APPROVED', 'UNDER_REVIEW', 'PENDING'
print('KYC Tier: ${user.kycTier}'); // 'TIER_2'
print('Is Approved: ${user.isKycApproved}'); // true
print('Legal Name: ${user.kycLegalFirstName} ${user.kycLegalLastName}');
print('Nationality: ${user.kycNationality}');
Launching Hosted Verification #
// Launch hosted KYC verification flow
await fricaClient.launchKycVerification(session.hostedUrl);
Sovereign Wallet & Token Management (FRICA) #
Commercial KYC verifications cost 0.45 FRICA tokens ($0.45 USD). Developers can monitor verification runway and top up balances directly in Flutter apps:
// Check remaining KYC verification runway
final wallet = await fricaClient.getDeveloperWallet(apiKey: 'YOUR_API_KEY');
print('Available Balance: ${wallet.availableBalance} FRICA');
print('Remaining KYC Checks: ${wallet.remainingKycChecks}');
// Top up tokens via Mobile Money (M-Pesa, MTN MoMo)
await fricaClient.topupDeveloperWallet(
amountUsd: 100.0,
paymentMethod: 'MOBILE_MONEY',
mobileMoneyProvider: 'MPESA',
phoneNumber: '+254712345678',
apiKey: 'YOUR_API_KEY',
);
Digital Passport Authenticity Verification #
// Publicly verify scanned QR codes or passport identifiers
final result = await fricaClient.verifyDigitalPassport('FRICA-PASSPORT-KWAME-001');
if (result.verified) {
print('Verified Citizen: ${result.fullName} (${result.country})');
}
License #
Apache-2.0 © Frica ID Team