bapp_auth 0.1.5 copy "bapp_auth: ^0.1.5" to clipboard
bapp_auth: ^0.1.5 copied to clipboard

Cross-platform OAuth package for Bapp authentication with Keycloak integration and API client

Bapp Auth #

A cross-platform Flutter package for Bapp authentication with Keycloak integration. Supports SSO OpenID Connect flow, device authentication flow, and provides a comprehensive API client for Bapp Framework.

Features #

  • Keycloak OAuth Integration

    • SSO OpenID Connect flow with PKCE
    • Device authentication flow
    • Token refresh and management
    • Token persistence with SharedPreferences
  • API Client

    • Configurable base URL
    • Token and Bearer authentication
    • Multi-tenancy support
    • Automatic retry with exponential backoff
    • Comprehensive CRUD operations
    • Task, Action, and Widget APIs
    • Pagination support
    • Error handling

Installation #

Add this to your package's pubspec.yaml file:

dependencies:
  bapp_auth:
    git:
      url: https://git.pidginhost.net/bapp-cloud/packages/flutter-bapp-auth.git

Or for local development:

dependencies:
  bapp_auth:
    path: ../path/to/bapp-auth

Platform Support #

This package supports all Flutter platforms:

  • Android - Custom URL scheme deep links
  • iOS - Custom URL scheme deep links
  • macOS - Custom URL scheme deep links
  • Web - Origin-based redirects
  • Windows - Localhost redirects
  • Linux - Localhost redirects

Platform-Specific Configuration #

Each platform requires specific configuration for OAuth redirects. The package includes a PlatformConfig helper that automatically detects your platform and provides the correct redirect URI.

Quick Setup:

import 'package:bapp_auth/bapp_auth.dart';

// Automatically get the correct redirect URI for current platform
final redirectUri = PlatformConfig.getRedirectUri();

final token = await auth.authenticateWithSSO(
  redirectUri: redirectUri,
);

For detailed platform-specific configuration instructions, see:

  • 📖 Complete Platform Configuration Guide

Quick Links:

  • Android Configuration
  • iOS Configuration
  • macOS Configuration
  • Web Configuration
  • Windows Configuration
  • Linux Configuration
  • Keycloak Setup

Usage #

Authentication #

SSO OpenID Connect Flow (with Browser Session Reuse!)

The package uses the system browser for authentication, which means:

  • If the user is already logged in to Keycloak in their browser, they won't need to log in again!
  • ✅ Browser cookies and sessions are shared automatically
  • ✅ Seamless single sign-on experience across apps
  • ✅ Users get a familiar, trusted browser experience
import 'package:bapp_auth/bapp_auth.dart';

final auth = KeycloakAuth(
  hostname: 'id.bapp.ro',
  realm: 'bapp',
  clientId: 'your-client-id',
);

try {
  // Use automatic platform detection for redirect URI
  final redirectUri = PlatformConfig.getRedirectUri();

  // If user is logged in to Keycloak in browser → Instant auth, no login needed!
  final token = await auth.authenticateWithSSO(
    redirectUri: redirectUri,
    // preferEphemeral: false (default) - Reuses browser session
    // preferEphemeral: true - Forces fresh login (private mode)
  );

  // Save token for later use
  await auth.saveToken(token);

  print('Access Token: ${token.accessToken}');
} catch (e) {
  print('Authentication failed: $e');
}

Want to force a fresh login?

final token = await auth.authenticateWithSSO(
  redirectUri: redirectUri,
  preferEphemeral: true, // Private mode - won't use existing session
);

📖 Read the complete SSO Session Management Guide to learn:

  • How browser session reuse works on each platform
  • When to use private mode vs. persistent sessions
  • Testing SSO session behavior
  • Best practices for session management

Device Authentication Flow

final token = await auth.authenticateWithDevice(
  onUserAction: (userCode, verificationUri) {
    print('Go to $verificationUri and enter code: $userCode');
  },
  onStatusUpdate: (status) {
    print('Status: $status');
  },
);

await auth.saveToken(token);

Token Refresh

if (token.isExpiringSoon && token.refreshToken != null) {
  final newToken = await auth.refreshToken(token.refreshToken!);
  await auth.saveToken(newToken);
}

API Client #

Basic Usage

final client = BappApiClient(
  baseUrl: 'https://panel.bapp.ro/api/',
  bearer: token.accessToken,
  app: 'erp',
);

// Call the "me" endpoint
final user = await client.me();
print('User: $user');

Using Fixed Token

final client = BappApiClient(
  baseUrl: 'https://panel.bapp.ro/api/',
  token: 'your-fixed-token',
  app: 'erp',
);

CRUD Operations

// List items
final items = await client.list('example.model', queryParams: {'page': '1'});

// Retrieve single item
final item = await client.retrieve('example.model', 'item-id');

// Create item
final newItem = await client.create('example.model', {
  'name': 'New Item',
  'description': 'Item description',
});

// Update item
final updated = await client.update('example.model', 'item-id', {
  'name': 'Updated Name',
});

// Patch item
final patched = await client.patchResource('example.model', 'item-id', {
  'description': 'New description',
});

// Delete item
await client.deleteResource('example.model', 'item-id');

Tasks API

// Get available tasks
final tasks = await client.getAvailableTasks();

// Get task options
final options = await client.getTaskOptions('task.code');

// Call task
final result = await client.callTask('task.code', data: {
  'param1': 'value1',
});

Actions API

// Get available actions
final actions = await client.getAvailableActions();

// Call action
final result = await client.callAction('action.code', data: {
  'param1': 'value1',
});

Widgets API

// Get available widgets
final widgets = await client.getAvailableWidgets();

// Call widget
final result = await client.callWidget('widget.code', data: {
  'param1': 'value1',
});

Pagination

// Stream all pages
await for (final page in client.listPages('example.model')) {
  print('Page: ${page['results']}');
}

// Stream individual items
await for (final item in client.iterResults('example.model', limit: 100)) {
  print('Item: $item');
}

// Get all items at once
final (items, totalCount) = await client.listAll('example.model');
print('Total items: $totalCount');

Multi-tenancy

// Set tenant globally
client.setTenant('tenant-id');

// Use tenant context for specific calls
await client.withTenant('tenant-id', () async {
  return await client.list('example.model');
});

Example #

See the example directory for a complete example app demonstrating both authentication flows and API client usage.

License #

MIT License

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

1
likes
0
points
66
downloads

Publisher

verified publishercbsoft.ro

Weekly Downloads

Cross-platform OAuth package for Bapp authentication with Keycloak integration and API client

Homepage

License

unknown (license)

Dependencies

crypto, flutter, flutter_web_auth_2, http, shared_preferences, url_launcher

More

Packages that depend on bapp_auth