Skip to content

Current Architecture Context diagram#

flowchart TB
    user(user)

    user--personal data-->bff

    subgraph external [Internet]
        direction LR
        entraId[Entra ID]
        bff((Frontdoor\nBFF))
        react((React\nWeb UI))

        bff-->react
        react-.api calls.->bff
    end

    subgraph dmz [Internal Network]
        direction LR
        ldb[|borders:tb|legacy db]
        servers((Servers API))

        bff--api routes-->api
        db<-->api
        api-.->legacy-api
        api-.->entraId
        api-->mediation

        subgraph cc-api [CommandCenter API]
            direction LR
            db[|borders:tb|database]
            api((CommandCenter\nAPI))
        end

        subgraph legacy-api [Legacy CC]
            direction LR
            legacy((Legacy API))
            legacy-service((CC Service))

            bff--legacy api routes-->legacy
            legacy<-->ldb
            legacy-service<-->ldb
        end
        subgraph mediation [Mediation Layer]
            direction LR
            servers-.->ldb
        end
        subgraph benefit [BenefitManager]
            direction LR
            db-customer[|borders:tb|customer db]
            bm-service((BenefitManager\nService))
            bm-app((BenefitManager\nWeb))
            api -- "`versioned req/res`" --> bm-app
            bm-service <--> db-customer
            bm-app <--> db-customer
        end
    end

%% Element type definitions

    classDef boundary fill:none
    dmz:::boundary
    external:::boundary
    classDef apis stroke-dasharray: 5 5
    legacy-api:::apis
    mediation:::apis
    cc-api:::apis
    benefit:::apis
Press "Alt" / "Option" to enable Pan & Zoom

Authentication and Authorization#

Overview Participant#

  • BFF (YARP + ASP.NET Core)
  • AzureEntraID as Entra ID
  • API 1 (ASP.NET Core)
  • API 2 (ASP.NET Core)
sequenceDiagram
    participant SPA
    participant Browser
    participant BFF
    participant Entra ID
    participant API 1
    participant API 2

    Note over SPA, BFF: Initial Page Load (User Not Authenticated)
    SPA->>Browser: Load application
    Browser->>SPA: Renders UI (e.g., shows Login button)

    Note over SPA, BFF: User Initiates Login
    SPA->>Browser: User clicks Login
    Browser->>BFF: GET /login (or similar auth trigger endpoint)

    Note over BFF, Entra ID: BFF Initiates Auth Code Flow
    BFF->>Browser: Redirect (302) to Entra ID /authorize endpoint (with client_id, redirect_uri, scope, code_challenge, state)
    Browser->>Entra ID: GET /authorize endpoint
    Entra ID->>Browser: Shows Login Page (if not already signed in)
    Browser->>Entra ID: User enters credentials
    Entra ID->>Browser: User authenticates, grants consent (if needed)
    Entra ID->>Browser: Redirect (302) back to BFF /signin-oidc (with authorization_code, state)

    Note over BFF, Entra ID: BFF Exchanges Code for Tokens
    Browser->>BFF: GET /signin-oidc (Callback)
    BFF->>BFF: Validates state
    BFF->>Entra ID: POST /token endpoint (with client_id, client_secret, code, code_verifier, redirect_uri)
    Entra ID-->>BFF: Returns ID Token, Access Token (for BFF), Refresh Token
    BFF->>BFF: Validates tokens, Creates session (e.g., cookie) for the user
    BFF->>Browser: Redirect (302) back to SPA (e.g., '/') with session cookie set (HttpOnly, Secure)
    Browser->>SPA: Follows redirect, now has session cookie

    Note over SPA, BFF: Authenticated SPA Call
    SPA->>Browser: Makes API call (e.g., fetch('/api/proxy/resource1'))
    Browser->>BFF: GET /api/proxy/resource1 (includes session cookie)
    BFF->>BFF: Validates session cookie, identifies user

    Note over BFF, API 1: BFF Calls Downstream API 1 (On-Behalf-Of User)
    BFF->>BFF: Needs to call API 1
    BFF->>Entra ID: POST /token endpoint (OBO Flow - grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, client_id, client_secret, assertion=<User's Access Token for BFF>, requested_token_use=on_behalf_of, scope=<API 1 Scope>)
    Entra ID-->>BFF: Returns new Access Token scoped for API 1 (representing the original user)
    BFF->>API 1: GET /resource (includes 'Authorization: Bearer <API 1 Access Token>')

    Note over API 1: API 1 Validates Token & Authorizes
    API 1->>API 1: Receives request, validates Bearer token (signature, issuer, audience=API 1, expiry, scopes/roles)
    API 1->>API 1: Checks authorization policies (e.g., user has required scope 'Resource1.Read')
    API 1-->>BFF: Returns resource data (e.g., 200 OK with JSON)

    Note over BFF, API 2: (Similar OBO flow if calling API 2)
    BFF->>BFF: Needs to call API 2
    BFF->>Entra ID: POST /token endpoint (OBO Flow - requesting token for API 2 scope)
    Entra ID-->>BFF: Returns new Access Token scoped for API 2
    BFF->>API 2: GET /other-resource (includes 'Authorization: Bearer <API 2 Access Token>')
    API 2->>API 2: Validates token (audience=API 2), checks authorization
    API 2-->>BFF: Returns other resource data

    Note over BFF, SPA: BFF Returns Response
    BFF->>Browser: Returns combined/transformed response to original request
    Browser->>SPA: Delivers response data
Press "Alt" / "Option" to enable Pan & Zoom