Authentication Strategy β€” GIW

Status: POC Β· Date: 2026-09-21 Authority: TASK ORDER β€” APPLY AUTH ARCHITECTURE GUARDRAILS, 21/09/2026

DIRECT GRANT / PASSWORD GRANT = POC-ONLY IMPLEMENTATION

Not a production architecture. Not a production Galaxy ID flow. Not a production employee authentication recommendation.

RFC 9700 (OAuth 2.0 Security Best Current Practice) states the password grant MUST NOT be used, and OAuth 2.1 removes it. No standards exception is claimed here. Direct Grant is used only as a constrained POC workaround for captive-portal UX validation. Production authentication architecture remains TBC and should prefer modern browser-based OIDC/federation where operationally feasible.


1. Two modes

Both are configured in the realm. Only Mode A is wired to the portal.

MODE A β€” POC LOCAL

Wi-Fi Portal / BFF
   β†’ Direct Grant (POST /token, grant_type=password)
   β†’ Keycloak
   β†’ HR Verification API          (employee path only)

Status: IMPLEMENTED / POC ONLY

Clients wifi-portal-api, wifi-portal-employee-api β€” both confidential
Customer grant_type=password
Registration client_credentials β†’ Admin API β†’ password
Employee grant_type=password + employeeId + citizenId β†’ custom employee-direct-grant flow β†’ Keycloak calls HR
Browser sees The portal only. One opaque sid cookie.
Why it exists To validate the captive-portal journey end to end without a redirect.

What it does not do: SSO, MFA, step-up, federation, credential isolation.

MODE B β€” PRODUCTION CANDIDATE

Wi-Fi Portal
   β†’ Authorization Code + PKCE
   β†’ Keycloak
   β†’ Enterprise IdP / Federation / MFA
   β†’ Keycloak
   β†’ Wi-Fi Portal

Status: PROPOSED / NOT IMPLEMENTED

Clients wifi-portal, wifi-portal-employee β€” public, PKCE S256 enforced
Flow employee-browser β†’ employee-verify-form β†’ giw-employee-verify
Present in the realm? Yes. Configured, importable, and exercised by earlier POC revisions.
Wired to the portal? No. Deliberately unused.
Why retained This is the path an Enterprise IdP federates into. ADR-003 recommends corporate IdP federation in place of CCCD; without this path that recommendation cannot be implemented without rebuilding the architecture.

Do not delete: employee-browser flow Β· employee-verify-form sub-flow Β· EmployeeVerifyAuthenticator Β· giw-employee-verify provider Β· the galaxy login theme and employee-verify.ftl Β· clients wifi-portal and wifi-portal-employee Β· their giw-identity scope attachment and flow binding override.

bootstrap reconciles both sets on every start, so Mode B stays working rather than rotting.

2. Comparison

Capability Direct Grant (Mode A, POC) Browser/OIDC (Mode B, production candidate)
Captive portal simplicity High TBC β€” must be validated against real CNA behaviour
SSO No Yes
MFA / step-up Limited / No Yes
Federation (Enterprise IdP, social) No Yes
Credential isolation Lower β€” the portal transits the password Better β€” the portal never sees it
CNA compatibility Better in this POC, on a laptop browser Must validate on real devices, real captive networks
Standards position RFC 9700: MUST NOT Recommended
Security / audit scope Wider β€” portal is in credential scope Narrower
Brand continuity No visible hand-off A visible hand-off, themeable
Production recommendation No Candidate

Two rows deserve care, because the POC has not earned them:

  • CNA compatibility. "Better in POC" means better on a desktop browser against a local stack. Nobody has tested either mode inside a real iOS or Android captive network assistant on an aircraft. Until that test exists, this is a hypothesis, not a finding.
  • Captive portal simplicity. Mode B's cell is TBC for the same reason.

3. Migration path, Mode A β†’ Mode B

Nothing below is built. It is recorded so the move is a change of route, not a rewrite.

Step What changes What does not
1 Portal adds /login/oidc β†’ redirect to wifi-portal client Entitlement, Session, HR, portal UI for every other screen
2 Portal adds /callback β†’ code + PKCE verifier exchange The establish() path: token β†’ entitlement β†’ session β†’ sid cookie
3 Employee journey points at wifi-portal-employee EmployeeVerification, the HR contract, CCCD handling
4 Keycloak adds the Enterprise IdP as an identity provider Claim contract: user_type, employee_verified, employee_ref, company
5 employee-browser flow gains an IdP redirector ahead of giw-employee-verify Everything downstream of the token
6 Direct Grant disabled on both API clients; EmployeeDirectGrantAuthenticator removed β€”

The reason this is cheap: the portal's establish() function takes a token and does everything after it. Whatever produced the token is interchangeable.

4. Security boundary

Who knows what. This is the property the BFF design buys, and it survives a move to Mode B.

Browser

Knows Holds Never
The portal host, and nothing else One opaque sid cookie β€” HttpOnly, SameSite=Strict, Max-Age=3600 An access token Β· a refresh token Β· an ID token
The Keycloak endpoint
The HR endpoint
The Entitlement endpoint
The Session endpoint

The sid is a UUID with no meaning outside the portal's in-memory map. HttpOnly keeps it away from script; SameSite=Strict means no cross-site request carries it.

Exception, POC demo aid: DEBUG_EXPOSE_TOKEN=1 returns the raw access token on GET /api/v1/auth/session, so an API client can be seeded during a demo. It is off by default and must stay off outside a laptop.

Portal / BFF

Does Does not
Holds tokens server-side only, in a map with a 1 h TTL reaped every 5 minutes Never persists a password β€” no store, no file, no database
Transits credentials in the POC Direct Grant flow Never persists a CCCD
Validates shape before calling anything (email format, password length, field presence) Never logs a credential β€” no log statement takes a password or a CCCD
Orchestrates: Galaxy ID β†’ Entitlement β†’ Session Never decides authentication
Never decides entitlement
Never touches a network device

On "clear sensitive values immediately after the request" β€” what is actually guaranteed.

JavaScript strings are immutable. A password or CCCD read from a request body cannot be zeroed; there is no memset available. What the code does instead:

  1. The value is read into a local variable and passed directly to the outbound request.
  2. It is never assigned to a field, a session object, a cache or a closure that outlives the request.
  3. It goes out of scope when the handler returns, and is left to the garbage collector.
  4. No log statement anywhere in the portal takes it as an argument.

Points 2–4 are enforceable and enforced. Point 1 is not a wipe, and this document will not claim it is. A language with controlled memory would do better; that is a real limitation of a Node BFF handling credentials, and one more reason Mode A is POC-only.

The same applies inside Keycloak: EmployeeVerification holds the CCCD in a local variable, hands it to HrVerificationClient, and never writes it to a field, a user attribute, an auth-session note, an event detail or a log line. HrVerificationClient logs e.getClass().getSimpleName() on failure, never e.getMessage(), because some transport stacks echo the request body into the exception message.

Authority map

System Authority over Never
Keycloak (Galaxy ID) Authentication Opens the network Β· decides entitlement
HR Verification API Employment status β€” is this an active, eligible employee Returns a profile Β· stores anything Β· is a system of record for identity
Entitlement Service Authorization β€” what access this subject may have Enforces Β· creates sessions
Session Service Enforcement β€” access state (CREATED/GRANTED/REVOKED/EXPIRED) Decides. POST /sessions/{id}/grant returns 422 without an entitlementId
Wi-Fi Portal / BFF Orchestration and presentation Decides anything

5. Decision record

Question Ref Status
Is Direct Grant acceptable beyond the POC? T-GRANT No. POC only.
What is the production auth architecture? β€” TBC / NOT APPROVED
If MFA is required, what carries the step-up? T-MFA TBC. Mode A cannot.
Corporate IdP federation for employees? ADR-003 PROPOSED. Requires Mode B.
Is CCCD acceptable in production? T-CCCD, ADR-003, D3 TBC. Requires Security + Legal/DPO + HR approval.
Does Mode A survive a real CNA on a real aircraft? β€” Untested.
Does Mode B survive a real CNA? β€” Untested.

6. Official status

Item Status
POC UX / API ACCEPTABLE FOR LOCAL DEMO
POC Identity PASS
Direct Grant POC ONLY
OIDC Browser / Federation PRODUCTION CANDIDATE / TBC
Production Auth Architecture NOT APPROVED / TBC
CCCD POC VERIFICATION INPUT ONLY. Production use requires Security + Legal/DPO + HR approval.

GIW POC Identity Platform Β· local demo Β· not production Β· generated from the repository