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.
Architecture
Section titled “Architecture”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 appFacebook OAuth credentials are stored in the core_conf table, configurable per deployment from the admin panel.
Database Schema
Section titled “Database Schema”facebook_account table
Section titled “facebook_account table”| Column | Type | Notes |
|---|---|---|
id | UUID | Primary key |
user_id | UUID | FK to user.id, unique, cascade delete |
facebook_id | String | Facebook’s unique user ID, unique |
email | String | Facebook email |
name | Option<String> | Display name |
picture_url | Option<String> | Profile picture URL |
created_at | Timestamptz | |
updated_at | Timestamptz |
core_conf additions
Section titled “core_conf additions”Two columns store the OAuth credentials:
facebook_oauth_app_id— your Facebook App IDfacebook_oauth_app_secret— the corresponding app secret
Configure these in Settings → System Config in the admin panel.
Authorization URL
Section titled “Authorization URL”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.
Callback Handler
Section titled “Callback Handler”GET /auth/facebook/callback is a raw Axum handler (not a Dioxus server function) because it receives query parameters directly from Facebook’s redirect.
-
CSRF validation — Decodes the
stateparameter, extracts the CSRF token, and compares it against thefacebook_oauth_csrfcookie. Returns 403 on mismatch. -
Token exchange — POSTs the authorization code to
https://graph.facebook.com/v21.0/oauth/access_tokenwith the app credentials. Receives anaccess_token. -
User info fetch — Queries the Facebook Graph API at
https://graph.facebook.com/me?fields=id,name,email,pictureusing the access token. -
User routing — Four scenarios, checked in order:
Scenario Condition Action Login facebook_accountexists byfacebook_idFind user, create session Auto-link (email) email_password_accountexists by emailCreate facebook_accountlinked to that userAuto-link (Google) google_accountexists by emailCreate facebook_accountlinked to that userSignup No matching account Create user + facebook_account, then create org or process invitation -
Session creation — Sets
session_tokencookie (HttpOnly, Secure) and clears the CSRF cookie. Redirects to/.
Error handling
Section titled “Error handling”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.
Data Types
Section titled “Data Types”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>,}Differences from Google OAuth
Section titled “Differences from Google OAuth”| Aspect | ||
|---|---|---|
| API version | v2 | v21.0 |
| User info source | JWT id_token claim decode | Graph API /me request |
| Token response | Returns id_token + access_token | Returns access_token only |
| Profile picture | picture string field in JWT | Nested picture.data.url object |
| Cross-provider linking | Links to email/password accounts | Links to email/password and Google accounts |
| Scope | openid email profile | email |
Key Files
Section titled “Key Files”| File | Purpose |
|---|---|
src/bases/auth/api/get_facebook_auth_url_api.rs | Generates authorization URL |
src/bases/auth/api/facebook_callback_handler.rs | Handles Facebook’s redirect callback |
src/bases/auth/types/facebook_oauth_types.rs | OAuth data types |
src/bases/auth/constants/facebook_oauth_constants.rs | URLs and cookie names |
src/bases/auth/conf/core/facebook_oauth_core_conf.rs | Loads credentials from core_conf |
migration/src/m20260318_120000_create_facebook_account_table.rs | facebook_account migration |
migration/src/m20260318_130000_core_conf_add_facebook_oauth_fields.rs | core_conf credential columns |
src/shared/components/facebook_sign_in_button_component.rs | Reusable Facebook sign-in button |
Frontend Sign-In Button
Section titled “Frontend Sign-In Button”The FacebookSignInButton component handles the client-side OAuth redirect flow.
| Prop | Type | Default | Purpose |
|---|---|---|---|
invitation_token | Option<String> | None | Passed through for invitation acceptance |
organization_name | Option<String> | None | Org name from the signup form |
label | String | "Continue with Facebook" | Button text |
Behavior
Section titled “Behavior”- User clicks → calls
get_facebook_auth_url_apiwith optionalinvitation_tokenandorganization_name - Receives
(auth_url, csrf_token)from the server - Sets the
facebook_oauth_csrfcookie via JavaScript (max-age 600s, SameSite=Lax) - Redirects the browser to
auth_url
The button renders with the Facebook “f” logo (#1877F2) and shows a loading spinner during redirect.
Where it appears
Section titled “Where it appears”- Login page (
login_card_component.rs) - Signup page (
signup_card_component.rs) — passesorganization_name - Invitation acceptance (
accept_invitation_card_component.rs) — passesinvitation_token
Shared OAuth Infrastructure
Section titled “Shared OAuth Infrastructure”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 genericcreate_provider_accountclosure.OAuthFlowState— Shared state struct encoded in thestateparameter for CSRF and flow context.