uflowid 2.0.0
uflowid: ^2.0.0 copied to clipboard
Flutter SDK for UFlow ID (id.uflow.uz) - email OTP, Cloud OAuth with API key/client_id, SSO across com.modder apps, black-white theme.
uflowid #
Flutter SDK for UFlow ID (id.uflow.uz) + UFlow Cloud (cloud.uflow.uz) — email OTP, OAuth with API key / client_id, SSO across com.modder.* apps, and black-white theme matching Next.js.
This is v2.0.0 - major update:
- Cloud OAuth: Get
client_id+apiKey (uf_live_...)from https://cloud.uflow.uz/dashboard, then OAuth flow - SSO: One UFlow account works across all
com.modder.*apps, plus optional device-local instant SSO viasharedUserId - Black-white theme: No more RGB gradients, only
UFlowTheme.light()/dark()matchingglobals.css(bg #f7f8fa light, #000000 dark, CTA blue)
Old package uflow_idflutter still works (same code), but uflowid is short name.
Install #
dependencies:
uflowid: ^2.0.0
import 'package:uflowid/uflowid.dart';
Quick start (Cloud OAuth + SSO) #
- Create app in Cloud Dashboard: https://cloud.uflow.uz/dashboard -> New App -> get
client_id(app id) and create API keyuf_live_... - Initialize in main():
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await UflowId.initialize(
supabaseUrl: 'https://YOUR-PROJECT.supabase.co',
supabaseAnonKey: 'YOUR-ANON-KEY',
cloudBaseUrl: 'https://cloud.uflow.uz',
apiBase: 'https://id.uflow.uz',
clientId: 'your-app-id-from-dashboard',
apiKey: 'uf_live_...', // confidential clients, or null for PKCE public clients
redirectUri: 'uz.uflow.widgets://oauth', // must match dashboard redirect_uris
);
// Try silent SSO from previous app
await UflowSSO.instance.trySilentSignIn();
runApp(MyApp());
}
- OAuth login:
// Start login - get authorize_url
final login = await UflowIdAuth.instance.startCloudLogin(
redirectUri: 'uz.uflow.widgets://oauth',
scopes: ['user:read'],
usePKCE: true, // mobile = true (no apiKey exposure)
);
// Open in browser
import 'package:url_launcher/url_launcher.dart';
await launchUrl(Uri.parse(login.authorizeUrl), mode: LaunchMode.externalApplication);
// In your deep link handler (app_links or uni_links):
// uz.uflow.widgets://oauth?code=AbC123&state=...
final tokens = await UflowIdAuth.instance.handleOAuthCallback(
callbackUrl: 'uz.uflow.widgets://oauth?code=AbC123...',
);
// tokens.accessToken is uf_at_... -> stored automatically
- Use Cloud APIs:
final me = await UflowCloud.instance.me(); // who is this token?
final user = await UflowCloud.instance.getUser(); // full profile
final active = await UflowIdSubscriptions.instance.isActive('widgets_full');
SSO among com.modder.* apps #
One account everywhere:
- Supabase
auth.usersis same table onuflow.uz,cloud.uflow.uz,id.uflow.uz-> signing in once, same user_id everywhere - Cloud grants stored server-side (
cloud_user_grants) -> if user authorizeduz.uflow.widgets, and later openscom.modder.otherapp, you can checkhasPreviousGrant() - Browser SSO:
cloud.uflow.uzuses cookie domain.uflow.uz, so session on cloud is valid on id. Mobile OAuth via system browser will be 1-tap if already signed in.
Device-local instant SSO (optional):
Add to all your com.modder.* apps' android/app/src/main/AndroidManifest.xml:
<manifest android:sharedUserId="uz.uflow.shared" ...>
And sign all with same keystore. Then tokens stored under uflow_access_token can be shared via native:
val ctx = createPackageContext("uz.uflow.widgets", 0)
val prefs = ctx.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE)
val token = prefs.getString("flutter.uflow_access_token", null)
Or use deep link export/import:
// App A (has token)
final link = await UflowSSO.instance.exportSSOLink(); // com.modder.sso://import?access_token=...
// Share via Intent to App B
// App B
await UflowSSO.instance.importSSOLink(link);
Email OTP (legacy, still works) #
await UflowIdAuth.instance.sendOtp('user@example.com');
await UflowIdAuth.instance.verifyOtp('user@example.com', '123456');
Theme - black-white like Next.js #
Old RGB gradient removed. New:
MaterialApp(
theme: UFlowTheme.light(),
darkTheme: UFlowTheme.dark(),
themeMode: ThemeMode.system, // follows .dark class like Next.js
home: MyPage(),
)
// Widgets:
UFlowCard(child: Text('card matching .card in globals.css'))
UFlowButton(label: 'Primary', onPressed: () {}, variant: UFlowButtonVariant.primary) // .btn-primary
UFlowButton(label: 'Ghost', variant: UFlowButtonVariant.ghost)
UFlowBadge(label: 'Active', variant: UFlowBadgeVariant.green)
Colors from cloud_uflow/app/globals.css:
- Light bg #f7f8fa, surface #ffffff, border #e3e6ec, text #1c1c1e, CTA #1544e0
- Dark bg #000000, surface #0a0a0c, border #26262b, text #ffffff, CTA #2f6bff
API Reference #
| Class | Description |
|---|---|
UflowId |
initialize(), isSignedIn, accessToken, clientId, apiKey, debugInfo |
UflowIdAuth |
sendOtp, verifyOtp, startCloudLogin, handleOAuthCallback, exchangeCode, signOut |
UflowCloud |
login, me, getUser, contact |
UflowOAuth |
exchangeCode, refresh, parseCallback, loadTokens, clearTokens |
UflowSSO |
isSignedIn, trySilentSignIn, exportSSOLink, importSSOLink, hasPreviousGrant, clear |
UflowIdSubscriptions |
isActive, get, activate |
Links #
- GitHub: https://github.com/modderboyy/uflowid
- Cloud Dashboard: https://cloud.uflow.uz/dashboard
- ID Web: https://id.uflow.uz
- Old package: https://pub.flutter-io.cn/packages/uflow_idflutter