Integration Guide
This guide explains how to integrate Fabi-SC ID authentication into your application.
Overview
The authentication flow works as follows:
- User clicks “Sign in with Fabi-SC ID” in your application
- User is redirected to Fabi-SC ID to log in (if not already) and grant permissions to your application
- User is redirected back to your callback URL with a one-time code
- Your server exchanges the code for a token
- Use the token to access user data via the API
Step 1: Redirect to Login
When a user wants to sign in, redirect them to:
https://id.fabi-sc.com/consent/{your-app-id}
Replace {your-app-id} with your application’s Client ID.
See the Branding Guide for official login buttons.
What Happens
- If the user is not logged in, they are prompted to log in first
- The user sees your application name, logo, and requested permissions
- The user can toggle optional permissions on/off
- The user clicks “Allow” or “Deny”
First Login vs Returning Users
- First time: User sees all requested scopes and must approve
- Already connected: If permissions haven’t changed, user is redirected immediately
- Re-consent needed: If you changed required scopes, user must approve again
Step 2: Handle the Callback
After the user clicks “Allow” (or “Deny”), they are redirected to your callback URL with a code parameter:
https://yourapp.com/callback?code=abc123...
Important:
- The code is single-use
- The code expires after 5 minutes
- If the user clicked “Deny”, they will not be redirected to your callback
Step 3: Exchange Code for Token
Exchange the one-time code for an access token by calling the exchange endpoint.
Request:
POST https://id.fabi-sc.com/api/v1/exchange
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"code": "abc123..."
}
Response:
{
"success": true,
"data": {
"token": "user-access-token",
"user_id": "derived-user-uuid",
"scopes": ["openid", "username", "email"]
}
}
The user_id returned is a derived ID unique to your application. See Privacy Considerations below.
Step 4: Use the Token
Store the token securely and use it to make API requests on behalf of the user.
See the API Reference for available endpoints.
Token Lifetime
Tokens expire based on your application’s configured lifetime (default: 1 day).
When a token expires:
- API requests return 401 Unauthorized
- Redirect the user to the login page to get a new token
You can validate a token at any time using the validate endpoint to check if it’s still valid.
Handling Re-consent
Sometimes users need to reconnect your application:
- You added new required scopes
- The user revoked a scope that your application requires
- You called the force-reconsent endpoint
When validating a token, check the reconsent flag in the response:
{
"success": false,
"error": "Re-consent required",
"reconsent": true
}
If reconsent is true, redirect the user to the login URL again.
Privacy Considerations
Derived User IDs
Fabi-SC ID provides your application with a derived user ID, not the user’s real ID.
- Each application receives a different ID for the same user
- IDs are deterministic (same user + same app = same derived ID)
- You cannot correlate users across different applications
- This protects user privacy
Minimal Data
Only request scopes you actually need. Users see all requested permissions and are more likely to trust applications that request minimal data.
Error Handling
All API responses follow this format:
{
"success": true|false,
"data": { ... } | null,
"error": "Error message" | null,
"reconsent": true|false
}
Common Errors
| Status | Error | Action |
|---|---|---|
| 401 | Invalid or missing API key | Check your API key |
| 403 | Domain not verified | Verify your domain |
| 403 | App banned | Contact support |
| 403 | Origin not allowed | Check allowed_origins setting |
| 400 | Invalid or expired code | Request a new code |
Example Flow
Here’s a complete example using Node.js with Express. The logic applies to any language or framework.
Important: The API key must never be exposed to the client. All API calls must be made from your server.
const express = require('express');
const app = express();
const APP_ID = 'your-app-id';
const API_KEY = 'your-api-key';
const API_BASE = 'https://id.fabi-sc.com/api/v1';
// 1. User clicks "Sign in" - redirect to Fabi-SC ID
app.get('/login', (req, res) => {
res.redirect(`https://id.fabi-sc.com/consent/${APP_ID}`);
});
// 2. User clicks Allow - handle the callback
app.get('/callback', async (req, res) => {
const { code } = req.query;
if (!code) return res.status(400).send('Missing code');
// 3. Exchange code for token
const response = await fetch(`${API_BASE}/exchange`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ code })
});
const result = await response.json();
if (!result.success) return res.status(401).send(result.error);
const { token, user_id, scopes } = result.data;
// 4. Store token and user_id in your database/session
req.session.userId = user_id;
req.session.token = token;
// 5. Fetch user data
const userResponse = await fetch(`${API_BASE}/user`, {
headers: {
'Authorization': `Bearer ${API_KEY}`,
'X-User-Token': token
}
});
const userData = await userResponse.json();
// 6. Redirect to dashboard
res.redirect('/dashboard');
});
app.listen(3000);