Skip to Content

Authentication flow

The vast majority of IBA members (~90%+) sign in with a standard username and password. Google and Facebook login are available too, but they’re an opt-in account-linking feature: a member must first create their account and sign in with username and password before they can connect a Google or Facebook identity.

This page describes all three flows in the order they actually matter: primary username/password login, OAuth login (only for members who linked a provider), and the account-linking flow itself.

Primary login — username + password

This is what nearly every member does, every time.

Key rules

  • Password storage — bcrypt hashes only; never plain text.
  • role_id gates sign-in — see member lifecycle. A member with role_id = 4 (pending email verification) can’t fully sign in; role_id = 2 (banned/deleted) is rejected without revealing whether the account exists.
  • Rate limiting — repeated failed logins are throttled per IP and per username to mitigate brute force.

Two-factor authentication (2FA)

After the password check, members with 2FA enabled must clear a second factor before a session is issued. Two distinct mechanisms exist:

  • Email / SMS one-time passcode (OTP) — for regular members who have opted in (members.two_fa = 1).
  • Authenticator-app TOTP — mandatory for the admin account (role_id = 1), which never falls through to the OTP path.

Mandatory 2FA for staff

Most members opt into 2FA voluntarily, but staff accounts are required to enable it. The requireTwoFa rule (computed on the member record in member/service and enforced in the web portal) is true when a member has not yet enabled 2FA (members.two_fa = 0) and they are either:

  • an instructor, trainer, or examiner (role_id 8 / 9 / 10) who currently holds instructor currency (currency_instructor = 1) — former staff who lapse back to being regular flyers lose that currency and correctly drop out of the requirement; or
  • the boss account (role_id 11) or a tunnel manager (role_id 12) — these are active staff who aren’t required to hold instructor currency, so they’re always required regardless of it.

Enforcement is a soft gate in the web portal: an eligible member who hasn’t enabled 2FA is redirected to their communication settings until they switch it on. Once enabled (two_fa = 1) the standard OTP gate below applies on every sign-in, web and mobile. The admin account (role_id = 1) is the separate, stricter case covered by Admin TOTP below.

When the OTP step applies

The OTP gate fires only when both are true:

  • members.two_fa = 1 (the member opted into 2FA), and
  • the member hasn’t completed 2FA within the last 8 hours (last_login is empty or older than 480 minutes).

So an opted-in member is challenged at most once per 8-hour window, not on every request.

OTP delivery and verification

Delivery channel is chosen automatically:

  • Email only when the member has a verified email but no verified phone.
  • Email by request when the client passes passcodeOption = 'email' and the email is verified.
  • SMS otherwise — sent to +<dialing-code><phone>. The SMS provider routes from the UK Twilio number for +44 recipients and the US number for everyone else. See SMS dialing code below.

OTP rules

  • 6-digit code — randomly generated, stored per member with an attempt counter.
  • 10-minute expiry — a code older than 10 minutes is rejected as expired.
  • Single-use — a correct code stamps last_login and is immediately deleted.
  • Send throttle — after 4 sends within 10 minutes, further sends are rate-limited.
  • Verification lock-out — at 5 validation attempts the stored code is discarded and the member must request a new one.
  • Masked recipient — the prompt shows a masked email/phone, never the full value.

SMS dialing code

The SMS recipient is built as +${members.country}${members.phone}. members.country stores the numeric dialing code (e.g. 1, 44), not an ISO code — the ISO code lives in members.country_code. A member whose members.country is 0 (never resolved) would produce an invalid +0… number and silently receive no SMS; that’s a data-integrity concern corrected outside the login flow, not a property of this code path.

Admin TOTP (role_id = 1)

The shared admin account must use an authenticator app (TOTP) and is never offered the email/SMS OTP path:

  • On first admin login, if TOTP isn’t configured the API returns requiresTotpSetup; setup returns a QR code plus one-time backup codes.
  • Subsequent logins return requiresTotp and require a current TOTP code (or a backup code) to complete sign-in.
  • TOTP setup, verification, and backup-code use are restricted to role_id = 1; any other role is rejected.

OAuth login (Google / Facebook)

Available only to members who have already linked a Google or Facebook identity to their account via the account-linking flow below. A member who has never linked a provider can’t sign in via OAuth — the “Sign in with Google / Facebook” buttons return them to the username/password form with a hint to connect a provider first.

The platform deliberately does not auto-create a member from an OAuth identity. A successful OAuth verification with no matching linked member returns the user to the username/password flow.

Account linking (enabling Google / Facebook login)

How a member opts in to OAuth login. Happens inside an authenticated session — the member must already be signed in via username/password.

Linking rules

  • One-way link. Linking adds an alternative sign-in path; it does not change the member’s username or password.
  • Linked identity is unique. A given Google or Facebook account can be linked to at most one IBA member. Re-using a provider account for a second IBA member is rejected with a 409.
  • Either provider, both, or neither. A member can link Google, Facebook, both, or neither — they’re independent toggles.
  • Unlinking is supported in account settings; it disables the corresponding OAuth login but doesn’t affect the underlying username/password sign-in.

Token refresh flow

Logout flow

Security considerations

  • Token expiry — access tokens expire after 15 minutes, refresh tokens after 7 days.
  • HTTPS only — all authentication traffic must use HTTPS.
  • Session storage — sessions stored in Redis with automatic expiry.
  • Rate limiting — login attempts (both username/password and OAuth) are rate-limited per IP and per account to prevent brute force.
  • CSRF protectionstate parameter used in OAuth flows to prevent CSRF attacks.
  • No account enumeration — login errors are deliberately generic (“invalid credentials”) and don’t reveal whether a username exists.
  • 2FA enforced server-side — there is no header or portal exemption; an opted-in member (or the admin account) must complete the second factor. OTP codes are single-use, expire after 10 minutes, and are both send-throttled and lock-out-protected.
Last updated on