Skip to content

Technology

Sergio Hernandez edited this page Jul 12, 2026 · 8 revisions

Technology

TrackHub ensures secure and seamless integration across its ecosystem by implementing the Authorization Code Flow with Proof Key for Code Exchange (PKCE) via OpenIddict as the authorization method for both frontend and backend services. Built with React.js, the frontend delivers a responsive user experience, while the backend services leverage GraphQL (via HotChocolate) and REST Minimal APIs to address specific integration needs.


Technology Stack

graph TB
    subgraph Frontend["Frontend Layer"]
        react["React.js 18+"]
        mui["Material UI (MUI)"]
        maps["Leaflet / Google Maps"]
        apollo["GraphQL Client"]
    end

    subgraph Auth["Authentication"]
        pkce["OAuth 2.0 + PKCE"]
        oiddict["OpenIddict 4.x"]
        jwt["JWT Bearer Tokens"]
    end

    subgraph Backend["Backend Services"]
        dotnet[".NET 10"]
        hc["HotChocolate (GraphQL)"]
        minapi["Minimal APIs (REST)"]
        cqrs["Custom CQRS Mediator"]
        fv["FluentValidation"]
    end

    subgraph Data["Data Layer"]
        pg["PostgreSQL 14+"]
        postgis["PostGIS Extension"]
        ef["Entity Framework Core"]
    end

    subgraph Infra["Infrastructure"]
        docker["Docker + Compose"]
        nginx["Nginx Reverse Proxy"]
        polly["Polly (Resilience)"]
    end

    react --> apollo --> hc
    react --> pkce --> oiddict
    oiddict --> jwt --> hc & minapi
    hc --> cqrs --> ef --> pg
    minapi --> cqrs
    pg --- postgis
Loading

Authentication Flow (PKCE)

TrackHub uses the Authorization Code Flow with PKCE for all public clients (web and mobile). This eliminates the need to store client secrets in the browser while maintaining security through a cryptographic code verifier.

sequenceDiagram
    participant User as User (Browser)
    participant App as TrackHub Web<br/>(React)
    participant Auth as AuthorityServer<br/>(OpenIddict)
    participant API as Backend Services

    Note over App: Generate code_verifier (random)<br/>Compute code_challenge = SHA256(code_verifier)

    App->>Auth: GET /Identity/authorize<br/>response_type=code<br/>client_id=web_client<br/>code_challenge=...<br/>code_challenge_method=S256<br/>scope=web_scope<br/>redirect_uri=.../callback

    Auth->>User: Login Page
    User->>Auth: Username + Password

    Auth-->>App: 302 Redirect → /callback?code=AUTH_CODE

    App->>Auth: POST /Identity/token<br/>grant_type=authorization_code<br/>code=AUTH_CODE<br/>code_verifier=ORIGINAL_VERIFIER<br/>redirect_uri=.../callback

    Note over Auth: Verify: SHA256(code_verifier) == code_challenge

    Auth-->>App: { access_token, refresh_token, expires_in }

    App->>API: GraphQL Request<br/>Authorization: Bearer {access_token}
    API->>Auth: Validate JWT Signature + Audience
    API-->>App: Response Data

    Note over App: When token expires...

    App->>Auth: POST /Identity/token<br/>grant_type=refresh_token<br/>refresh_token=...
    Auth-->>App: { new_access_token, new_refresh_token }
Loading

OAuth Clients

Client Type Scope Usage
web_client Public web_scope Web browser application
mobile_client Public mobile_scope Mobile application
sync_worker_client Confidential service_scope Backend service-to-service

Key Endpoints

Endpoint Purpose
/Identity/authorize Start authorization flow
/Identity/token Exchange code for tokens / refresh tokens
/Identity/revoke Revoke a token
/Identity/logout End session
/Identity/.well-known/openid-configuration OIDC discovery metadata

Frontend Architecture

graph TB
    subgraph App["TrackHub Web (React)"]
        router["React Router"]
        auth_mod["OAuth Module<br/><i>PKCE + Token Refresh Mutex</i>"]

        subgraph Pages["Pages"]
            dash["Dashboard<br/><i>Live Map + Positions</i>"]
            reports["Reports<br/><i>Excel Export</i>"]
            geofence["Geofence Manager<br/><i>Draw + Monitor</i>"]
            admin["Administration<br/><i>Users, Groups, Operators</i>"]
            profile["Profile<br/><i>Settings</i>"]
        end

        subgraph Services["API Services"]
            gql_client["GraphQL Client<br/><i>Manager, Security,<br/>Router, Geofencing</i>"]
            rest_client["REST Client<br/><i>Reporting</i>"]
        end
    end

    router --> Pages
    Pages --> Services
    auth_mod -->|Bearer Token| Services

    gql_client -->|"GraphQL over HTTPS"| backend["Backend Services"]
    rest_client -->|"REST over HTTPS"| reporting["Reporting API"]
Loading

Frontend Security Hardening

  • Token refresh mutex — Prevents race conditions during concurrent token refresh
  • GraphQL injection prevention — Input sanitization via formatValue
  • Error Boundary — React component-level error handling
  • Notification system — MUI Snackbar replaces raw alert() calls
  • Security headersX-Content-Type-Options, X-Frame-Options
  • Request timeout — 30-second Axios timeout on all requests

Backend Architecture (Clean Architecture + CQRS)

Each backend service follows Clean Architecture with four layers:

graph LR
    subgraph Layers["Dependency Direction →"]
        web["Web<br/><i>Endpoints</i>"]
        app["Application<br/><i>Commands / Queries</i>"]
        domain["Domain<br/><i>Entities / Interfaces</i>"]
        infra["Infrastructure<br/><i>DB / External APIs</i>"]
    end

    web --> app --> domain
    infra --> domain

    subgraph Pipeline["CQRS Mediator Pipeline"]
        direction TB
        b1["1. Logging"]
        b2["2. Validation<br/><i>FluentValidation</i>"]
        b3["3. Authorization<br/><i>[Authorize] attribute</i>"]
        b4["4. Caching<br/><i>[Caching] attribute</i>"]
        b5["5. Rate Limiting<br/><i>[RateLimiting] attribute</i>"]
        b6["6. Handler Execution"]

        b1 --> b2 --> b3 --> b4 --> b5 --> b6
    end
Loading

Inter-Service Communication

All service-to-service calls use GraphQL with:

  • Polly resilience — Retry (3×, exponential backoff) + circuit breaker
  • Bearer token propagation — User context forwarded on downstream calls
  • 30-second timeout — Configurable per client
  • Client credentials flow — For background services (SyncWorker)

References

Clone this wiki locally