Skip to main content

Authentication Guide

This guide explains how to work with authentication in the OpenCloud Mobile app.

Authentication Flow

The app uses OpenID Connect (OIDC) for authentication with OpenCloud servers:

  1. Server Connection: User enters the server URL
  2. WebFinger Discovery: Discovers OIDC provider capabilities
  3. OIDC Configuration: Retrieves authentication endpoints
  4. Authorization: Redirects to browser for login
  5. Token Exchange: Exchanges authorization code for tokens

Implementation Details

Server Connection

When a user enters a server URL, several checks are performed:

  • URL normalization (adding https:// if missing)
  • Security check for HTTP URLs
  • WebFinger discovery to verify OIDC support
// Example: Server URL handling
const { url: normalizedUrl, isInsecure } = AuthService.normalizeServerUrl(serverUrl);

// Handle insecure connection warning if needed
if (isInsecure) {
// Show warning and get user confirmation
}

// Initialize authentication
const { success } = await AuthService.initialize(normalizedUrl);

WebFinger and OIDC Discovery

The app uses WebFinger to discover the OpenID Connect provider:

// WebFingerService.discoverOidcIssuer
const webFingerResponse = await this.discover(serverUrl, resource);
const oidcLink = this.findLinkByRel(webFingerResponse, 'http://openid.net/specs/connect/1.0/issuer');

Then it fetches the OpenID configuration:

// OidcService.fetchConfiguration
const configUrl = `${baseUrl}/.well-known/openid-configuration`;
const response = await fetch(configUrl);
return await response.json();

Authentication Flow

The actual authentication happens through browser redirection:

// Get authorization URL
const authUrl = AuthService.getAuthorizationUrl();

// Open browser for authentication
await WebBrowser.openAuthSessionAsync(authUrl, authConfig.redirectUri);

After authentication, the app exchanges the authorization code for tokens:

// Exchange authorization code for tokens
const tokens = await AuthService.exchangeCodeForTokens(authCode);

Platform-Specific Configuration

The authentication system is configured for different platforms:

  • Client IDs:

    • iOS: OpenCloudIOS
    • Android: OpenCloudAndroid
  • Redirect URIs:

    • iOS: oc://ios.opencloud.eu
    • Android: oc://android.opencloud.eu

Implementing Custom Authentication

To customize the authentication flow:

  1. Update Configuration:

    // In config/app.config.ts
    auth: {
    clientId: 'your-client-id',
    redirectUri: 'your-custom-scheme://callback',
    defaultScopes: 'openid profile email',
    }
  2. Register URL Scheme:

    • Update iOS Info.plist and Android AndroidManifest.xml as described in the Configuration Guide
  3. Handle Authentication Callback:

    • Create a route handler for your redirect URI
    • Extract the authorization code from the URL
    • Exchange the code for tokens
  4. Store and Use Tokens:

    • Securely store the access and refresh tokens
    • Include the access token in API requests
    • Implement token refresh logic

Testing Authentication

Manual Testing

To test authentication during development:

  1. Use a real OpenCloud server with OIDC support
  2. Enter the server URL in the app
  3. Complete the authentication flow
  4. Check the logs for token information

Automated Testing

The project includes comprehensive unit tests for all authentication services with 100% code coverage:

  1. WebFingerService Tests:

    • Testing WebFinger discovery
    • Testing link retrieval
    • Testing OIDC issuer discovery
    • Testing error handling
  2. OidcService Tests:

    • Testing configuration fetching
    • Testing OIDC discovery
    • Testing authorization URL generation
    • Testing various parameter combinations
  3. AuthService Tests:

    • Testing URL normalization
    • Testing service initialization
    • Testing token exchange
    • Testing secure and insecure connections

To run the authentication tests:

npx jest "services/__tests__"

To run tests with coverage report:

npx jest "services/__tests__" --coverage

To run specific service tests:

npx jest "services/__tests__/WebFingerService-test.ts"
npx jest "services/__tests__/OidcService-test.ts"
npx jest "services/__tests__/AuthService-test.ts"

When writing your own components that use these services, you can mock them in your tests:

// Example: Mocking AuthService in a component test
jest.mock('../services/AuthService');
// Then in your test
(AuthService.initialize as jest.Mock).mockResolvedValue({ success: true });