Architecture Overview
This document provides an overview of the OpenCloud Mobile architecture, explaining the main components and how they interact with each other.
High-Level Architecture
OpenCloud Mobile follows a modern React Native architecture with Expo:
├── App (Root)
│ ├── Navigation (Expo Router)
│ ├── Screens
│ ├── Components
│ ├── Hooks
│ ├── Services
│ └── Utils
Core Principles
The architecture follows these core principles:
- Component-Based Design: UI is built using reusable components
- Separation of Concerns: Different aspects of the app are separated into logical modules
- TypeScript: Strong typing to ensure code quality and maintainability
- Hooks-Based Logic: Application logic is encapsulated in custom hooks
- Service-Based APIs: External communication is handled by dedicated services
Key Architectural Components
Navigation
The app uses Expo Router for file-based navigation, which provides:
- Automatic route generation based on file structure
- Deep linking support
- Type-safe navigation
State Management
State management is handled through:
- React Context for global state
- React Query for server state
- Local component state for UI-specific state
Data Flow
Data flows through the application in the following way:
- User Interaction: User interacts with UI components
- Component Handlers: Components call handlers in hooks or services
- Services: Services make API calls or update local state
- State Updates: Updated state flows back to components
Server Communication
Communication with the OpenCloud server is handled by a dedicated API service architecture:
HTTP Utilities and Standards
The app follows strict HTTP communication standards through a shared HttpUtil
class:
-
Standardized headers across all requests:
- User-Agent: Platform and version-specific (e.g.,
OpenCloudMobile/1.0.0 (ios)
) - X-Request-ID: UUID v4 for request correlation and tracing
- Content-Type and Accept headers based on request type
- User-Agent: Platform and version-specific (e.g.,
-
Secure redirect handling:
- Manual redirect handling (
redirect: 'manual'
) for all requests - No automatic redirect following for security and user control
- Explicit evaluation of redirect responses based on status codes
- Manual redirect handling (
-
Comprehensive logging:
- Request/response logging with configurable verbosity
- Request timing measurements
- Redacted sensitive information (tokens) in logs
- Debug curl command generation for troubleshooting
Service Structure
The API layer is organized into specialized services:
ApiService
: Core API communication with authorizationWebFingerService
: WebFinger discoveryOidcService
: OpenID Connect operationsAuthService
: Authentication coordination
Authentication Flow
The app uses OpenID Connect (OIDC) for authentication with the OpenCloud server:
-
Server Connection: User enters the server URL in the connection screen.
-
WebFinger Discovery:
- The app performs a WebFinger lookup to the
/.well-known/webfinger
endpoint. - It looks for the OpenID Connect issuer link with the relation
http://openid.net/specs/connect/1.0/issuer
.
- The app performs a WebFinger lookup to the
-
OIDC Configuration:
- The app retrieves the OpenID Connect configuration from
/.well-known/openid-configuration
. - This provides essential endpoints like authorization, token, and userinfo.
- The app retrieves the OpenID Connect configuration from
-
Authorization:
- The app constructs an authorization URL and opens it in a browser.
- The user logs in on the server's login page.
- After successful login, the server redirects back to the app with an authorization code.
-
Token Exchange:
- The app exchanges the authorization code for access and refresh tokens.
- These tokens are used for subsequent API calls.
This flow is implemented using dedicated services for WebFinger discovery, OIDC operations, and overall authentication coordination.
Configuration Architecture
The app uses a centralized configuration system designed for flexibility and white-labeling support:
-
Core Configuration Layer:
- Central configuration files in the
/config
directory - Type-safe configuration using TypeScript interfaces
- Platform-specific settings (different values for iOS vs Android)
- Central configuration files in the
-
Configuration Categories:
- Authentication: Client IDs, redirect URIs, scopes
- API: Timeouts, endpoints, retry strategies
- UI: Theme settings, feature flags
-
White-Labeling Support:
- Configuration designed to support multiple branded versions of the app
- Build-time configuration using environment variables or build arguments
- Client-specific overrides for visual elements and behavior
-
Platform-Specific Configuration:
- Different client IDs per platform (iOS:
OpenCloudIOS
, Android:OpenCloudAndroid
) - Platform-specific redirect URIs for authentication (iOS:
oc://ios.opencloud.eu
, Android:oc://android.opencloud.eu
) - Platform detection using React Native's
Platform
API - Conditional configuration based on runtime environment
- Different client IDs per platform (iOS:
Error Handling
The app implements a centralized error handling system that:
- Captures errors from various sources
- Formats errors for user display
- Logs errors for debugging
- Provides recovery mechanisms where possible
File Structure
The project follows this file structure:
opencloud-mobile/
├── app/ # Expo Router pages
├── components/ # Reusable UI components
├── hooks/ # Custom React hooks
├── services/ # API and business logic services
├── utils/ # Helper functions and utilities
├── types/ # TypeScript type definitions
└── assets/ # Static assets like images
Dependency Diagram
Key dependencies between components:
Screens → Components → Hooks → Services → API
↓ ↓ ↓ ↓
Utils ──────────────────────────┘
Technology Stack
- React Native: Cross-platform mobile framework
- Expo: Development framework and tooling
- TypeScript: Programming language
- Expo Router: Navigation
- React Query: Data fetching and caching
- Jest: Testing framework