How to Use OTP-Only (Passwordless) Authentication with Fabrixly-IDS
Overview
OTP-only authentication allows users to log in without a password—they just enter their email or mobile number, receive a one-time passcode, and enter it to log in! It's secure and user-friendly.
Step 1: Configure Your Fabrixly-IDS Client
First, set up your OIDC client in Fabrixly-IDS:
Admin Console Configuration
- Open Fabrixly-IDS Admin Console → Clients → select or create your client
- Under Authentication Settings:
- Auth Mode: select
OTP Only - Enable Mobile Login: toggle on/off
- OTP Delivery Method: choose
Email,SMS, orBoth
- Auth Mode: select
- Save changes!
API Configuration
Authenticating API Requests
Management API endpoints (like /api/clients, /api/users, etc.) require administrative authentication. To call them:
- Include the Token in the Authorization Header: Add
-H "Authorization: Bearer <your-admin-jwt-token>"to your API calls.
Obtain an Admin JWT Token:
curl -X POST https://ids.fabrixly.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "your-admin-password"
}'
Note: This returns a JSON response containing a token.
curl -X POST https://ids.fabrixly.com/api/clients \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-admin-jwt-token>" \
-d '{
"client_name": "Passwordless App",
"redirect_uris": ["http://localhost:3003/callback"],
"response_types": ["code"],
"grant_types": ["authorization_code"],
"token_endpoint_auth_method": "client_secret_basic",
"auth_mode": "otp",
"otp_delivery_method": "email"
}'
User Login Flow
- User visits your app and clicks "Login"
- App redirects to Fabrixly-IDS login page (password field hidden)
- User enters email or mobile number and clicks "Send OTP"
- Fabrixly-IDS sends OTP via chosen delivery method(s)
- User receives OTP, enters it, clicks "Verify & Log In"
- OTP is validated, user is redirected back to your app with code
- App exchanges code for tokens and logs user in!
Example: Express + OTP-Only App
Create otp-only-app.js:
const express = require('express');
const session = require('express-session');
const { Issuer, generators } = require('openid-client');
const app = express();
const PORT = 3003;
app.use(session({
secret: 'another-super-secret-key',
resave: false,
saveUninitialized: true
}));
async function initClient() {
const issuer = await Issuer.discover('https://ids.fabrixly.com/oidc');
return new issuer.Client({
client_id: 'your-otp-client-id',
client_secret: 'your-otp-client-secret',
redirect_uris: ['http://localhost:3003/callback']
});
}
let client;
initClient().then(c => client = c);
app.get('/', (req, res) => {
if (req.session.user) {
res.redirect('/dashboard');
} else {
res.send(`
<h1>Passwordless Login Example</h1>
<a href="/login">Login with OTP</a>
`);
}
});
app.get('/login', (req, res) => {
req.session.state = generators.state();
req.session.nonce = generators.nonce();
const authUrl = client.authorizationUrl({
scope: 'openid profile email',
state: req.session.state,
nonce: req.session.nonce
});
res.redirect(authUrl);
});
app.get('/callback', async (req, res) => {
const params = client.callbackParams(req);
const tokenSet = await client.callback(
'http://localhost:3003/callback',
params,
{ state: req.session.state, nonce: req.session.nonce }
);
req.session.tokenSet = tokenSet;
req.session.user = await client.userinfo(tokenSet.access_token);
res.redirect('/dashboard');
});
app.get('/dashboard', (req, res) => {
if (!req.session.user) return res.redirect('/');
res.send(`
<h1>Welcome to Passwordless App!</h1>
<p>Hello ${req.session.user.email}!</p>
<p>Logged in without any password! 🎉</p>
<a href="/">Home</a>
`);
});
app.listen(PORT, () => console.log(`OTP-only app running on port ${PORT}`));
OTP Delivery Methods
- Email: Sends OTP to user's verified email address
- SMS: Sends OTP to user's verified mobile number (requires SMS provider set up)
- Both: Sends OTP to both email and SMS (user gets both, uses whichever they prefer)
OTP Settings
You can configure OTP behavior via environment variables (in .env file):
OTP_EXPIRY_MINUTES=5 # OTP expires after 5 minutes
OTP_LENGTH=6 # 6-digit OTP
Security Tips
- Short Expiry: Keep OTP expiry short (5‑10 minutes)
- Rate Limiting: Fabrixly-IDS automatically rate-limits OTP requests to prevent abuse
- HTTPS: Always use HTTPS in production
- Phone Verification: Require email/mobile verification before OTP login
Troubleshooting
- "No user found" error: Ensure user exists and has a verified email/mobile number
- OTP not received: Check spam folder (for email), or verify SMS provider settings (for SMS)
- "OTP invalid or expired": Request a new OTP
Next Steps
- Try using "Both" delivery method for redundancy
- Explore flexible authentication
- Enable 2FA for higher-security use cases