Hilton Login → Hilton Auth Server → Backend → Booking API (OAuth PKCE flow)
By Admin
•
November 15, 2025
Hilton Login → Hilton Auth Server → Backend → Booking API
With PKCE, annotations, and user actions shown.
Here is the corrected and updated flow, with the missing step added clearly showing WHERE the frontend sends the code_verifier to the backend.
IMPORTANT:Step 7 must include BOTH:
- authorization_code
- code_verifier
Otherwise the backend cannot complete Step 8.
I have updated Step 7 to include this.
UPDATED + CORRECTED FULL FLOW WITH code_verifier SENT TO BACKEND
┌─────────────────────────────────────────────────────────────┐
│ 0. HILTON WEBSITE │
│ (User just browsing normally) │
│ ❌ No PKCE generated at this point │
└─────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 1. USER CLICKS "LOGIN" or "VIEW RESERVATIONS" │
│ ✔ This action STARTS the OAuth login flow │
│ ✔ This is when PKCE must be generated │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 2. FRONTEND (React/Vue/JS) GENERATES PKCE │
│ ✔ code_verifier = random 43–128 chars │
│ ✔ code_challenge = SHA256(code_verifier) │
│ ✔ code_verifier stored in memory/sessionStorage on frontend │
│ │
│ ⚠ Backend DOES NOT know code_verifier yet │
│ PKCE is always generated inside the browser │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 3. FRONTEND REDIRECTS BROWSER TO AUTH SERVER │
│ GET https://login.hilton.com/authorize? │
│ client_id=hilton-app │
│ response_type=code │
│ code_challenge=XYZ123 (sent here) │
│ code_challenge_method=S256 │
│ redirect_uri=https://app.hilton.com/callback │
│ │
│ ✔ Front-channel browser redirect │
│ ✔ SAFE to send code_challenge (hash; cannot be reversed) │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 4. AUTH SERVER SHOWS LOGIN PAGE │
│ 5. USER ENTERS CREDENTIALS │
│ │
│ ✔ User interaction happens here │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 6. AUTH SERVER REDIRECTS BROWSER BACK │
│ https://app.hilton.com/callback?code=AUTH_CODE_123 │
│ │
│ ✔ Browser receives ONLY authorization_code │
│ ✔ Browser still has code_verifier locally │
│ ✔ No tokens exposed │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 7. FRONTEND SENDS BOTH TO BACKEND: │
│ │
│ POST /exchange_code │
│ { │
│ code: "AUTH_CODE_123", │
│ code_verifier: "ORIGINAL_CODE_VERIFIER" <── NEWLY ADDED │
│ } │
│ │
│ ✔ THIS is the step where backend receives the code_verifier │
│ ✔ code_verifier NEVER sent to auth server through browser │
│ ✔ Still no tokens in the browser │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 8. BACKEND SENDS TOKEN REQUEST TO AUTH SERVER │
│ │
│ POST https://login.hilton.com/token │
│ grant_type=authorization_code │
│ code=AUTH_CODE_123 │
│ code_verifier=ORIGINAL_CODE_VERIFIER <── Backend sends this │
│ client_id=hilton-app │
│ client_secret=xxxxx (confidential clients only) │
│ │
│ ✔ BACK-CHANNEL (server → server HTTPS) │
│ ✔ code_verifier now available because frontend sent it │
│ ✔ Backend performs full PKCE binding │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 9. AUTH SERVER VALIDATES PKCE │
│ │
│ SHA256(code_verifier) == code_challenge ? │
│ │
│ IF MATCH → returns tokens (BACK-CHANNEL ONLY): │
│ - access_token (JWT) │
│ - refresh_token │
│ - id_token │
│ │
│ ✔ Tokens NEVER travel through browser │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 10. BACKEND CREATES SESSION COOKIE │
│ │
│ ✔ Backend stores tokens securely │
│ ✔ Browser gets only a secure HttpOnly cookie │
│ ✔ Browser NEVER handles access_token │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 11. BROWSER CALLS BACKEND FOR DATA │
│ │
│ GET /my/reservations │
│ │
│ ✔ Backend uses access_token to call Booking API │
└──────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────┐
│ 12. BACKEND → BOOKING API USING ACCESS TOKEN │
│ │
│ GET /api/reservations │
│ Authorization: Bearer <access_token> │
│ │
│ ✔ Resource server validates JWT and returns reservation data │
└──────────────────────────────────────────────────────────────────────┘
