Skip to content

Facebook OAuth

Loquent supports Facebook OAuth 2.0 via the authorization code flow, following the same architecture as Google OAuth. A single callback handler manages login, signup, invitation acceptance, and auto-linking of existing accounts (email/password or Google). The frontend provides a reusable sign-in button on all authentication pages.

Browser → get_facebook_auth_url_api → Facebook consent screen
→ Facebook redirects to /auth/facebook/callback
→ Token exchange → Graph API user info
→ Smart user routing (login / link / signup)
→ Session cookie → redirect to app

Facebook OAuth credentials are stored in the core_conf table, configurable per deployment from the admin panel.

ColumnTypeNotes
idUUIDPrimary key
user_idUUIDFK to user.id, unique, cascade delete
facebook_idStringFacebook’s unique user ID, unique
emailStringFacebook email
nameOption<String>Display name
picture_urlOption<String>Profile picture URL
created_atTimestamptz
updated_atTimestamptz

Two columns store the OAuth credentials:

  • facebook_oauth_app_id — your Facebook App ID
  • facebook_oauth_app_secret — the corresponding app secret

Configure these in Settings → System Config in the admin panel.

POST /auth/facebook/url generates the Facebook consent URL.

// Request
{
invitation_token: Option<String>,
organization_name: Option<String>,
}
// Response — (auth_url, csrf_token)
("https://www.facebook.com/v21.0/dialog/oauth?...", "a1b2c3d4...")

The server loads credentials from core_conf, generates a CSRF token (UUID v4), and encodes an OAuthFlowState as base64 in the state parameter. The frontend stores the CSRF token in a facebook_oauth_csrf cookie before redirecting.

GET /auth/facebook/callback is a raw Axum handler (not a Dioxus server function) because it receives query parameters directly from Facebook’s redirect.

  1. CSRF validation — Decodes the state parameter, extracts the CSRF token, and compares it against the facebook_oauth_csrf cookie. Returns 403 on mismatch.

  2. Token exchange — POSTs the authorization code to https://graph.facebook.com/v21.0/oauth/access_token with the app credentials. Receives an access_token.

  3. User info fetch — Queries the Facebook Graph API at https://graph.facebook.com/me?fields=id,name,email,picture using the access token.

  4. User routing — Four scenarios, checked in order:

    ScenarioConditionAction
    Loginfacebook_account exists by facebook_idFind user, create session
    Auto-link (email)email_password_account exists by emailCreate facebook_account linked to that user
    Auto-link (Google)google_account exists by emailCreate facebook_account linked to that user
    SignupNo matching accountCreate user + facebook_account, then create org or process invitation
  5. Session creation — Sets session_token cookie (HttpOnly, Secure) and clears the CSRF cookie. Redirects to /.

All failures redirect to /login?error=... (or /invite/accept/{token}?error=... if an invitation was in progress). If user or organization records were partially created, the handler rolls back by deleting them.

Types live in src/bases/auth/types/facebook_oauth_types.rs:

/// Query parameters Facebook sends to the callback URL.
struct FacebookCallbackParams {
code: String,
state: String,
}
/// Response from Facebook's token exchange endpoint.
struct FacebookTokenResponse {
access_token: String,
}
/// User info from the Facebook Graph API /me endpoint.
struct FacebookUserInfo {
id: String, // Facebook user ID
name: Option<String>,
email: String,
picture: Option<FacebookPicture>,
}
struct FacebookPicture {
data: FacebookPictureData,
}
struct FacebookPictureData {
url: String,
}

The OAuthFlowState struct is shared with Google OAuth:

struct OAuthFlowState {
csrf_token: String,
organization_name: Option<String>,
invitation_token: Option<String>,
}
AspectGoogleFacebook
API versionv2v21.0
User info sourceJWT id_token claim decodeGraph API /me request
Token responseReturns id_token + access_tokenReturns access_token only
Profile picturepicture string field in JWTNested picture.data.url object
Cross-provider linkingLinks to email/password accountsLinks to email/password and Google accounts
Scopeopenid email profileemail
FilePurpose
src/bases/auth/api/get_facebook_auth_url_api.rsGenerates authorization URL
src/bases/auth/api/facebook_callback_handler.rsHandles Facebook’s redirect callback
src/bases/auth/types/facebook_oauth_types.rsOAuth data types
src/bases/auth/constants/facebook_oauth_constants.rsURLs and cookie names
src/bases/auth/conf/core/facebook_oauth_core_conf.rsLoads credentials from core_conf
migration/src/m20260318_120000_create_facebook_account_table.rsfacebook_account migration
migration/src/m20260318_130000_core_conf_add_facebook_oauth_fields.rscore_conf credential columns
src/shared/components/facebook_sign_in_button_component.rsReusable Facebook sign-in button

The FacebookSignInButton component handles the client-side OAuth redirect flow.

PropTypeDefaultPurpose
invitation_tokenOption<String>NonePassed through for invitation acceptance
organization_nameOption<String>NoneOrg name from the signup form
labelString"Continue with Facebook"Button text
  1. User clicks → calls get_facebook_auth_url_api with optional invitation_token and organization_name
  2. Receives (auth_url, csrf_token) from the server
  3. Sets the facebook_oauth_csrf cookie via JavaScript (max-age 600s, SameSite=Lax)
  4. Redirects the browser to auth_url

The button renders with the Facebook “f” logo (#1877F2) and shows a loading spinner during redirect.

  • Login page (login_card_component.rs)
  • Signup page (signup_card_component.rs) — passes organization_name
  • Invitation acceptance (accept_invitation_card_component.rs) — passes invitation_token

Facebook OAuth reuses several helpers originally built for Google OAuth, now generalized:

  • handle_existing_user — Processes invitation (if present), finds the user’s member record, creates a session, and redirects. Used by both Google and Facebook callbacks.
  • handle_new_oauth_user — Creates a new user, calls a provider-specific account creator, seeds notification preferences, and handles org creation or invitation processing. Accepts a generic create_provider_account closure.
  • OAuthFlowState — Shared state struct encoded in the state parameter for CSRF and flow context.