Skip to content

Authentication Flow

sequenceDiagram
    participant User as User<br/>iOS Device
    participant Keychain as iOS Keychain
    participant Server as Signaling Server
    participant EmailSMS as Email/SMS Provider

    Note over User,Server: AUTHENTICATION & E2EE KEY REGISTRATION

    Note over User,Server: This diagram shows the initial setup process for ECALL<br/>including authentication and RSA key pair generation<br/><br/>📝 This flow applies to ALL users<br/>(User A, User B, User C, etc.)

    Note over User: STANDARD REGISTRATION FLOW

    User->>User: Install ECALL App
    User->>User: Launch app for first time

    Note over User: STEP 1: RSA KEY GENERATION

    User->>User: RSAKeyService.generateRSAKeyPair()<br/>Algorithm: RSA-2048<br/>Using SecKeyCreateRandomKey
    Note right of User: Generates cryptographically<br/>secure keypair

    User->>Keychain: Store Public Key<br/>(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)
    User->>Keychain: Store Private Key<br/>(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)
    Note right of User: 🔒 Private key NEVER<br/>leaves device<br/>Stored in iOS Keychain

    User->>Keychain: Store Device Info:<br/>deviceName, systemName,<br/>systemVersion, identifier
    User->>Keychain: Store APNs Token & VoIP Token
    Note right of User: For push notifications

    Note over User: STEP 2: USER INPUT

    User->>User: User enters:<br/>• Email OR Phone Number<br/>• Display Name

    Note over User: STEP 3: LOGIN REQUEST

    User->>Server: POST /login<br/>{<br/>  email: "user@example.com",<br/>  phoneNumber: "+1234567890",<br/>  displayName: "Alice",<br/>  publicKey: "Base64EncodedPublicKey",<br/>  voipToken: "...",<br/>  apnsToken: "...",<br/>  deviceName: "Alice's iPhone",<br/>  systemName: "iOS",<br/>  systemVersion: "17.0",<br/>  identifier: "iPhone15,2",<br/>  verified: false<br/>}
    Note over Server: Server validates request

    Server->>Server: Check if user exists<br/>(by email or phone)

    alt User exists
        Server->>Server: Load existing user
    else New user
        Server->>Server: Create new user record
    end

    Server->>Server: Generate 6-digit OTP code

    alt Email provided
        Server->>EmailSMS: Send OTP via Email<br/>Subject: "Your ECALL verification code"
        EmailSMS-->>User: Email with OTP code
    else Phone provided
        Server->>EmailSMS: Send OTP via SMS (Twilio)<br/>Message: "Your ECALL code: 123456"
        EmailSMS-->>User: SMS with OTP code
    end

    Server-->>User: HTTP 200 OK<br/>{<br/>  userId: 12345,<br/>  displayName: "Alice",<br/>  email: "user@example.com",<br/>  phoneNumber: "+1234567890"<br/>}
    Note right of User: No accessToken yet<br/>(not verified)

    Note over User: STEP 4: OTP VERIFICATION

    User->>User: User receives OTP<br/>(via Email or SMS)
    User->>User: User enters 6-digit OTP code

    User->>Server: POST /verify-login<br/>{<br/>  code: "123456",<br/>  email: "user@example.com",<br/>  phoneNumber: "+1234567890",<br/>  publicKey: "Base64EncodedPublicKey",<br/>  voipToken: "...",<br/>  apnsToken: "...",<br/>  deviceName: "Alice's iPhone",<br/>  systemName: "iOS",<br/>  systemVersion: "17.0",<br/>  identifier: "iPhone15,2"<br/>}

    Server->>Server: Verify OTP code<br/>(check code validity & expiration)

    alt OTP Invalid
        Server-->>User: HTTP 400 Bad Request<br/>{error: "Invalid or expired code"}
        User->>User: Show error message<br/>"Invalid code, please try again"
    else OTP Valid
        Server->>Server: Mark user as verified

        Note over Server: DEVICE REGISTRATION

        Server->>Server: RegisterDevice()<br/>Create or update device record:<br/>• userId<br/>• publicKey (Base64)<br/>• publicKeyHash (SHA-256)<br/>• voipToken<br/>• apnsToken<br/>• deviceInfo<br/>• IP address<br/>• Location (from IP)

        Note over Server: Generate Access Token + Refresh Token

        Server->>Server: Generate Access Token<br/>Claims: {<br/>  userId: 12345,<br/>  deviceId: 67890,<br/>  type: "access",<br/>  exp: timestamp + 15 minutes<br/>}<br/>Signed with JWT_SECRET_KEY

        Server->>Server: Generate Refresh Token<br/>Claims: {<br/>  userId: 12345,<br/>  deviceId: 67890,<br/>  type: "refresh",<br/>  exp: timestamp + 30 days<br/>}<br/>Signed with JWT_SECRET_KEY

        Server-->>User: HTTP 200 OK<br/>{<br/>  "accessToken": "eyJhbGciOiJIUzI1NiIs...",<br/>  "refreshToken": "eyJhbGciOiJIUzI1NiIs...",<br/>  "expiresIn": 900,<br/>  "refreshExpiresIn": 2592000,<br/>  "userId": 12345,<br/>  "deviceId": 67890<br/>}
        Note right of User: Access Token: 15 min<br/>Refresh Token: 30 days
    end

    Note over User: STEP 5: SAVE CREDENTIALS

    User->>Keychain: KeyStorage.storeUserInfosInKeychain()<br/>Save to Keychain:<br/>• userId: "12345"<br/>• displayName: "Alice"<br/>• email: "user@example.com"<br/>• phoneNumber: "+1234567890"<br/>• accessToken: "eyJhbG..."<br/>• refreshToken: "eyJhbG..."<br/>• tokenExpiry: timestamp<br/>• refreshTokenExpiry: timestamp<br/>• deviceId: "67890"<br/>• publicKey: "Base64..."<br/>• privateKey: "Base64..."<br/>• publicKeyHash: "SHA256..."

    Note right of User: All credentials secured<br/>in iOS Keychain

    User->>User: Navigate to Main App

    Note over User: ✅ USER AUTHENTICATED<br/>✅ E2EE KEYS REGISTERED<br/>✅ DEVICE REGISTERED

    Note over User,Server: 📝 Every user (User A, User B, User C, etc.)<br/>follows this same registration flow

    Note over User,Server: ALTERNATIVE AUTHENTICATION METHODS

    Note over User,Server: 🍎 APPLE SIGN-IN

    participant Apple as Apple ID Server

    User->>User: Tap "Sign in with Apple"
    User->>Apple: Apple Sign-In Request
    Apple-->>User: Authorization Code + ID Token

    User->>Server: POST /apple-login<br/>{<br/>  code: "apple_auth_code",<br/>  appleIdToken: "id_token",<br/>  displayName: "Alice",<br/>  publicKey: "Base64...",<br/>  deviceInfo: {...}<br/>}

    Server->>Apple: Verify authorization code<br/>Exchange for access token
    Apple-->>Server: User info + Apple Subject ID

    Server->>Server: Create/Find user by appleSubId
    Server->>Server: Register Device
    Server->>Server: Generate Access Token + Refresh Token
    Note over Server: Apple Sign-In is pre-verified<br/>No OTP needed

    Server-->>User: HTTP 200 OK<br/>{<br/>  "userId": 12345,<br/>  "deviceId": 67890,<br/>  "displayName": "Alice",<br/>  "email": "user@example.com",<br/>  "appleSubId": "001234.abc...",<br/>  "accessToken": "eyJhbG...",<br/>  "refreshToken": "eyJhbG...",<br/>  "expiresIn": 900,<br/>  "refreshExpiresIn": 2592000<br/>}

    User->>Keychain: Save credentials + appleLoginFlag
    Note over User: ✅ Apple Sign-In Complete

    Note over User,Server: 🔵 GOOGLE SIGN-IN

    participant Google as Google OAuth

    User->>User: Tap "Sign in with Google"
    User->>Google: Google Sign-In Request<br/>(OAuth 2.0)
    Google-->>User: User profile + Access Token

    User->>User: Extract email and displayName<br/>from Google profile

    User->>Server: POST /login<br/>{<br/>  email: "from Google",<br/>  displayName: "from Google",<br/>  publicKey: "Base64...",<br/>  verified: true,<br/>  deviceInfo: {...}<br/>}
    Note over Server: verified=true for Google<br/>(email already verified by Google)

    Server->>Server: Create/Find user by email
    Server->>Server: Register Device
    Server->>Server: Generate Access Token + Refresh Token
    Note over Server: No OTP needed<br/>(pre-verified by Google)

    Server-->>User: HTTP 200 OK<br/>{<br/>  "userId": 12345,<br/>  "deviceId": 67890,<br/>  "displayName": "Alice",<br/>  "email": "user@example.com",<br/>  "accessToken": "eyJhbG...",<br/>  "refreshToken": "eyJhbG...",<br/>  "expiresIn": 900,<br/>  "refreshExpiresIn": 2592000<br/>}

    User->>Keychain: Save credentials
    Note over User: ✅ Google Sign-In Complete

    Note over User,Server: SECURITY FEATURES

    Note over User,Server: 🔐 KEY STORAGE<br/>• iOS Keychain with kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly<br/>• Private keys never transmitted to server<br/>• Public keys stored on server for E2EE key exchange<br/>• SHA-256 hash of public key for device identification

    Note over User,Server: 🔑 AUTHENTICATION<br/>• Access Token: 15 minutes (short-lived)<br/>• Refresh Token: 30 days (long-lived)<br/>• Rolling refresh: Extends 30-day window on each refresh<br/>• Standard HTTP 401 + error codes for auth failures<br/>• OTP codes expire after 10 minutes<br/>• Rate limiting on OTP requests<br/>• Device-based authentication (multi-device support)<br/>• Unique deviceId per installation<br/>• See e2ee_02_token_refresh_flow.mermaid for details

    Note over User,Server: 📱 DEVICE MANAGEMENT<br/>• Each device gets unique RSA keypair<br/>• Multiple devices per user supported<br/>• Device info tracked: name, OS, version, location<br/>• Push tokens (VoIP + APNs) registered per device

    Note over User,Server: 🔄 RE-AUTHENTICATION<br/>• Users can login on new devices<br/>• Each device generates its own RSA keypair<br/>• Server maintains public keys for all user devices<br/>• Format: "userId_deviceId" for multi-device E2EE

    Note over User,Server: RELATED DIAGRAMS

    Note over User,Server: 📝 Token Refresh & Management<br/>→ e2ee_02_token_refresh_flow.mermaid

    Note over User,Server: 📝 1-to-1 Calls<br/>→ e2ee_03_1to1_call_flow.mermaid

    Note over User,Server: 📝 Group Calls (3+ participants)<br/>→ e2ee_04_group_call_flow.mermaid