How 2FA and Social Logins Work (Architectural Guide)

This guide describes the technical workflows of Two-Factor Authentication (2FA) and Social Logins inside the Fabrixly-IDS OIDC interaction engine, explaining how session state, tokens, and redirects are managed during multi-step logins.


Part A: Social Logins OIDC Workflow

Social Logins (Google, GitHub) hook directly into the OIDC interaction flow. Here is the step-by-step path from authorization redirect to interaction completion:

sequenceDiagram
    participant ClientApp as Client Application (SPA/Backend)
    participant IDS as Fabrixly-IDS (OIDC Issuer)
    participant UI as Login / Interaction Screen
    participant Google as Google OAuth Authority

    ClientApp->>IDS: GET /oidc/auth (OIDC Authorization Redirect)
    IDS->>UI: Redirect to /interaction/:uid (Consent/Login Screen)
    UI->>Google: Click Login → GET /api/auth/google?client_id=...&uid=:uid
    Google-->>IDS: Callback GET /api/auth/google/callback?code=...
    Note over IDS: Verifies Google profile, links/creates User record, creates session
    IDS->>UI: Redirect GET /interaction/:uid/google-callback?token=:jwtToken
    Note over UI: Verifies temporary JWT, sets active session, calls interactionFinished
    UI->>IDS: interactionFinished() callback
    IDS->>ClientApp: Redirect to Callback URI with Auth Code

1. Initiation

The client application redirects the user to /oidc/auth. The OIDC provider detects no active session and redirects the browser to the interaction page: /interaction/:uid.

2. Social Login Redirection

The interaction UI displays Google/GitHub buttons. Clicking a button triggers a query containing the OIDC session identifier (uid): GET https://ids.fabrixly.com/api/auth/google?client_id=your-client-id&uid=oidc-session-uid

3. Callback & User Provisioning

After authenticating at Google, Google callbacks to /api/auth/google/callback with state containing the uid.

  • Existing User: Links googleId if it is not already stored on the user's database record.
  • Just-in-Time (JIT) Provisioning: If the email doesn't exist, Fabrixly-IDS auto-registers the user under the client's parent organization.
  • Session Creation: The server creates a session and redirects the browser to: GET /interaction/:uid/google-callback?token=<signed-jwt-containing-userId>

4. Completing OIDC Flow

The interaction route (/:uid/google-callback) validates the temporary JWT token, marks the OIDC session login reference (amr: ['google']), and calls: provider.interactionFinished(req, res, { login: { accountId: userId } }) This redirects the user back to the client application with the standard OIDC authorization code.


Part B: Two-Factor Authentication (2FA) Workflow

2FA (password_and_otp) divides the login screen into a two-step verification process context-bound by the OIDC session.

1. Step 1: Password Verification

  1. The user enters their email and password on the login screen.
  2. The UI posts credentials to: POST /interaction/:uid/login.
  3. Upon matching the password hash, the backend:
    • Generates a cryptographically secure 6-digit OTP code.
    • Sends the code using the configured provider (SMTP or SMS).
    • Stores the intermediate auth state (e.g. is_password_verified: true) on the OIDC interaction session.

Returns:

{
  "status": "otp_required",
  "message": "Please enter the OTP verification code sent to your device."
}

2. Step 2: OTP Challenge

  1. The UI displays the OTP submission input box.
  2. The user submits the code: POST /interaction/:uid/verify-otp.
  3. The backend verifies the OTP code against expiration limits (default: 5 minutes):
    • If correct, it completes the session, registers the user login event in the audit logs, and calls interactionFinished to complete the OIDC auth code redirect.

Part C: Interaction Between Social Logins and 2FA

When a user authenticates via a social identity provider (Google/GitHub), standard credential challenges (password and OTP) are bypassed by default because the identity provider has already confirmed the authentication.

Enforcing Multi-Factor on Social Login

If your security policies mandate that social users must still complete a second-factor challenge (e.g., verifying a mobile OTP):

  1. Ensure enable_2fa: true is toggled on the user profile record.
  2. After the social callback completes /interaction/:uid/google-callback, the interaction controller detects enable_2fa: true on the user entity.
  3. Rather than finalizing the flow, the controller generates an OTP code, redirects the user to the /interaction/:uid/mfa challenge screen, and expects the user to verify the code before calling interactionFinished.

Subscribe to The Fabrixly Blog

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe