OAuth-Plan – Step 1B Milestone

Failure & Edge Case Flow Documentation

1️⃣ Purpose of This Document

This document completes Step 1B of the OAuth-Plan. It describes how the authentication system behaves when things go wrong: popup issues, Google errors, CSRF problems, missing cookies, expired sessions, and 401 responses during normal usage.

The goal is to have a clear, stable “resilience spec”: for each scenario we define:

Step 1B is documentation-only. It does not necessarily mean everything is already implemented exactly like this, but it is the target behaviour specification that later phases will converge to.

2️⃣ Scope: Failure & Edge Case Scenarios

The following scenarios are considered in this milestone:

ID Scenario Where It Happens Primary Symptom
E1 Popup closed before login completes Browser / Frontend Promise rejection: "Popup closed"
E2 Google OAuth error (redirect_uri mismatch, consent error, etc.) Google → Flask callback Redirect to error page or JSON error from callback
E3 CSRF / state mismatch or missing cookie Flask callback {"error":"csrf_state_mismatch"} or similar
E4 Session cookie missing/blocked at /auth/me Browser / Flask /auth/me returns 401, user seen as logged out
E5 Session lost/expired while user is using the app Browser / Flask API starts returning 401 mid-session
E6 BroadcastChannel / popup success notification never received Browser Main window “waits” and user experiences confusion
E7 Internal auth exceptions (e.g. parsing id_token, network issues) Flask auth backend 5xx or structured error JSON

3️⃣ Scenario Specs (Per Error Case)

E1 – Popup Closed Before Login Completes

Frontend UX


E2 – Google OAuth Error (redirect_uri mismatch, consent errors, etc.)

Backend UX


E3 – CSRF / State Mismatch or Missing Cookie

Backend


E4 – Session Cookie Missing / Blocked at /auth/me

Frontend Backend


E5 – Session Lost / Expired While Using the App

Frontend Backend UX


E6 – BroadcastChannel / Popup Success Not Received

Frontend


E7 – Internal Auth Exceptions

Backend

4️⃣ Failure-Oriented Sequence Diagram (Mermaid Text)

Generic representation of a failed login attempt (covers E1/E2/E3/E7).

        sequenceDiagram
            participant U as User
            participant B as Browser (Main Window)
            participant P as Popup
            participant API as Flask Auth API
            participant G as Google OAuth

            U->>B: Click "Sign in"
            B->>API: GET /auth/login/google?popup=true
            API-->>G: Redirect to Google OAuth

            G-->>U: Show Google Login Page
            U->>G: Interact (login or cancel)

            alt User closes popup (E1)
                P--xB: <no auth:success>
                B-->>B: Promise reject("Popup closed")
                B-->>U: Stay logged out, show optional message
            else Google / config error (E2)
                G-->>API: Redirect with error
                API-->>P: JSON / error page (oauth_error)
                P--xB: <no auth:success>
                B-->>U: Stay logged out, optional "Sign-in failed" hint
            else CSRF / state mismatch (E3)
                G-->>API: Redirect with invalid/missing state
                API-->>P: 400 {"error":"csrf_state_mismatch"}
                P--xB: <no auth:success>
            else Internal error (E7)
                API->>API: Exception
                API-->>P: 500 {"error":"internal_error"}
                P--xB: <no auth:success>
            end

            Note over B: User remains unauthenticated
auth badge still shows "Sign in"
PlantUML Flow
Figure: Failure-Oriented Sequence Diagram

5️⃣ Session Loss & 401 Handling (Mermaid Text)

This diagram shows mid-session expiry (E5) when the user is already inside the app.

    sequenceDiagram
    participant U as User
    participant B as Browser App
    participant API as Flask API

    U->>B: Interacts with app (clicks "Refresh directories")
    B->>API: GET /api/video_server/get_directories (with cookie)
    API-->>B: 200 OK (authenticated)

    Note over B: Time passes, server restarts or session expires

    U->>B: Interacts again (refresh, analyze, etc.)
    B->>API: GET /api/video_server/get_directories (old cookie)
    API-->>B: 401 {"ok":false, "error":"not_authenticated"}

    B-->>B: Treat user as logged out
    B-->>U: Show banner "Session expired, please sign in again"
    B->>API: (optional) GET /auth/me
    API-->>B: 401 {"authenticated":false}
    
    
PlantUML Flow
Figure: PlantUML Popup Authentication Flow

6️⃣ PlantUML – Error Flow Variants

Consolidated PlantUML sequence that shows success vs error branches.

        @startuml
        title OAuth Login - Success vs Failure Variants

        actor User
        participant "Browser (Main Window)" as B
        participant "Popup Window" as P
        participant "Flask API" as API
        participant "Google OAuth" as G

        User -> B: Click "Sign in"
        B -> API: GET /auth/login/google?popup=true
        API -> G: Redirect to Google OAuth
        G -> User: Login / Consent Screen

        alt SUCCESS
        User -> G: Accept / login
        G -> API: Redirect with code
        API -> G: Exchange code -> token
        G -> API: Token + user info
        API -> API: Store session
        API -> P: Redirect /oauth-popup-complete.html
        P -> B: Broadcast auth:success
        B -> API: GET /auth/me
        API -> B: 200 authenticated
        B -> User: UI shows "Signed in"
        else POPUP CLOSED (E1)
        User -> P: Close window
        P -x B: <no auth:success>
        B -> B: Promise reject("Popup closed")
        B -> User: Stay logged out, optional info
        else OAUTH ERROR (E2)
        G -> API: Redirect with error
        API -> P: Show {"error":"oauth_error"}
        P -x B: <no auth:success>
        B -> User: "Sign-in failed"
        else CSRF / STATE MISMATCH (E3)
        G -> API: Redirect with invalid state
        API -> P: 400 {"error":"csrf_state_mismatch"}
        P -x B: <no auth:success>
        else INTERNAL ERROR (E7)
        API -> API: Exception
        API -> P: 500 {"error":"internal_error"}
        P -x B: <no auth:success>
        end

        @enduml
        
    
PlantUML Flow
Figure: OAuth Login - Success vs Failure Variants

7️⃣ Behaviour Invariants

To keep behaviour predictable and easy to reason about, the following invariants are defined:

8️⃣ Milestone Status

Step 1B of the OAuth-Plan is now documented.
All major failure and edge-case flows have:

Implementation can now be aligned with this spec, and deviations can be treated as bugs or future design changes.

Next milestone: Step 1C – Environment Split & Redirect-URI / Config Strategy.