API_BASE_URL is the externally reachable address of the FIM Agent backend. Examples:
| Scenario | Example callback URL |
|---|---|
| Local dev | http://localhost:8000/api/auth/oauth/github/callback |
| Dedicated API subdomain | https://api.yourdomain.com/api/auth/oauth/github/callback |
| Reverse-proxy (same domain) | https://yourdomain.com/api/auth/oauth/github/callback |
GitHub
Developer console: https://github.com/settings/developers- Click OAuth Apps → New OAuth App.
- Fill in:
- Application name — any name (e.g.
FIM Agent) - Homepage URL — your frontend URL (e.g.
https://yourdomain.com) - Authorization callback URL —
https://yourdomain.com/api/auth/oauth/github/callback
- Application name — any name (e.g.
- Click Register application, then click Generate a new client secret.
- Copy the Client ID and the generated Client Secret into your
.env.
read:user, user:email
GitHub accounts with a private primary email are handled correctly — FIM Agent always fetches the primary verified email from /user/emails, not the public profile email.
- Click + CREATE CREDENTIALS → OAuth client ID.
- If prompted, configure the OAuth consent screen first (set User Type to “External” for personal/public apps).
- Set Application type to Web application.
- Under Authorized redirect URIs, add:
- Click Create, then copy the Client ID and Client Secret.
openid, email, profile
Note: During development the consent screen will show a “This app is not verified” warning. You can proceed past it for testing. Publish the consent screen if you want to remove the warning for end users.
Discord
Developer console: https://discord.com/developers/applications- Click New Application and give it a name.
- In the left sidebar, click OAuth2.
- Under Redirects, click Add Redirect and enter:
- Copy the Client ID (shown at the top of the OAuth2 page) and click Reset Secret to reveal the Client Secret.
identify, email
Discord does not guarantee a verified email for all accounts. If a user has not verified their email with Discord, thenull. FIM Agent creates the account with a null email in that case — the user can add one later in Settings.
Feishu (Lark)
Developer console: https://open.feishu.cn/app- Click Create App → In-house app (自建应用). Company/enterprise accounts are required — Feishu OAuth is not available for personal accounts.
- Under Permissions & Scopes, search for and enable:
contact:user.email:readonly
- Under Security Settings → Redirect URL, add your callback URL:
- Copy the App ID and App Secret from the Credentials & Basic Info section.
contact:user.email:readonly
Note: Feishu usesApp ID/App Secretinstead of the standardClient ID/Client Secretnaming. The env var names reflect this:FEISHU_APP_IDandFEISHU_APP_SECRET.
Important: Feishu Email Behavior
The Feishu user info API (authen/v1/user_info) returns the user’s enterprise contact email (联系邮箱) — the address configured by the organization admin in the Feishu admin console. This is not the user’s personal Feishu login email.
Consequences:
- Users whose org admin has not configured a contact email will get an empty email field from the API, even though they have a valid Feishu account.
- Users on personal Feishu accounts (not part of an enterprise) will always get an empty email.
Account Binding Rules
Registered users can link additional OAuth providers from Settings → Account. The following rules apply when a user initiates a binding:General rule (GitHub, Google, Discord)
The email returned by the OAuth provider must match the FIM account’s registered email. This prevents accidentally linking another person’s social account to your FIM account. If the emails do not match, the binding is rejected with anemail_mismatch error.
Feishu exception
Because Feishu’s API returns the enterprise contact email rather than the login email, and that field is often empty for personal accounts or accounts in orgs where the admin has not configured it, the email-match check for Feishu follows a looser rule:- Both sides have an email → the emails must match (same check as other providers).
- Either side has no email (Feishu returned empty, or the FIM account has no email) → binding succeeds based on the ticket-based authentication alone.
Feishu login (no binding yet)
When a user logs in via Feishu for the first time (no existing binding):- FIM Agent looks for an existing account whose email matches the Feishu enterprise contact email.
- If a match is found, the Feishu account is auto-bound to that existing FIM account and the user is logged in.
- If no match (including when the email is empty), a new FIM account is created identified by the Feishu
open_id. The account will have a null email, which the user can fill in from Settings later.
Environment Variables Quick Reference
| Variable | Provider | Required | Description |
|---|---|---|---|
GITHUB_CLIENT_ID | GitHub | Both | GitHub OAuth App client ID |
GITHUB_CLIENT_SECRET | GitHub | Both | GitHub OAuth App client secret |
GOOGLE_CLIENT_ID | Both | Google OAuth 2.0 client ID | |
GOOGLE_CLIENT_SECRET | Both | Google OAuth 2.0 client secret | |
DISCORD_CLIENT_ID | Discord | Both | Discord OAuth2 application client ID |
DISCORD_CLIENT_SECRET | Discord | Both | Discord OAuth2 application client secret |
FEISHU_APP_ID | Feishu | Both | Feishu in-house app ID (note: not CLIENT_ID) |
FEISHU_APP_SECRET | Feishu | Both | Feishu in-house app secret |
FRONTEND_URL | All | Prod | Where the browser is redirected after OAuth completes (e.g. https://yourdomain.com) |
API_BASE_URL | All | Prod | Externally reachable backend URL, used to build callback URLs |
NEXT_PUBLIC_API_URL | All | Prod | Browser-side API URL for OAuth redirects — baked in at build time |
_ID and _SECRET (or _APP_ID and _APP_SECRET for Feishu) must be set together; setting only one has no effect.
See Environment Variables for full documentation ofFRONTEND_URL,API_BASE_URL, andNEXT_PUBLIC_API_URL.