Skip to main content

frica_id_flutter 1.2.0 copy "frica_id_flutter: ^1.2.0" to clipboard
frica_id_flutter: ^1.2.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.

pub package License


Public Frica ID #

With the profile scope, the user profile exposes an optional publicId, such as FID-7K9MX4QP2N8C. Use it for public account labels. Continue using the opaque sub to match authenticated accounts; its format must not be assumed. Profiles from older servers or without the claim remain supported.

final user = await client.getUserInfo();
print(user.publicId ?? user.name);

The OAuth token endpoint's HTTP 200 response and compact picture URL already work with the SDK. Avatar images are fetched using the returned URL rather than embedded in ID tokens.

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 FricaSignInButton with 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,
            ),
          ],
        ),
      ),
    );
  }
}

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

Release automation #

Bump the package version and update the changelog in a pull request. After a merge to main, passing CI creates an immutable v<version> tag and dispatches the existing publish workflow from that tag. Published versions are skipped; existing tags are never moved. Publishing uses the registry's existing OIDC trusted-publishing configuration, without a long-lived package token.

For pub.dev, enable Publishing from GitHub Actions → workflow_dispatch alongside tag pushes in the package's Admin settings. The dispatched workflow must run on the version tag. Failed publishing runs can be retried from GitHub Actions; do not change an existing release tag.

2
likes
160
points
898
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Official Flutter SDK for Sign in with Frica ID. OAuth 2.1 PKCE authorization, user management, and seamless authentication for iOS, Android, and Web.

Homepage
Repository (GitHub)
View/report issues

License

Apache-2.0 (license)

Dependencies

crypto, flutter, http, url_launcher

More

Packages that depend on frica_id_flutter